首页 新闻 会员 周边

C# 动态调用非托管dll,能获取dll指针,使用GetProcAddress方法无法获取函数指针

0
悬赏园豆:10 [已关闭问题] 关闭于 2016-01-07 10:54
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Runtime.InteropServices;//加载非托管dll(跨平台dll)的调用类库
using System.ComponentModel;//显示win32错误代码提示
namespace DllHandle
{
   public class NotHostingDLLHandler
    {
       //kernel32.dll是Windows 9x/Me中非常重要的32位动态链接库文件,属于内核级文件。
       //它控制着系统的内存管理、数据的输入输出操作和中断处理,当Windows启动时,kernel32.dll就驻留在内存中特定的写保护区域,使别的程序无法占用这个内存区域。
        //LoadLibrary:传入dll路径,返回dll的实例指针
       [DllImport("Kernel32.dll")]
       private static extern IntPtr LoadLibrary(string path);
       //GetProcAddress:,参数lib为LoadLibrary()方法返回的值,FunName方法名,返回dll中指定的方法委托
       [DllImport("Kernel32.dll")]
       private static extern IntPtr GetProcAddress(IntPtr lib, string FunName);

       [DllImport("kernel32.dll")]
       public static extern bool FreeLibrary(IntPtr lib);


       private IntPtr libr;//指针或句柄


       public NotHostingDLLHandler(string path)
       {
           libr = LoadLibrary(path);//加载非托管dll的加载
       }

       public Delegate Invoke(string funName, Type type)
       {
           Delegate d = null;
           try
           {
               IntPtr api = GetProcAddress(libr, funName);
               d = (Delegate)Marshal.GetDelegateForFunctionPointer(api, type);//把非托管函数转化为委托
           }
           catch (Exception)
           {
               Console.WriteLine(new Win32Exception().Message);
           
           }

           return d;
       }

       ~NotHostingDLLHandler()//按位取反~
       {
           FreeLibrary(libr);
       }

      

   }
}
非托管dll处理类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using DllHandle;
using System.Reflection;//加载托管dll(非跨平台dll)的调用类库
using System.Runtime.InteropServices;

using System.IO;

namespace DllHelper
{
    class Program
    {

        public delegate  bool DBConnect();//如果需要执行的函数有参数,可对之进行声明。
        static void Main(string[] args)
        {
 
            int index = AppDomain.CurrentDomain.BaseDirectory.IndexOf(@"\bin");
            string path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, index) + "\\Dlls\\zlDrugPacker.dll";
         //  Assembly ab = DllHandler.GetUrlAssembly(path);//获取指定路径的dll对象,这里加载的是托管的dll,不是第三方的,而是.net自带的,调用方式与是否注册没关系
            //zlDrugPacker.clsDrugPacker model = new zlDrugPacker.clsDrugPacker();
            //model.DBConnect();
          

            NotHostingDLLHandler notHostdll = new NotHostingDLLHandler(path);
            
            DBConnect dbconnect = (DBConnect)notHostdll.Invoke("DBConnect", typeof(DBConnect));
           
            //show();



            Console.ReadLine();


        }
    }
}
调用代码

 

问题:IntPtr api = GetProcAddress(libr, funName);//函数指针获取为0,libr的dll地址是获取到的。

其中zlDrugPacker.dll为我的VB6的非托管代码

Lasthelloworld的主页 Lasthelloworld | 初学一级 | 园豆:92
提问于:2015-11-23 17:12
< >
分享
所有回答(1)
0

P/invoke上有这个例子,http://www.pinvoke.net/default.aspx/kernel32/GetProcAddress.html

VB6的代码是32位的,你的托管程序是64位的吧

2012 | 园豆:21230 (高人七级) | 2015-11-23 17:43

感谢你的回复,这里我的系统确定是32位的系统,在这里我的dll文件中有个函数名叫:DBConnect(),名字是没有写错的。

奇怪的是:网上我下载了其他的demo调用我的dll文件时都出现GetProcAddress方法返回值为0的情况,而他们的demo调用自己的非托管dll能成功调用。

支持(0) 反对(0) Lasthelloworld | 园豆:92 (初学一级) | 2015-11-23 17:46

@Lasthelloworld: VB我不太熟,是否函数的导出不对,使用depends.exe看看dll的输出信息,或者查查该函数的stdcall cdcall之类的导出函数用法

支持(0) 反对(0) 2012 | 园豆:21230 (高人七级) | 2015-11-23 17:49

@2012: 好的,我刚才已经打开了但是第一次用denpends.exe,先研究下

支持(0) 反对(0) Lasthelloworld | 园豆:92 (初学一级) | 2015-11-23 17:55
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册