如何在Windows中使用rundll32.exe删除文件



我发现它应该是这样的:

rundll32 kernel32.dll,DeleteFileA,test.txt

但它就是不起作用。我试过了:

rundll32 kernel32.dll,DeleteFileA test.txt
rundll32 "kernel32.dll,DeleteFileA test.txt"

文件将保留。从PowerShell尝试时,当我拼错DeleteFileA时,它会显示一条错误消息,以便在kernel32.dll中找到正确的条目。它就是不起作用,可能是因为没有得到文件名参数。

为什么我需要它?我需要能够以管理员的身份删除在常规用户上下文中运行的程序中的文件。我绝对不希望整个应用程序以管理员身份运行。只有一次删除才会显示UAC确认。

以下是在我的C#应用程序中有效的东西:

private static void DeleteAsAdmin(string target) {
Process.Start(new ProcessStartInfo { FileName = "cmd", Arguments = $"/C "del /F /Q """{target}""""", Verb = "RunAs", CreateNoWindow = true });
}

不过,它还是显示了一个窗口。有一段时间,但它是可见的。这是因为我必须显式地执行cmd才能使用del命令。

这就是为什么我想使用rundll32。默认情况下,这不会创建任何窗口。并公开了FileDeleteA方法。

我知道,我可以添加一个助手可执行文件,作为应用程序的管理员删除文件,但这是一个非常丑陋的解决方案,甚至比调用cmd更丑陋。

为什么我首先需要删除该文件?为了安全。该文件包含一个敏感的程序配置,该配置将被加密(使用DPAPI(并移动到用户可访问的目录中。原始文件,位于";C: \程序文件"为了额外的安全需要移除。如果用户取消UAC提示,那么这将失败,但将敏感配置以纯文本形式显示将是用户的错。

是的,我知道我可以通过MSI将文件放在用户的目录中,但这对我来说也不好,因为这需要额外的配置步骤,我想避免。在使用完全默认的MSI安装程序安装后,程序必须自己完成所有的家务。我可以这样说,但rundll32黑客似乎只是在嘲笑我,而我离它只有一个特殊的角色;(

rundll32需要一个非常具体的函数签名,它不是一个通用的"调用任何函数";助手应用程序。

要隐藏cmd窗口,你可以尝试添加WindowStyle = ProcessWindowStyle.Hidden,但如果你已经有了C#应用程序,为什么还要麻烦呢?只要叫自己去做这项任务。这至少会在UAC对话框中放入正确的.exe。

即使你让这一切都发挥作用,它仍然是错误的!如果你要安装到%ProgramFiles%中,那么你是为机器上的所有用户安装的,一旦第二个用户运行你的应用程序,你的方案就会中断。任何写入用户配置文件的操作都必须在用户第一次运行程序时完成,而不是在安装阶段。您可以将模板文件从安装目录复制到用户配置文件,但不能删除这些模板。

如果需要删除文件,可以使用IFileOperation。示例代码:

#include <shobjidl_core.h>
// assume
// CoInitializeEx(0, COINIT_DISABLE_OLE1DDE|COINIT_APARTMENTTHREADED);
// already called
HRESULT DeleteFileElevated(PCWSTR lpFilename)
{
IShellItem* psi;
HRESULT hr = SHCreateItemFromParsingName(lpFilename, 0, IID_PPV_ARGS(&psi));
if (0 <= hr)
{
IFileOperation *pFileOp;
BIND_OPTS2 bo = { sizeof(bo) };
bo.dwClassContext = CLSCTX_LOCAL_SERVER;
if (0 <= (hr = CoGetObject(L"Elevation:Administrator!new:{3ad05575-8857-4850-9277-11b85bdb8e09}", &bo, IID_PPV_ARGS(&pFileOp))))
{
0 <= (hr = pFileOp->SetOperationFlags(FOF_NOCONFIRMATION| 
FOF_NOERRORUI| 
FOF_FILESONLY| 
FOFX_EARLYFAILURE|
FOFX_SHOWELEVATIONPROMPT)) &&
0 <= (hr = pFileOp->DeleteItem(psi, 0))
&& 
0 <= (hr = pFileOp->PerformOperations());
pFileOp->Release();
}
psi->Release();
}
return hr;
}

最新更新