关于c#中平台调用dll中方法的问题(P/Invoke相关)

时间:2022-08-28 07:56:38
改写之前项目的方法,源代码是VB的,现在要改成C#,引用的dll也不知道是什么语言封装的,C#中不能直接添加引用,以上是背景

VB中引用的源代码:
Declare Function Do_3Des Lib "3desmid.dll" (ByVal bType As Long, ByVal bMode As Long, ByVal sIn As String, ByVal sOut As String, ByVal datalen As Long, ByVal sKey As String, ByVal keylen As Long) As Long

项目中的声明和方法调用

Dim hexCardSnr As String
Dim tmpKey As String * 16
Dim SecretSys As String * 32
Dim iRet As Long

iRet = Do_3Des(0, 0, hexCardSnr, tmpKey, 8, SecretSys, 16)


在执行Do_3Des()方法的时候,hexCardSnr为16位的16进制转化的字符串,tmpKey和SecretSys均为空
执行后hexCardSnr的值不变,tmpKey为16位的字符串,SecretSys为32位的字符串(均不是空值)

我的改写,因为tmpKey和SecretSys的值都发生了改变,我这里就把类型设定为了StringBuilder,没有初始值。

[DllImport("3desmid.dll", EntryPoint = "Do_3Des", SetLastError = true,
            CharSet = CharSet.Ansi, ExactSpelling = false,
            CallingConvention = CallingConvention.Winapi)]
        public static extern Int16 Do_3Des(Int32 bType, Int32 bMode, string sIn, StringBuilder sOut, Int32 datalen, StringBuilder sKey, Int32 keylen);


方法调用

iRet = CardWriter.Do_3Des(0, 0, hexCardSnr1, tmpKey, 8, SecretSys, 16);

执行后hexCardSnr的值与VB中保持一致,但是tmpKey的值与VB中不一致,位数也是16位,SecretSys的值为空了

修改了很多次都没法获得一样的结果..各位大大能看出什么问题么,如果需要3desmid.dll方便研究,可以留下邮箱我发给你~谢谢了,分数有限,不好意思~

31 个解决方案

#1


tmpKey,SecretSys 改成 Char[] 试试。

#2


不行哦,声明 Char[] tmpKey = new Char[16]  
           Char[] SecretSys = new Char[32]  
返回值还是空的

#3


自己顶下~

#4


不懂VB,不过这种迁移多少可以这么做:

编译 VB 代码
将编译后的 assembly 用工具(如  Red Gate's Reflector)打开,把语言设置成 C#
把代码拷贝出来

#5


yangglemu@163.com
Dll发给我试试?

#6


DLL已发

#7


我认为问题也许出在hexCardSnr参数上,.net中string是unicode编码,vb中默认好象是vbFromUnicode什么的.
这样C#和vb中虽然显示同样的16位字串,但是传入dll函数中可能不是一样的编码序列.
试试从怎样能传入与vb中相同的字符编码序列这个角度着手有没有效果.

#8


我也试过把hexCardSnr用StringBuilder和Char[],但是都不行呃,返回值tmpKey始终对不起来,而生成的密钥SecretSys压根就是空值..很郁闷

#9


挺有意思的问题,能把dll文件发给我看看?
su_miao@hotmail.com

#10


引用 9 楼 su_miao 的回复:
挺有意思的问题,能把dll文件发给我看看?
su_miao@hotmail.com

已经发了

#11


为什么这么简单的方法不试一下呢?

引用 4 楼 yizhili 的回复:
编译 VB 代码
将编译后的 assembly 用工具(如 Red Gate's Reflector)打开,把语言设置成 C#
把 C# 代码拷贝出来

#12


用Depends看了下,貌似3desmid.dll中引用到了两个Dll文件:
mwrf32.dll
multicoder.dll
楼主一并发下? 

#13


[DllImport("3desmid.dll", EntryPoint = "Do_3Des", SetLastError = true,
            CharSet = CharSet.Ansi, ExactSpelling = false,
            CallingConvention = CallingConvention.Winapi)]
        public static extern Int32 Do_3Des(Int32 bType, Int32 bMode, string sIn, StringBuilder sOut, Int32 datalen, StringBuilder sKey, Int32 keylen);

//StringBuilder 必须先初始化
StringBuilder sOut=new StringBuilder(16);
StringBuilder sKey=new StringBuilder(32);
CardWriter.Do_3Des(0, 0, hexCardSnr1, sOut, 8, sKey, 16);


#14


问题解决了吗?你发给我的第二封邮件是乱码,不明白什么意思.

#15


引用 14 楼 su_miao 的回复:
问题解决了吗?你发给我的第二封邮件是乱码,不明白什么意思.

啊,是乱码么,我再发你一次吧

#16


引用 12 楼 yangglemu 的回复:
用Depends看了下,貌似3desmid.dll中引用到了两个Dll文件:
mwrf32.dll
multicoder.dll
楼主一并发下?

也发你了~

#17


引用 11 楼 yizhili 的回复:
为什么这么简单的方法不试一下呢?


引用 4 楼 yizhili 的回复:
编译 VB 代码
将编译后的 assembly 用工具(如 Red Gate's Reflector)打开,把语言设置成 C#
把 C# 代码拷贝出来


我没学过VB,这个VB源代码由一个主程序和几个子程序(生成DLL后供主程序调用)构成,可以具体问下怎么实现上面说的操作么?

#18


这个事你要改的 DLL 吧?直接把 DLL 拖到 Reflector 里就可以了
那个工具是针对 .NET assembly 的,用哪个语言没关系

引用 17 楼 tobyseven7 的回复:
引用 11 楼 yizhili 的回复:
为什么这么简单的方法不试一下呢?


引用 4 楼 yizhili 的回复:
编译 VB 代码
将编译后的 assembly 用工具(如 Red Gate's Reflector)打开,把语言设置成 C#
把 C# 代码拷贝出来


我没学过VB,这个VB源代码由一个主程序和几个子程序(生成DLL后供主程序调用)构成,可以具体问下怎么……

#19


Reflector 我昨天尝试过了,那个只能反编译.NET的DLL吧,我这个dll我用软件测出来是C++写的,用到了3DES加密解密,另外这个dll的方法还引用了一个叫做MultiCoder.dll里面的方法..现在头很大
引用 18 楼 yizhili 的回复:
这个事你要改的 DLL 吧?直接把 DLL 拖到 Reflector 里就可以了
那个工具是针对 .NET assembly 的,用哪个语言没关系


引用 17 楼 tobyseven7 的回复:

引用 11 楼 yizhili 的回复:
为什么这么简单的方法不试一下呢?


引用 4 楼 yizhili 的回复:
编译 VB 代码
将编译后的 assembly 用工具……

#20


在VB里面测试也没有得出正确的结果啊.
输入是"0B008FB5F4FF704A",
输出tmpKey好象是个随机的16位串,SecretSys总是空.

#21


郁闷了..
引用 20 楼 su_miao 的回复:
在VB里面测试也没有得出正确的结果啊.
输入是"0B008FB5F4FF704A",
输出tmpKey好象是个随机的16位串,SecretSys总是空.

#22


可能我的代码没问题,但是引用的dll没找全 =。=

#23


你们原先的项目源代码不是VB吗,为什么我得不到正确的结果?

另外VB升.net,其实用vs打开vb项目可以直接把VB代码转换成vb.net代码,但是象这类调用dll的方法一般都不容易直接转换成功.

#24


该回复于2011-02-17 11:22:59被版主删除

#25


原来的代码是 VB 不是 VB.NET ?那么我弄错了。
我的意思是反编译原来的代码,应为 Reflector 可以反编译成不同语言,就可以直接得到 C# 代码了。

引用 19 楼 tobyseven7 的回复:
Reflector 我昨天尝试过了,那个只能反编译.NET的DLL吧,我这个dll我用软件测出来是C++写的,用到了3DES加密解密,另外这个dll的方法还引用了一个叫做MultiCoder.dll里面的方法..现在头很大
引用 18 楼 yizhili 的回复:
这个事你要改的 DLL 吧?直接把 DLL 拖到 Reflector 里就可以了
那个工具是针对 .NET assembly ……

#26


实在不行就只有大杀器 managed C++ 了

#27


那项目什么文档都没有,我之前也没用VB编程过,接手的时候是一头雾水,我发你其中一个模块的源代码吧
引用 23 楼 su_miao 的回复:
你们原先的项目源代码不是VB吗,为什么我得不到正确的结果?

另外VB升.net,其实用vs打开vb项目可以直接把VB代码转换成vb.net代码,但是象这类调用dll的方法一般都不容易直接转换成功.

#28


哦,那个项目能运行起来吗,结果正常吗?我觉得现在好象不是代码的问题,是不是缺少其它的什么组件.

#29


项目正常的,因为已经使用好几年了,现在需要进行一些业务上的变更,所以最好改写下
引用 28 楼 su_miao 的回复:
哦,那个项目能运行起来吗,结果正常吗?我觉得现在好象不是代码的问题,是不是缺少其它的什么组件.

#30


试了下,参数用char*,sKey总为空
改用BSTR,不为空,但和你的结果不一样,象序列号一样的32个字符,还有小横杠的
建议楼主发到VB版块去问问(注意不是VB.Net,是VB6)

#31


感谢各位,我选择在原来代码的基础上进行修改,可能是代码环境的缘故

#1


tmpKey,SecretSys 改成 Char[] 试试。

#2


不行哦,声明 Char[] tmpKey = new Char[16]  
           Char[] SecretSys = new Char[32]  
返回值还是空的

#3


自己顶下~

#4


不懂VB,不过这种迁移多少可以这么做:

编译 VB 代码
将编译后的 assembly 用工具(如  Red Gate's Reflector)打开,把语言设置成 C#
把代码拷贝出来

#5


yangglemu@163.com
Dll发给我试试?

#6


DLL已发

#7


我认为问题也许出在hexCardSnr参数上,.net中string是unicode编码,vb中默认好象是vbFromUnicode什么的.
这样C#和vb中虽然显示同样的16位字串,但是传入dll函数中可能不是一样的编码序列.
试试从怎样能传入与vb中相同的字符编码序列这个角度着手有没有效果.

#8


我也试过把hexCardSnr用StringBuilder和Char[],但是都不行呃,返回值tmpKey始终对不起来,而生成的密钥SecretSys压根就是空值..很郁闷

#9


挺有意思的问题,能把dll文件发给我看看?
su_miao@hotmail.com

#10


引用 9 楼 su_miao 的回复:
挺有意思的问题,能把dll文件发给我看看?
su_miao@hotmail.com

已经发了

#11


为什么这么简单的方法不试一下呢?

引用 4 楼 yizhili 的回复:
编译 VB 代码
将编译后的 assembly 用工具(如 Red Gate's Reflector)打开,把语言设置成 C#
把 C# 代码拷贝出来

#12


用Depends看了下,貌似3desmid.dll中引用到了两个Dll文件:
mwrf32.dll
multicoder.dll
楼主一并发下? 

#13


[DllImport("3desmid.dll", EntryPoint = "Do_3Des", SetLastError = true,
            CharSet = CharSet.Ansi, ExactSpelling = false,
            CallingConvention = CallingConvention.Winapi)]
        public static extern Int32 Do_3Des(Int32 bType, Int32 bMode, string sIn, StringBuilder sOut, Int32 datalen, StringBuilder sKey, Int32 keylen);

//StringBuilder 必须先初始化
StringBuilder sOut=new StringBuilder(16);
StringBuilder sKey=new StringBuilder(32);
CardWriter.Do_3Des(0, 0, hexCardSnr1, sOut, 8, sKey, 16);


#14


问题解决了吗?你发给我的第二封邮件是乱码,不明白什么意思.

#15


引用 14 楼 su_miao 的回复:
问题解决了吗?你发给我的第二封邮件是乱码,不明白什么意思.

啊,是乱码么,我再发你一次吧

#16


引用 12 楼 yangglemu 的回复:
用Depends看了下,貌似3desmid.dll中引用到了两个Dll文件:
mwrf32.dll
multicoder.dll
楼主一并发下?

也发你了~

#17


引用 11 楼 yizhili 的回复:
为什么这么简单的方法不试一下呢?


引用 4 楼 yizhili 的回复:
编译 VB 代码
将编译后的 assembly 用工具(如 Red Gate's Reflector)打开,把语言设置成 C#
把 C# 代码拷贝出来


我没学过VB,这个VB源代码由一个主程序和几个子程序(生成DLL后供主程序调用)构成,可以具体问下怎么实现上面说的操作么?

#18


这个事你要改的 DLL 吧?直接把 DLL 拖到 Reflector 里就可以了
那个工具是针对 .NET assembly 的,用哪个语言没关系

引用 17 楼 tobyseven7 的回复:
引用 11 楼 yizhili 的回复:
为什么这么简单的方法不试一下呢?


引用 4 楼 yizhili 的回复:
编译 VB 代码
将编译后的 assembly 用工具(如 Red Gate's Reflector)打开,把语言设置成 C#
把 C# 代码拷贝出来


我没学过VB,这个VB源代码由一个主程序和几个子程序(生成DLL后供主程序调用)构成,可以具体问下怎么……

#19


Reflector 我昨天尝试过了,那个只能反编译.NET的DLL吧,我这个dll我用软件测出来是C++写的,用到了3DES加密解密,另外这个dll的方法还引用了一个叫做MultiCoder.dll里面的方法..现在头很大
引用 18 楼 yizhili 的回复:
这个事你要改的 DLL 吧?直接把 DLL 拖到 Reflector 里就可以了
那个工具是针对 .NET assembly 的,用哪个语言没关系


引用 17 楼 tobyseven7 的回复:

引用 11 楼 yizhili 的回复:
为什么这么简单的方法不试一下呢?


引用 4 楼 yizhili 的回复:
编译 VB 代码
将编译后的 assembly 用工具……

#20


在VB里面测试也没有得出正确的结果啊.
输入是"0B008FB5F4FF704A",
输出tmpKey好象是个随机的16位串,SecretSys总是空.

#21


郁闷了..
引用 20 楼 su_miao 的回复:
在VB里面测试也没有得出正确的结果啊.
输入是"0B008FB5F4FF704A",
输出tmpKey好象是个随机的16位串,SecretSys总是空.

#22


可能我的代码没问题,但是引用的dll没找全 =。=

#23


你们原先的项目源代码不是VB吗,为什么我得不到正确的结果?

另外VB升.net,其实用vs打开vb项目可以直接把VB代码转换成vb.net代码,但是象这类调用dll的方法一般都不容易直接转换成功.

#24


该回复于2011-02-17 11:22:59被版主删除

#25


原来的代码是 VB 不是 VB.NET ?那么我弄错了。
我的意思是反编译原来的代码,应为 Reflector 可以反编译成不同语言,就可以直接得到 C# 代码了。

引用 19 楼 tobyseven7 的回复:
Reflector 我昨天尝试过了,那个只能反编译.NET的DLL吧,我这个dll我用软件测出来是C++写的,用到了3DES加密解密,另外这个dll的方法还引用了一个叫做MultiCoder.dll里面的方法..现在头很大
引用 18 楼 yizhili 的回复:
这个事你要改的 DLL 吧?直接把 DLL 拖到 Reflector 里就可以了
那个工具是针对 .NET assembly ……

#26


实在不行就只有大杀器 managed C++ 了

#27


那项目什么文档都没有,我之前也没用VB编程过,接手的时候是一头雾水,我发你其中一个模块的源代码吧
引用 23 楼 su_miao 的回复:
你们原先的项目源代码不是VB吗,为什么我得不到正确的结果?

另外VB升.net,其实用vs打开vb项目可以直接把VB代码转换成vb.net代码,但是象这类调用dll的方法一般都不容易直接转换成功.

#28


哦,那个项目能运行起来吗,结果正常吗?我觉得现在好象不是代码的问题,是不是缺少其它的什么组件.

#29


项目正常的,因为已经使用好几年了,现在需要进行一些业务上的变更,所以最好改写下
引用 28 楼 su_miao 的回复:
哦,那个项目能运行起来吗,结果正常吗?我觉得现在好象不是代码的问题,是不是缺少其它的什么组件.

#30


试了下,参数用char*,sKey总为空
改用BSTR,不为空,但和你的结果不一样,象序列号一样的32个字符,还有小横杠的
建议楼主发到VB版块去问问(注意不是VB.Net,是VB6)

#31


感谢各位,我选择在原来代码的基础上进行修改,可能是代码环境的缘故