我创建了一个DLL,并希望在Windows上使用rundll32.exe命令执行其中一个功能。
使用rundll32.exe,它可以从命令行正确运行;但是,我想从一个单独的程序中调用它(rundll32.exe)。由于我正在使用的基础库(Easyhook)中存在32/64位兼容性问题,因此我无法直接从代码中调用该函数。
下面是我在尝试运行dll函数时使用的:
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi));
LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe";
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc";
BOOL cpRes = CreateProcess(application,
cmd,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi);
if(cpRes == 0) {
cout << "ERROR\n";
cout << GetLastError() << endl;
} else {
cout << "DLL Launched!" << endl;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
我的控制台的输出始终为
DLL Launched
;但是,我看不到实际调用DLL的效果(当前以命令写入文件的方式进行存根处理)。如果我将应用程序换成
C:\\Windows\\system32\\notepad.exe
之类的程序,程序将成功运行。为了完成,这是
MyFunc
的正文:ofstream file;
file.open("C:\\Projects\\Test\\test.txt");
file << "I wrote to a file!";
file.close();
有什么原因不能将RunProcess32与CreateProcess一起使用?在阅读此内容时,我发现了一些有关
LoadLibrary()
和DLLMain
的警告,但似乎与它们无关。更多说明:
当前,这是一个32位应用程序(据说)正在启动32位
rundll32.exe
(稍后将添加逻辑以调用32或64位版本)。我的dll如下:
extern "C" __declspec(dllexport) void CALLBACK MyFunc(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
void CALLBACK MyFunc(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { ... }
其中也有一个
.def
文件,其中包含:EXPORTS
MyFunc
跑步
C:\Windows\system32\rundll32.exe C:\Projects\Test\mydll.dll,MyFunc
产生预期的结果。
更新资料
如注释中所述,将
application
设置为NULL
并在cmd中包括rundll32.exe
似乎有效。相关文件:
CreateProcess
RunDll32.exe
最佳答案
根据CreateProcess()
文档:
如果lpApplicationName
和lpCommandLine
均为非NULL,则lpApplicationName
指向的以Null终止的字符串指定要执行的模块,而lpCommandLine
指向的以Null终止的字符串则指定命令行。新进程可以使用GetCommandLine
检索整个命令行。用C编写的控制台进程可以使用argc
和argv
参数来解析命令行。由于argv[0]
是模块名称,因此C程序员通常将模块名称作为命令行中的第一个标记重复。
您没有将rundll32.exe
作为第一个命令行标记重复。
因此,如果继续使用lpApplicationName
参数,请更改此参数:
LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe";
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc";
为此:
LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe");
LPTSTR cmd = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");
请注意,您当前正在针对ANSI / MBCS进行编译(因为您正在将窄字符串传递给
CreateProcess()
)。如果您曾经更新过项目以针对Unicode进行编译,请改用以下代码:TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");
这是因为文档指出:
lpCommandLine [输入,输出,可选]
...
此函数的Unicode版本
CreateProcessW
可以修改此字符串的内容。因此,此参数不能是指向只读存储器的指针(例如const变量或文字字符串)。如果此参数是常量字符串,则该函数可能会导致访问冲突。您可能仍然考虑将
cmd
更改为TCHAR[]
数组,即使在ANSI / MBCS中也是如此,因此可以执行以下操作:LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe");
TCHAR cmd[(MAX_PATH*2)+10];
wsprintf(cmd, TEXT("%s %s,%s"), application, TEXT("C:\\Projects\\Test\\mydll.dll"), TEXT("MyFunc"));
不管哪种方式,通过将模块文件名作为第一个标记传递给
lpCommandLine
参数,然后可以将lpApplicationName
参数设置为NULL:lpApplicationName
参数可以为NULL。在这种情况下,模块名称必须是lpCommandLine
字符串中第一个由空格分隔的标记。让
CreateProcess()
设置正确的命令行为您传递给rundll32.exe
:TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc");
BOOL cpRes = CreateProcess(NULL, cmd, ...);
关于c++ - 使用CreateProcess执行rundll32.exe,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46434605/