我想从命令行调用各种 Windows DLL 中的功能。看来该rundll32
实用程序可以满足我的需要 - 它接受 DLL 名称和函数名称,并使用参数运行该函数。
我当然希望这不会有什么问题。我可以使用哪些功能rundll32
?
答案1
几乎肯定会出现问题。
我可以使用哪些功能rundll32
?
嗯,理想情况下,你根本不会使用它——它已弃用:
Rundll32 是 Windows 95 的遗留产物,至少从 Windows Vista 开始就被弃用了,因为它违反了许多现代工程准则。如果您通过 Rundll32 运行某些程序,那么您将无法根据所运行程序定制执行环境。
rundll32
仅被设计用于调用非常特定类型的函数,具体来说,就是创建窗口和处理窗口消息的函数。微软关于rundll32
界面的文档解释你正在调用的函数必须取一个HWND
、一个HINSTANCE
、一个LPSTR
和一个int
(按此顺序),并且必须使用_stdcall
/CALLBACK
调用约定。
查阅要调用的函数的 MSDN 文档,查看它是否具有该签名。例如,ExitWindowsEx
不合适。事实上,我找不到任何有该签名的函数。
如果您不确定这些意味着什么,您可以跳过下一部分并继续最后一部分。
如果我在其他功能上使用它,会出现什么问题?
还记得整个函数签名的事情吗?rundll32
假设你尝试调用的函数有正确的签名,无论事实是否如此。当它的假设错误时,可能会发生与堆栈相关的严重奇怪的事情。(堆栈是存储在函数之间传递的参数的内存位置。)
函数签名不匹配会导致提供的数据rundll32
被解释为不同的内容,因为函数期望其参数在堆栈上的位置不同。rundll32
提供的第一个数据是窗口句柄,它以不确定的方式分配。因此,如果您误用rundll32
,你实际上是将随机数据作为第一个参数传递. 进一步阅读:如果调用约定不匹配,会发生什么问题?
其余参数也没有什么好结果。即使你通过 向函数提供命令行rundll32
,它也不会被解析为适合该函数的数据类型。相反,它只会rundll32
获取整个“额外”文本,将其塞入字符串变量,并将指向该数据的指针作为后续参数传递给函数。解析文本由函数决定。因此,使用 调用带有用户提供的参数的任意函数是不可能的rundll32
。
如果目标函数不需要参数,这并不是一场彻底的灾难,但你仍然会弄乱堆栈。有代码rundll32
可以处理这个问题,但这并不能成为你继续滥用它的借口。
如果您使用rundll32
来调用第三方 DLL 中兼容的函数,而该 DLL 是设计用于这种方式的,那么您仍然可能会遇到问题。rundll32
始终选择加入所有新的 Windows 功能(例如数据执行保护),这可能会引入第三方代码未设计为针对的更改;这就是为什么该行为是选择加入的。
幸运的是,有更好的方法可以实现您的愿望。
我可以做什么呢?
尝试锁定工作站 ( user32.dll,LockWorkStation
)?只需运行tsdiscon
。
是否要关闭系统 ( user32.dll,ExitWindowsEx
)?使用shutdown
带有适当标志的实用程序 — 请参阅shutdown /?
获取帮助。
您是应用程序开发人员,想在不编写新 EXE 的情况下调用您的 DLL 函数吗?编写该 EXE(可能使用 C++)。
想运行其他程序吗?我的开源实用程序打印动态链接库支持用户指定的参数列表、多种调用约定和脚本,以便处理多个函数及其输出。如果您只喜欢使用 Windows 附带的工具,您可以这样做使用 PowerShell 进行 P/Invoke。
rundll32
这个问题和答案是为了纠正那些建议以可疑方式使用的材料而编写的参考。如果您发现有人滥用rundll32
,请向他们提供此页面的链接!