700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > C#调用PB生成dll详解

C#调用PB生成dll详解

时间:2020-01-16 05:56:04

相关推荐

C#调用PB生成dll详解

前言:调用dll时,需要先问清楚dll是由什么语言编译的,要不然方向错了会有很多无用功

试错过程:

直接引用出错:“…不是规范的COM组件”DllImportm方式

[DllImport("yhinterface.dll", EntryPoint = "f_sblwsk", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]public static extern void f_sblwsk(string hospitalComb, ref object ret);

更详细的可见c#调用外部dll

使用以上方法遇到的报错

直接引用时,报错“尝试写入或读取受保护的内存,这通常是指内存已损坏”DllImport时,报错无法找到方法入口无法加载该模块

解决方案思路:

最开始由于不知道dll是pb生成的,误当作c++生成的,所以当报错无法找到入口时,就怀疑提供方给错dll了,当时接口文档也没有说清楚,就一直在找这个问题。后来注册了该dll,把相关的依赖项放进与exe同级目录下,就可以直接引用进去了之后直接调用的时候,需要new一个对象,用过两种方式 常见new

COClass_n_yhinterface b = new COClass_n_yhinterface();

反射

```csharpprivate object Invoke(string lpFileName, string Namespace, string ClassName, string lpProcName, object[] ObjArray_Parameter){try{// 载入程序集Assembly MyAssembly = Assembly.LoadFrom(lpFileName);Type[] type = MyAssembly.GetTypes();foreach (Type t in type){// 查找要调用的命名空间及类if (t.Namespace == Namespace && t.Name == ClassName){// 查找要调用的方法并进行调用MethodInfo m = t.GetMethod(lpProcName);if (m != null){object o = Activator.CreateInstance(t);return m.Invoke(o, ObjArray_Parameter);}else Console.WriteLine(" 装载出错 !");}}}catch (System.NullReferenceException e){Console.WriteLine(e.Message);}//catchreturn (object)0;}

以上方法仍然报“…内存损坏”

开始怀疑dll不是c++编译的,于是找反编译工具尝试

我找了两种,一种是depends22_x86,一种是pb反编译工具;通过depends22_x86可以看到dll的函数入口,并没有需要的函数,反编译工具编译出pb程序以后,就开始找新方向了;

pb的dll注册:需要pb运行环境,PB环境变量不需要配,把PB的支持库文件放到system32里就行了;也可以安装一下powerbuilder;或者把pb的*.dll和.exe放一起就可以跑PB程序了

参考:

C#调用PB写的com组件dll

C#WEBSERVICE调用PB生成的DLL

出结果以后还需注意

m_Com_Document.InvokeMember("f_sblwsk", BindingFlags.InvokeMethod, null, objDoc, new object[] {hospitalComb, RetStr });

这种方式,如果函数方法是出参ref或者out 类型时,参数值并未发生变化

解决方案:

object[] args = new object[2];string RetStr = "123";args[0] = hospitalComb;args[1] = RetStr;ParameterModifier pMod = new ParameterModifier(2);pMod[1] = true;ParameterModifier[] mods = {pMod };Type m_Com_Document = Type.GetTypeFromProgID("PB90.n_yhinterface");object objDoc = Activator.CreateInstance(m_Com_Document);object tempObj = m_Com_Document.InvokeMember("f_sblwsk", BindingFlags.InvokeMethod, null, objDoc, args,mods,null,null);Console.WriteLine("args[1]:" + Convert.ToString(args[1]));Console.WriteLine("RetStr:" + Convert.ToString(RetStr));Console.WriteLine("tempObj:" + Convert.ToString(tempObj));RetStr = Convert.ToString(args[1]);string[] datas = RetStr.Split('|');Console.WriteLine("datas[0]:" + datas[0]);

参考:

使用数组

使用ParameterModifier

以上,解决

后续需要加强的部分:

反射值类型和引用类型,值的变化wcf和wpf的理解以上的理解会造成,有时已经找到答案了,因为认知缺陷就把正确答案pass掉了,也做了很多无用功,看网上的资料时,遇到别人的解决方案,需要耐心验证,不要走马观花

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。