读书人

C#调用DLL实在找不到有关问题出在哪

发布时间: 2012-10-13 11:38:17 作者: rapoo

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 很少啊
[解决办法]
探讨
我的DLL文件放在bin目录下,应该没有问题吧?

DllImport会按照顺序自动去寻找的地方:
1、exe所在目录
2、System32目录
3、环境变量目录

Web程序最好放在System32目录 下,并注意,Web程序是匿名账户身份运行的,注意权限问题

[解决办法]
C# 应该是不能调用非com 的dll组件。不知道那个dll是不是标准的com组件

读书人网 >asp.net

热点推荐