C#调用DLL,实在找不到问题出在哪里了

fengwanzk 2012-09-24 09:13:17
在网上看了许多关于C#调用C/C++编写的DLL文件的帖子,但是都没有能解决我的问题,有点抓狂了......

1. 目前的程序是在别人的程序的基础上进行的“修修补补”,该程序是使用DLL文件进行的二次开发。

2. 可能出问题的地方:
(2.1)C#调用的代码是:

[DllImport("MyFunction.dll",EntryPoint="GetPortInfo")]
public static extern UInt32 GetPortInfo(UInt32 Device, Byte Num, IntPtr pPortInfo);

(2.2)C代码是:

UInt32 GetPortInfo( UInt32 hDevice, unsigned char num, PortInfo& pPortInfo );

(2.3)其中,PortInfo数据结构是:
在C#中的写法:

[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++中的写法:

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是这样定义的:

IntPtr pPortInfo = Marshal.AllocHGlobal(40);

因此,我对C#该数据结构做了修改,去掉了“Pack=1”,并添加了填充字节:

[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)我把该部分程序换了一个位置进行测试。
我的程序的结构是“在第一个页面中点击进入按钮,进入第二页面”,而出错的部分正是在第二个页面中。
我把下面程序放入第一个页面中:

IntPtr pPortInfo = Marshal.AllocHGlobal(40);
GetPortInfo( UInt32 hDevice, unsigned char num, PortInfo& pPortInfo );
Marshal.FreeHGlobal(pPortInfo );

程序正常。再将其放入第二个页面,又出错了。

请教问题可能出在哪里?谢谢!
...全文
576 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
yanli19880419 2013-07-24
  • 打赏
  • 举报
回复
不知你的问题解决了没,我也与到同样的问题,目前不知如何解决,同样一个程序在一台电脑可以运行,在另一台电脑上会出现你那样的报错,而两台电脑安装的Vs是一样的。
xuan.ye 2012-09-26
  • 打赏
  • 举报
回复
C# 应该是不能调用非com 的dll组件。不知道那个dll是不是标准的com组件
fengwanzk 2012-09-26
  • 打赏
  • 举报
回复
我现在很怀疑是权限问题。
因为找不到解决方法,我只好新建一个工程,把原来的代码逐个拷贝进来,重点调试了报错部分的代码,结果一切正常了。
请教,我只是按照“添加”-->“新项”的方式,添加新的“aspx”文件进入原来的工程中,而原来的工程我也看了,似乎没有设置权限的地方。
到底是怎么了?
希望大家能赐教。我可以追加分数。
fengwanzk 2012-09-26
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
C# 应该是不能调用非com 的dll组件。不知道那个dll是不是标准的com组件
[/Quote]应该是吧。可以调用的
fengwanzk 2012-09-25
  • 打赏
  • 举报
回复
我用的是IIS5.1,该版本使用的是进程模型,而应用程序池是IIS6.0的概念。我再看看IIS陪置是否正确。
孟子E章 2012-09-25
  • 打赏
  • 举报
回复
一个工程的不同网页还有可能出现不同的访问权限吗?

一般是不会的。

你可以在网站使用的 应用程序池-标识-选择一个权限高的账户,如本地系统或者管理员帐户进行测试下
fengwanzk 2012-09-25
  • 打赏
  • 举报
回复
在哪里设置的权限?搜了一下没看明白
fengwanzk 2012-09-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
我的DLL文件放在bin目录下,应该没有问题吧?

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

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

(1)我把相同的dll文件放在我的程序的原始版本里的bin目录下,它可以正常运行。(当然,我一会儿去测试一下放在你说的那些目录下)
(2)当我把现在报错的地方的程序屏蔽掉后,后面那些对dll文件调用的部分挨个报这个相同的错误。所以,我怀疑是不是权限的问题啊。但是为什么放在第一个文件中,可以调用正常?放在第二个文件中就不行了呢?
另外,一个工程的不同网页还有可能出现不同的访问权限吗?我没有进行过这些设置啊,它的权限应该是一样的吧。
H_Gragon 2012-09-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
我的DLL文件放在bin目录下,应该没有问题吧?

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

Web程序最好放在System32目录 下,并注意,Web程序是匿名账户身份运行的,注意权限问题
[/Quote]
同意!
快乐的小二兔 2012-09-25
  • 打赏
  • 举报
回复
这个东西。。。。。只有P哥,版主等大神才能解决
c#调用c 的dll 很少啊
孟子E章 2012-09-25
  • 打赏
  • 举报
回复
我的DLL文件放在bin目录下,应该没有问题吧?

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

Web程序最好放在System32目录 下,并注意,Web程序是匿名账户身份运行的,注意权限问题
孟子E章 2012-09-25
  • 打赏
  • 举报
回复
在VS里面调试,是以当前登录计算机的账户运行的,一般是管理员组的权限,发布到iis,运行的账户就是匿名帐号(当然,iis值是可以设置其他身份账户的,默认情况下是匿名账户)了,这个你要清楚
fengwanzk 2012-09-25
  • 打赏
  • 举报
回复
我重新建了个工程,按照现在程序的结构写了个测试程序,结果一切正常。 我很怀疑是权限的问题,但是目前我正处于程序的调试阶段,而不是发布程序的阶段,而且我没有做任何权限方面的设置。调试程序也需要权限吗?

62,047

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧