3

Windows 有一个名为 rundll32.exe 的实用程序,可以将本机动态链接库作为应用程序执行。

假设我有一段代码打印“Hello World!” 到控制台。是否可以用 C++(最好是 Visual C++)编写一个可以使用 rundll32.exe 执行并运行此代码的库?如果是这样,怎么做?

4

4 回答 4

10

谷歌搜索“rundll32”,第三次点击是文档链接,

http://support.microsoft.com/kb/164787

根据该文档,rundll32调用具有类似签名的用户指定函数wWinMain(除了这里的第一个参数是窗口句柄而不是实例句柄),

void CALLBACK
EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

所以,试试这个:

// File [foo.def]
EXPORTS
    sayHello
// File [foo.cpp]
#include <iostream>

namespace myCode {

    void sayHello()
    {
        using namespace std;
        cout << "Hello, world!" << endl;
    }

}    // namespace myCode

#undef UNICODE
#define UNICODE
#include <windows.h>

extern "C" 
__declspec( dllexport )
void CALLBACK sayHello( HWND, HINSTANCE, wchar_t const*, int )
{
    AllocConsole();
    freopen( "CONIN$", "r", stdin ); 
    freopen( "CONOUT$", "w", stdout ); 
    freopen( "CONOUT$", "w", stderr ); 

    DWORD const infoBoxOptions = MB_ICONINFORMATION | MB_SETFOREGROUND;
    MessageBox( 0, L"Before call...", L"DLL message:", infoBoxOptions );
    myCode::sayHello();
    MessageBox( 0, L"After call...", L"DLL message:", infoBoxOptions );
}

构建和运行:

[d:\开发\测试]
> cl foo.cpp foo.def user32.lib /MD /LD /D _CRT_SECURE_NO_WARNINGS
foo.cpp
   创建库 foo.lib 和对象 foo.exp

[d:\开发\测试]
> rundll32 foo.dll,sayHello

[d:\开发\测试]
> _

输出显示在其自己的控制台窗口中,通过 创建AllocConsole,这通常是必要的,因为 rundll32 是一个 GUI 子系统程序(这也是freopen调用的原因)。

要在现有控制台窗口中显示输出,只需省略对AllocConsoleand的调用freopen,并将标准输出重定向rundll32到管道。more例如,当输出只有几行时,标准输出可以通过 Windows 进行管道传输,或者通过一些 *nix-utilitycat来传输更多行。但是,在标准命令解释器 [cmd.exe] 中,仅将输出重定向到con.

于 2012-08-11T19:41:48.307 回答
3

http://support.microsoft.com/kb/164787

这篇 MSDN 文章我相信还是准确的;您将入口点定义为

  void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
于 2012-08-11T19:08:16.553 回答
2

虽然可以使用 rundll32 在 DLL 中运行设计合理的函数,但不建议这样做。这样做意味着您的 DLL 受 rundll32 的进程设置(大地址感知、终端服务感知、DPI 感知、提升清单等)的支配。更糟糕的是:如果其他一些 rundll32 进程触发了应用程序兼容性行为(例如低碎片heap),那么这将影响包括您的所有 rundll32 进程。

只需编写一个单独的EXE。

于 2012-08-12T00:17:56.927 回答
0

就像乔和你自己所说的那样,使用这样的东西:

 void CALLBACK func(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) 
 { 
   std::cout << "Hello world!" << std::endl; 
 }

但是,CALLBACK = __stdcall,当您的“func”被导出时,它将更改为 _func@16

您可以更改此名称,http://support.microsoft.com/kb/140485

所以,你可能想尝试类似的事情:

rundll32.exe DLLTest.dll,_func@16 
于 2012-08-11T19:45:21.520 回答