NET执行BAT,DLL (转)

本文介绍了一种通过批处理文件和命令行来实现DLL文件的注册与解除注册的方法,并涉及了文件的删除与复制操作。

Process.Start(@"D:/Root/***/***/bin/Debug/***.bat");
Process.Start(
"cmd.exe","/c  regsvr32  "+path) 
***.bat内容:

regsvr32 
/s/%windir%/system32/***.dll
del 
***.dll %windir%/system32/***.dll
copy jmail.dll 
%windir%/system32
regsvr32 
/%windir%/system32/***.dll

 

 

 

原址:http://www.cnblogs.com/houhou/archive/2006/12/22/600138.html

<think>我们正在处理用户关于“如何从批处理文件调用DLL”或“DLL入口点解释”的查询。 根据用户意图,我们需要解释如何从批处理文件(.bat)调用动态链接库(DLL)以及DLL入口点的概念。 首先,需要明确:批处理文件(BAT)本身不能直接调用DLL函数,因为BAT是脚本,而DLL包含需要由程序加载的编译代码。 但是,可以通过以下间接方式实现: 1. 使用rundll32.exe:这是Windows提供的一个实用程序,专门用于运行DLL中的函数。 2. 编写一个中间程序(如C/C++、C#等)来调用DLL,然后在批处理中运行该程序。 关于DLL入口点:每个DLL可以有一个可选的入口点函数(通常命名为DllMain),它在DLL被加载或卸载时由系统调用。 步骤: 一、使用rundll32.exe调用DLL函数 语法:rundll32.exe <dll文件名>,<入口函数名> [参数] 注意:该函数必须具有特定的调用约定(stdcall),并且函数原型需为: void CALLBACK FunctionName(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow); 或类似的格式(实际上参数可以自定义,但必须与调用约定匹配,且rundll32.exe会传递一个窗口句柄、实例句柄、命令行字符串和显示命令)。 示例:假设有一个MyDll.dll,其中有一个导出函数MyFunction,那么可以这样调用: rundll32.exe MyDll.dll,MyFunction 二、通过编写中间程序调用DLL 如果DLL中的函数不是上述格式,或者需要更复杂的交互,则可以编写一个小程序(例如用C++编写一个控制台程序)来调用DLL中的函数,然后在批处理中运行该程序。 三、DLL入口点(DllMain)解释 当DLL被加载到进程的地址空间时,系统会调用DLL的入口点函数(如果存在)。函数原型如下: BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); 参数说明: hinstDLLDLL模块的句柄。 fdwReason:调用原因,可以是以下值之一: DLL_PROCESS_ATTACH:进程加载DLL DLL_THREAD_ATTACH:线程创建时 DLL_THREAD_DETACH:线程退出时 DLL_PROCESS_DETACH:进程卸载DLL lpvReserved:保留参数。 注意:在DllMain中应避免进行复杂的初始化或调用其他DLL,因为可能会导致死锁或不可预知的行为。 四、创建可被rundll32调用的DLL 为了演示,我们可以创建一个简单的DLL,其中包含一个符合rundll32调用约定的函数。 示例(C++): 1. 使用__declspec(dllexport)导出函数。 2. 使用extern "C"来避免名称修饰(这样函数名就不会被改变)。 3. 使用调用约定(如WINAPI,即__stdcall)。 代码示例: #include <windows.h> extern "C" __declspec(dllexport) void WINAPI MyEntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { MessageBox(NULL, lpszCmdLine, "From DLL", MB_OK); } // 可选的DllMain BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } 编译这个DLL后,就可以在批处理中调用: rundll32.exe MyDll.dll,MyEntryPoint "Hello, World!" 五、注意事项 - 使用rundll32.exe时,函数名区分大小写,并且必须与DLL导出表中的名称完全一致(可以使用工具如Dependency Walker查看导出函数)。 - 如果函数名有@后缀(表示参数字节数),在rundll32命令中也需要加上(例如:MyFunction@16)。 - 参数传递:rundll32.exe会将逗号后的所有内容作为命令行参数传递给函数(作为lpszCmdLine参数),因此如果需要传递多个参数,需要在函数内部解析字符串。 六、替代方案 如果DLL函数不是为rundll32设计的,那么可能需要使用其他方法,如: - 使用脚本语言(如VBScript、PowerShell)调用DLL。 - 使用Python等语言编写脚本,通过ctypes调用DLL。 但是,用户特别提到了批处理文件,所以我们主要介绍rundll32方法。 根据以上内容,我们可以组织回答。</think>### 如何从批处理文件调用DLLDLL入口点解释 #### 一、通过批处理文件调用DLL的方法 批处理文件(.bat)本身无法直接调用DLL函数,但可通过以下两种方式间接实现: 1. **使用`rundll32.exe`(推荐方法)** Windows系统自带`rundll32.exe`工具,专门用于执行DLL中的导出函数。语法格式: ```bat rundll32.exe <DLL文件名>,<函数名> [参数] ``` **示例**: 假设有`MyLib.dll`导出函数`ShowDialog`,批处理调用方式: ```bat rundll32.exe MyLib.dll,ShowDialog "Hello World" ``` **要求**: - 目标函数必须是`__stdcall`调用约定 - 函数原型需匹配: ```c void CALLBACK FunctionName(HWND hwnd, HINSTANCE hinst, LPCSTR lpszCmdLine, int nCmdShow); ``` - 函数名需在DLL中显式导出(通过`.def`文件或`__declspec(dllexport)`) 2. **通过中间可执行程序** 编写一个C/C++或C#程序调用DLL函数,在批处理中启动程序: ```bat @echo off MyDllCaller.exe "function_param" ``` --- #### 二、DLL入口点机制详解 每个DLL可以包含一个可选的入口点函数`DllMain`,在特定事件发生时被操作系统自动调用。 **函数原型**: ```c BOOL WINAPI DllMain( HINSTANCE hinstDLL, // DLL模块句柄 DWORD fdwReason, // 调用原因代码 LPVOID lpvReserved // 保留参数 ); ``` **调用原因(fdwReason)**: | 代码值 | 触发场景 | 典型操作 | |----------------------|----------------------------|----------------------------| | `DLL_PROCESS_ATTACH` | DLL被加载到进程内存 | 初始化全局变量/资源 | | `DLL_PROCESS_DETACH` | DLL从进程卸载 | 清理资源/保存状态 | | `DLL_THREAD_ATTACH` | 新线程创建 | 初始化线程局部存储(TLS) | | `DLL_THREAD_DETACH` | 线程终止 | 清理线程相关资源 | **重要注意事项**: 1. 入口点函数应保持简单,避免复杂初始化或调用其他DLL 2. 当`fdwReason = DLL_PROCESS_ATTACH`时返回`FALSE`会导致加载失败 3. 多线程环境下需注意同步问题 4. 可通过`/ENTRY`链接器选项自定义入口点名称[^2] --- #### 三、完整实现示例 **DLL代码(C++)**: ```cpp #include <windows.h> extern "C" __declspec(dllexport) void ShowDialog(HWND hwnd, HINSTANCE hinst, LPSTR cmd, int show) { MessageBox(NULL, cmd, "DLL Message", MB_OK); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) { switch (reason) { case DLL_PROCESS_ATTACH: // 初始化代码 break; case DLL_PROCESS_DETACH: // 清理代码 break; } return TRUE; } ``` **批处理调用示例**: ```bat @echo off rundll32.exe MyLib.dll,ShowDialog "Called from batch file!" ``` --- #### 四、常见问题解决 1. **错误提示"未找到入口点"** - 检查函数名是否完全匹配(大小写敏感) - 使用`dumpbin /exports MyLib.dll`验证导出函数名 - 确保函数使用`extern "C"`防止名称修饰 2. **参数传递限制** `rundll32`仅支持单字符串参数,需在DLL函数内解析: ```c // 示例:解析逗号分隔参数 char* param1 = strtok(cmd, ","); char* param2 = strtok(NULL, ","); ``` 3. **替代方案** 复杂场景建议使用: - PowerShell:`[System.Reflection.Assembly]::LoadFile()` - Python:`ctypes.CDLL()` - VBScript:`CreateObject("WScript.Shell").Run()`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值