System.TypeLoadException:无法加载类型“x”;来自汇编“y”

发布于 2024-11-05 16:34:11 字数 3032 浏览 3 评论 0原文

我正在尝试将一个程序从 VB6 移植到 C#,该程序读取二进制文件并解析它。我没有收到编译时错误或警告,但是当我尝试运行它时,在它进入 Main() 之前,它会抛出异常

System.TypeLoadException was unhandled
  Message=Could not load type 'Conversion.DataStructures.ClientOld' from assembly
     'SandboxConsole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because
     it contains an object field at offset 1 that is incorrectly aligned or overlapped
     by a non-object field.
  Source=SandboxConsole
  TypeName=Conversion.DataStructures.ClientOld
  StackTrace:
       at sandbox.Program.Main(String[] args)
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

这是旧 VB6 代码的示例

Private Type SrcClientOld
    Active As String * 1            '0
    titleLength As Byte             '1
    title As String * 8             '2
    lastNameLength As Byte          '10
    LastName As String * 25         '11
    (...)
    AddedBy As String * 3           '369
    junk7 As String * 22            '372
End Type                            '394

这是我的 C# 代码 经过一番谷歌搜索

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
struct ClientOld
{
    [FieldOffset(0)]
    public byte Active;

    [FieldOffset(1)]
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string Title;

    [FieldOffset(10)]
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string LastName;

    (...)

    [FieldOffset(368)]
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string AddedBy;

    [FieldOffset(372)]
    [MarshalAs(UnmanagedType.LPArray, SizeConst = 22)]
    public byte[] Unknown7;
}

后,我认为我缺少 Pack = 1 但添加它并没有解决我的问题。

关于做什么还有其他建议吗?

编辑:

第一个字符是一个字节长,这里是文件中第一条记录的十六进制转储

A.Dr.......Smith....................
41 03 44 72 2E 00 00 00 00 00 05 53 6D 69 74 68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|  |  |                       |  ^LastName
|  |  ^title                  ^lastNameLength
|  ^titleLength
^Active

编辑2: 将我的代码更改为以下内容以消除所有其他可能的错误,它仍然给我相同的异常,

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
struct ClientOld
{
    [FieldOffset(0)]
    public byte Active;

    [FieldOffset(1)]
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string Title;
}

我尝试了 fieldoffset(1) 和 2,但都不起作用。

I am trying to port a program from VB6 to C# that reads in a binary file and parses it. I get no compile time errors or warnings however when I try to run it, before it even enters Main() it throws the exception

System.TypeLoadException was unhandled
  Message=Could not load type 'Conversion.DataStructures.ClientOld' from assembly
     'SandboxConsole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because
     it contains an object field at offset 1 that is incorrectly aligned or overlapped
     by a non-object field.
  Source=SandboxConsole
  TypeName=Conversion.DataStructures.ClientOld
  StackTrace:
       at sandbox.Program.Main(String[] args)
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

Here is a sample of the old VB6 code

Private Type SrcClientOld
    Active As String * 1            '0
    titleLength As Byte             '1
    title As String * 8             '2
    lastNameLength As Byte          '10
    LastName As String * 25         '11
    (...)
    AddedBy As String * 3           '369
    junk7 As String * 22            '372
End Type                            '394

And here is my C# code I wrote

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
struct ClientOld
{
    [FieldOffset(0)]
    public byte Active;

    [FieldOffset(1)]
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string Title;

    [FieldOffset(10)]
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string LastName;

    (...)

    [FieldOffset(368)]
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string AddedBy;

    [FieldOffset(372)]
    [MarshalAs(UnmanagedType.LPArray, SizeConst = 22)]
    public byte[] Unknown7;
}

After some googleing I thought that it was that I was missing the Pack = 1 but adding that did not solve my issue.

Any other suggestions on what to do?

EDIT:

The first charater is one byte long, here is a hex dump of the first record in the file

A.Dr.......Smith....................
41 03 44 72 2E 00 00 00 00 00 05 53 6D 69 74 68 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|  |  |                       |  ^LastName
|  |  ^title                  ^lastNameLength
|  ^titleLength
^Active

EDIT2:
Changing my code to the following to strip out all other possible errors it is still giving me the same exception

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
struct ClientOld
{
    [FieldOffset(0)]
    public byte Active;

    [FieldOffset(1)]
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string Title;
}

I tried both fieldoffset(1) and 2 and neither work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

趴在窗边数星星i 2024-11-12 16:34:12

我认为

Active As String * 1

会转换为

Char,

在 Unicode 语言中它不是 1 个字节,因此下一个字段偏移量不应该是 1,而可能是 7(如果我正确理解了以下内容的话):

说明:

这里是理解字符串的关键:当我们编写代码时:

Dim str As String str = "help" 我们是
未定义 Unicode 字符数组
本身。我们正在定义一个成员
称为 BSTR 的数据类型,它很短
对于基本字符串。 BSTR 实际上是
指向以 null 结尾的 Unicode 的指针
前面带有 a 的字符数组
4 字节长度字段。

编辑:

根据您的转储,第二个成员似乎应该具有 [FieldOffset(2)],因为如果没有,它将与前一个成员重叠。 (编辑误报,我见过有 03 的地方有 00)。

I think that

Active As String * 1

translates to

Char

which in a Unicode language is not 1 byte, so the next field offset should not be 1, but probably 7 if I understood the following correctly:.

Explanation:

Here is the key to understanding strings: when we write the code:

Dim str As String str = "help" we are
not defining a Unicode character array
per se. We are defining a member of a
data type called BSTR, which is short
for Basic String. A BSTR is, in fact,
a pointer to a null-terminated Unicode
character array that is preceeded by a
4-byte length field.

Edit:

By your dump it seems that the second member should have [FieldOffset(2)] because if not it would overlap on the previous member. (edit false alarm, I have seen a 00 where there is a 03).

北恋 2024-11-12 16:34:12

从我看来,您混淆了“Active”和“TitleLength”的声明,这似乎完全被跳过了。

From what I see, you confused the declarations of "Active" and "TitleLength" which seems to be skipped completely..

难理解 2024-11-12 16:34:12

尝试使用 IntPtr 而不是字符串,然后调用 Marshall.PtrToStringAnsi

您需要保留旧代码的确切布局才能使此转换正常进行。二进制文件将以上次保存的格式存储,因此您必须准确地重现它,即使这意味着到处使用字节和字节数组。

如果您想使用新布局,则可以使用旧布局创建一个版本,将它们加载到新格式的副本值,然后使用新格式将它们保存回来。从那时起,您可以使用新布局加载它们。在这种情况下,您对新格式的选择是无穷无尽的。

Try using an IntPtr instead of a string, and then call Marshall.PtrToStringAnsi

You will need to retain the exact layout of the old code in order for this conversion to work. The binary is going to be stored in the format that it was last saved in, so you have to reproduce it exactly, even if that means using bytes and byte arrays everywhere.

If you want to use your new layout instead, you can create a version with the old layout, load them up copy values over to your new format and then save them back out with the new format. From then on you can load them up with your new layout instead. With that scenario your options are endless for your new format.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文