从C#向dll传递固定长度字符串时获取AccessViolationException
我有以下(VB6?)代码可以在VBA for Excel中完美工作。我正在使用的dll(x.dll)对我来说是一个“黑匣子”。我不知道它是用什么写的,不管是不是非托管的。从历史技术的角度来看,我对它知之甚少。我只知道这个函数在从Excel VBA调用时可以工作,而在从C#调用它时,我无法同样地让它工作,我认为我应该能够。同样,dll使用并更改了c.b128的值从C#向dll传递固定长度字符串时获取AccessViolationException,c#,excel,dllimport,stringbuilder,access-violation,C#,Excel,Dllimport,Stringbuilder,Access Violation,我有以下(VB6?)代码可以在VBA for Excel中完美工作。我正在使用的dll(x.dll)对我来说是一个“黑匣子”。我不知道它是用什么写的,不管是不是非托管的。从历史技术的角度来看,我对它知之甚少。我只知道这个函数在从Excel VBA调用时可以工作,而在从C#调用它时,我无法同样地让它工作,我认为我应该能够。同样,dll使用并更改了c.b128的值 'In VBA for excel the value inside "c.b128" is changed from '" 12345
'In VBA for excel the value inside "c.b128" is changed from
'" 1234567890123456789012345678901234567890123456789012345678901234567890123456789 "
'to
'" 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 123456789 "
Excel代码的VBA
我试图在.NET中实现同样的功能,但在返回“returndllspace(-1,-1,c,d);”时出错 尝试读取或写入受保护内存的[…]中发生system.accessviolationexception类型的未处理异常。其他内存已损坏 我需要将其转换为.NET,然后得到一个AccessViolationException。我到处都读到StringBuilders保留的内存可以被C#中的DLL访问。我试过“ref StringBuilder”,我试过使用byte[],我试过使用不安全的描述符,我不明白。另外,如果有一种方法可以让我使用IDE查看内存中发生的更多事情,这也会对我有所帮助。我可以在本地和监视窗口中看到我的所有变量,但我看不到,也不知道如何查看有关抛出异常的更多详细信息。我正在Win32位操作系统机器上使用Visual Studio Express 2013 for Windows桌面 这是我的c代码的一个片段
C#代码片段
VBA代码清楚地表明,您拥有的实际上是一个包含固定长度字符串的结构。这意味着
StringBuilder
是错误的类型。您应改为使用:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct k128
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string b128;
}
另外,据我所知,VBA默认使用ByRef
。因此,C#宣言应该是:
[DllImport(@"x.dll")]
private static extern int dllSpace(
ref int aInfo,
ref int bVec,
ref k128 cQry,
ref k128 dErr
);
现在,ref k128
与容量为128的StringBuilder
编组时具有相同的内存布局,因此您可以更方便地切换回:
[DllImport(@"x.dll")]
private static extern int dllSpace(
ref int aInfo,
ref int bVec,
StringBuilder cQry,
StringBuilder dErr
);
尝试捕获Win32Exception
catch(Win32Exception w)
然后可以调用var e=w.GetBaseException()
获取有关异常的更多详细信息。感谢您对@vendettamit的响应,我遇到了问题。感谢您对@vendettamit的响应,我遇到了问题。public int StartTheDataSpace(){//我还没有完全准备好这里…//实际上有一个数组,整数通过该数组传递int[]try1={0,-1,-1,2,0,0,0,0};StringBuilder c=new StringBuilder(128);StringBuilder d=new StringBuilder(128);c.Append(“1234567890134[…]”);try{return dllSpace(try1[1],try1[1],c,d);}catch(System.ComponentModel.Win32Exception ex){Console.WriteLine(ex.Data);return-1;}
以上代码对我无效。。。我想我知道如何实现try-catch…在这里我想我尝试了每种组合。谢谢David Heffernan,我很不好意思地说我已经在这个问题上工作了很多天了。我只是在两个整数声明前面添加了ref,dllSpace返回0,这是“无错误”响应。再次感谢。
[DllImport(@"x.dll")]
private static extern int dllSpace(
ref int aInfo,
ref int bVec,
ref k128 cQry,
ref k128 dErr
);
[DllImport(@"x.dll")]
private static extern int dllSpace(
ref int aInfo,
ref int bVec,
StringBuilder cQry,
StringBuilder dErr
);