none
powershell cmdlet DllImport C\C++ 结构体, 嵌套Union(联合体)问题! RRS feed

  • 问题

  • 最近做一个PowerShell的项目, 其中做了很多了cmdlet命令, 为实现一些功能, 自己又做了不少C的方法封在DLL里, 供C#调用.其中有这样一个结构:

    typedef struct _ABOUT_INFO_OBJ
             {
                 ULONG    nLicenseType;

                 union
                 {
                      ULONG    nClientCount;
                      ULONG    nErrorCode;
                 };

                 CHAR pchSerialNo[64];

                 union
                 {
                      struct 
                      {
                           INT  nDaysLeft;
                      }Trial;

                      struct 
                      {
                           CHAR pchName[64];
                           CHAR pchCompName[256];

                           union
                           {
                               INT  nDaysLeft;
                           }TimeLimit;

                           union
                           {
                           }Infinite;
                      }Registed;
                 };
             } ABOUT_INFO_OBJ, *PABOUT_INFO_OBJ;

    我用C#是这样封的:

          [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
            public struct ABOUT_INFO_OBJ
             {
                 [FieldOffset(0)]
                 public UInt32 nLicenseType;

                 [FieldOffset((int)(sizeof(UInt32)))]
                 public UnionPart_1 m_UnionPart_1;

                 [FieldOffset((int)(sizeof(UInt32) * 2))]
                 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
                 public string pchSerialNo;

                 [FieldOffset((int)(sizeof(UInt32) * 2) + 64)]
                 public UnionPart_2 m_UnionPart_2;
             }

        [StructLayout(LayoutKind.Explicit, Size = (int)(sizeof(int)))]
            public struct UnionPart_1
            {
                [FieldOffset(0)]
                public UInt32 nClientCount;

                [FieldOffset(0)]
                public UInt32 nErrorCode;
            }

            [StructLayout(LayoutKind.Explicit, Size = (int)(64 + 256 + sizeof(Int32)))]
            public struct UnionPart_2
            {
                [FieldOffset(0)]
                public UnionPart_2_1 Trial;

                [FieldOffset(0)]
                public UnionPart_2_2 Registed;
            }

            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct UnionPart_2_1
            {
                public Int32 nDaysLeft;
            }

            [StructLayout(LayoutKind.Sequential, Pack = 2)]
            public struct UnionPart_2_2
            {
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
                public string pchName;

                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
                public string pchCompName;

                public UnionPart_2_2_1 TimeLimit;

                public UnionPart_2_2_2 Infinite;
            }

            [StructLayout(LayoutKind.Explicit, Size = (int)(sizeof(int)))]
            public struct UnionPart_2_2_1
            {
                [FieldOffset(0)]
                public int nDaysLeft;
            }

            [StructLayout(LayoutKind.Explicit, Size = 0)]
            public struct UnionPart_2_2_2
            {
            }

    随后我将用C#做好的cmdlet DLL文件Add到本地powershell环境中, (Add-PSSnapin xxxxx.PowerShell.Commands), 此时报了个错:

    Add-PSSnapin : 未能从程序集“xxxxxPowerShell, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中加载类型“UnionPart_2”,因为它在 0 偏移位置处包含一个对象字段,该字段已由一个非对象字段不正确地对齐或重叠。
    所在位置 行:1 字符: 1
    + Add-PSSnapin xxxxx.PowerShell.Commands
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [Add-PSSnapin], TypeLoadException
        + FullyQualifiedErrorId : System.TypeLoadException,Microsoft.PowerShell.Commands.AddPSSnapinCommand

    问题就在名为 UnionPart_2 的机构体, 把它注释掉, powershell就正常添加模块了.  以往我也定义过这种嵌套的Union(联合体), 想请大家帮我看看问题出在那里, 是用C#定义嵌套的结构体不对, 还是powershell里有限制?


    2013年7月9日 11:44

全部回复