C#调用DLL,实在找不到问题出在哪里了
在网上看了许多关于C#调用C/C++编写的DLL文件的帖子,但是都没有能解决我的问题,有点抓狂了......
1. 目前的程序是在别人的程序的基础上进行的“修修补补”,该程序是使用DLL文件进行的二次开发。
2. 可能出问题的地方:
(2.1)C#调用的代码是:
- C# code
[DllImport("MyFunction.dll",EntryPoint="GetPortInfo")]public static extern UInt32 GetPortInfo(UInt32 Device, Byte Num, IntPtr pPortInfo);(2.2)C代码是:
- C/C++ code
UInt32 GetPortInfo( UInt32 hDevice, unsigned char num, PortInfo& pPortInfo );
(2.3)其中,PortInfo数据结构是:
在C#中的写法:
- C# code
[StructLayout(LayoutKind.Sequential,Pack=1)]public struct port{ [MarshalAs(UnmanagedType.ByValArray,SizeConst=6)] public Byte[] mac; [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public Byte[] ip; [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public Byte[] mask; [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public Byte[] gage; [MarshalAs(UnmanagedType.U4)] public Uint32 ArpReply; [MarshalAs(UnmanagedType.U4)] public Uint32 IcmpReply; [MarshalAs(UnmangeddType.U1)] public Byte IgmpEnable; [MarshalAs(UnmangeddType.U1)] public Byte MultiPauseEnable; [MarshalAs(UnmangeddType.U1)] public Byte DirectPauseEnable; [MarshalAs(UnmanagedType.ByValArray,SizeConst=6)] public Byte[] UserDefAddr;}在C++中的写法:
- C/C++ code
struct PortInfo{ unsigned char mac[6]; unsigned char ip[4]; unsigned char mask[6]; unsigned char gate[6]; ArpReplayEnum ArpReply; IcmpReplyEnum IcmpReply; unsigned char IgmpEnable; unsigned char MultiPauseEnable; unsigned char DirectPauseEnable; unsigned char UserDefAddr[6];}3. 当调用该函数时报出的错误是:
用户代码未处理System.AccessViolationException
Message="尝试读取或者写入受保护的内存。这通常指示其他内存已损坏。
4. 碰到这个问题后,我先是上网搜索,有不少这样的帖子,我进行了一系列的排错:
(4.1)硬件损坏;
该程序是一个利用C#进行二次开发的程序。我的机子上正好有改程序C++发行版软件,在硬件平台上运行后,一切正常,因此,我觉得可以排除这个可能性。
(4.2)DLL文件传入的参数类型与C#本身的数据类型有矛盾;
这是我看到的网上最流行的说法之一。
在我的电脑上保存有“目前我修改的这个程序”的原始版本,我运行原始版本的程序,没有出错。我有找了身边做这方面工作的同事帮我看了一下,认为参数没有问题。
(4.3)DLL文件放置的位置不正确。
我的DLL文件放在bin目录下,应该没有问题吧?
(4.4)DLL文件本身有问题。
我运行原始版本的C#程序,没有出错,我想应该可以排除当前的这个错误的可能性了吧?
(4.5)访问权限的问题。
我对比了原始版本的C#程序,和我现在的这个的Web配置文件,是一样的(因为实际上我是直接拷贝了原来的那个程序,然后再拷贝的程序上进行的修改)。因此,这个方面是否没有问题了?
(4.6)C++中的结构体的大小与C#中结构体的大小不一致。
我用VC6测试了一下:
sizeof(port) = 40;
在C#中,传递的参数IntPtr pPortInfo是这样定义的:
- C# code
IntPtr pPortInfo = Marshal.AllocHGlobal(40);
因此,我对C#该数据结构做了修改,去掉了“Pack=1”,并添加了填充字节:
- C# code
[StructLayout(LayoutKind.Sequential)]public struct port{ [MarshalAs(UnmanagedType.ByValArray,SizeConst=6)] public Byte[] mac; [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public Byte[] ip; [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public Byte[] mask; [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public Byte[] gage; public UInt16 pad1; [MarshalAs(UnmanagedType.U4)] public Uint32 ArpReply; [MarshalAs(UnmanagedType.U4)] public Uint32 IcmpReply; [MarshalAs(UnmangeddType.U1)] public Byte IgmpEnable; [MarshalAs(UnmangeddType.U1)] public Byte MultiPauseEnable; [MarshalAs(UnmangeddType.U1)] public Byte DirectPauseEnable; [MarshalAs(UnmanagedType.ByValArray,SizeConst=6)] public Byte UserDefAddr; public UInt16 pad2; public Byte pad2;}
此时,该结构体在C#中也是40个字节了。
(4.7)我把该部分程序换了一个位置进行测试。
我的程序的结构是“在第一个页面中点击进入按钮,进入第二页面”,而出错的部分正是在第二个页面中。
我把下面程序放入第一个页面中:
- C# code
IntPtr pPortInfo = Marshal.AllocHGlobal(40);GetPortInfo( UInt32 hDevice, unsigned char num, PortInfo& pPortInfo );Marshal.FreeHGlobal(pPortInfo );
程序正常。再将其放入第二个页面,又出错了。
请教问题可能出在哪里?谢谢!
[解决办法]
我的DLL文件放在bin目录下,应该没有问题吧?
DllImport会按照顺序自动去寻找的地方:
1、exe所在目录
2、System32目录
3、环境变量目录
Web程序最好放在System32目录 下,并注意,Web程序是匿名账户身份运行的,注意权限问题
[解决办法]
这个东西。。。。。只有P哥,版主等大神才能解决
c#调用c 的dll 很少啊
[解决办法]
[解决办法]
C# 应该是不能调用非com 的dll组件。不知道那个dll是不是标准的com组件