ShellExecute bat文件提升(FMX,Win32)

时间:2019-02-08 21:44:47

标签: winapi firemonkey c++builder

我想从我的FMX应用程序(在Win32上)以提升的特权生成一个批处理文件。在ShellExecute底部of this thread的Remy回答中,我找到了如何启动批处理文件。现在,我不知道如何以提升的特权启动它。下面是我的代码:

String Prog = "c:\\Users\\rwp\\Desktop\\test.bat";
int nErrorCode = (int) ShellExecute(NULL, L"runas", Prog.c_str(), NULL, NULL, SW_SHOWNORMAL);
if (nErrorCode <= 32) {
 ShowMessage("an error occured");
}

我在读完this后第二个参数中添加了“ runas”,但无济于事。可以手动运行批处理文件(右键单击并以admin身份运行)。这是批处理文件fyi(仅是系统映像的一击)的内容:

c:\Windows\system32\wbAdmin.exe start backup -backupTarget:D: -include:C: -allCritical -quiet

我如何以管理员身份ShellExecute此批处理文件?

更新1:我正在尝试根据Remy建议使用CreateProcess。这是我的代码(基于this example):

//Code is inside a __fastcall button click
    PROCESS_INFORMATION     piProcInfo;
    STARTUPINFO             siStartInfo;
    siStartInfo.cb          = sizeof(STARTUPINFO);
    siStartInfo.lpReserved  = NULL;
    siStartInfo.lpReserved2 = NULL;
    siStartInfo.cbReserved2 = 0;
    siStartInfo.lpDesktop   = NULL;
    siStartInfo.dwFlags     = 0;

   //   String strCmdLine = "C:\\Users\\rwpatter\\Desktop\\test.bat";
    String strCmdLine = "C:\\Windows\\System32\\wbAdmin.exe start backup -backupTarget:T: -include:C: -allCritical -quiet";

    // Create the child process.
    int rtrn =  CreateProcess(

        NULL,
        strCmdLine.c_str(),
        NULL,           // process security attributes
        NULL,           // primary thread security attributes
        0,              // handles are inherited
        0,              // creation flags
        0,              // use parent's environment
        0,           // use parent's current directory
        &siStartInfo,   // STARTUPINFO pointer
        &piProcInfo);   // receives PROCESS_INFORMATION

        // Wait for the processs to finish
        DWORD rc = WaitForSingleObject(
                      piProcInfo.hProcess, // process handle
                      INFINITE);
        ShowMessage(IntToStr(rtrn));

如果我如图所示运行它(右键单击exe并以admin身份运行),它将返回0,表示它为failed。如果我通过将wbAdmin命令行放入test.bat文件(请参见代码中String strCmdLine上方的注释行)来运行它,则CreateProcess返回1(成功),但wbAdmin仍未运行。它闪烁了一个DOS窗口,我如下图所示捕获了它。它在标题栏中显示东方字符,并说未被识别为内部或外部命令。但是,如果我直接运行该test.bat(提升),它将运行wbAdmin没问题。

关于什么是错的任何想法?除了我,我显然很无知。 (对。在此之后,我将在ShellExecute上测试Golvind的答案...)

enter image description here

2 个答案:

答案 0 :(得分:1)

  

手动运行批处理文件(右键单击并以管理员身份运行)是可行的。

因为您在手动启动时正在运行64位版本的cmd。

  

它在标题栏中显示东方字符,并说未识别   作为内部或外部命令。

因为您的应用程序是32位的。一个32位应用程序看不到与64位应用程序相同的System32文件夹。您可以使用虚拟sysnative文件夹访问32位应用程序中的64位System32文件夹。

#include <shellapi.h>
...
    String strCmdLine = "wbAdmin.exe start backup -backupTarget:T: -include:C: -allCritical -quiet";
    int rtrn = CreateProcess(
        NULL,
        strCmdLine.c_str(),
        NULL,           // process security attributes
        NULL,           // primary thread security attributes
        0,              // handles are inherited
        0,              // creation flags
        0,              // use parent's environment
        0,           // use parent's current directory
        &siStartInfo,   // STARTUPINFO pointer
        &piProcInfo);   // receives PROCESS_INFORMATION
    if (!rtrn)
    {
        String newCmdLine = "c:\\windows\\sysnative\\wbAdmin.exe start backup -backupTarget:T: -include:C: -allCritical -quiet";
        rtrn = CreateProcess(
            NULL,
            newCmdLine.c_str(),
            NULL,           // process security attributes
            NULL,           // primary thread security attributes
            0,              // handles are inherited
            0,              // creation flags
            0,              // use parent's environment
            0,           // use parent's current directory
            &siStartInfo,   // STARTUPINFO pointer
            &piProcInfo);   // receives PROCESS_INFORMATION
    }

或将您的应用程序编译为64位。

答案 1 :(得分:0)

您需要使用"runas"以管理员身份启动CMD.exe,并将批处理文件指定为命令提示符下的“先运行然后退出”(即/c)参数,这样:

WCHAR wszCmdPath[MAX_PATH];
GetEnvironmentVariableW(L"ComSpec", wszCmdPath, MAX_PATH);
ShellExecuteW(NULL, L"runas", wszCmdPath, L"/c \"C:\\Path\\BatchFile.bat\"", L"", SW_SHOW);

此处调用的两个函数都可能失败,而健壮的代码将在继续之前测试成功。