Search code examples
winapifiremonkeyc++builder

ShellExecute bat file elevated (FMX, Win32)


I want to spawn a batch file from my FMX app (on Win32) with elevated privileges. From Remy's answer at the bottom of this thread on ShellExecute I found how to launch the batch file. Now, i can't figure out how to launch it with elevated privilege. Below is my code:

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");
}

I added "runas" for the second argument after reading this to no avail. Running the batch file manually (right-click and run as admin) works. Here is content of the batch file fyi (just kicks of a system imaging):

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

How can i ShellExecute this batch file as admin?

UPDATE 1: I'm attempting to use CreateProcess per Remy suggestion. Here is my code (based on 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));

If I run it as shown (right-click on exe and run as admin) it returns 0 which means it failed. If I run it by putting the wbAdmin command line in the test.bat file (see commented line right above String strCmdLine in the code) then CreateProcess returns a 1 (success) but wbAdmin is still not running. It flashed a DOS window and i captured it as shown in the picture below. It shows oriental characters in the title bar and says not recognized as internal or external command. But, if i run that test.bat directly (elevated) it runs wbAdmin no problem.

Any ideas on what is wrong? Besides me obviously being ignorant. (p.s. i'll get to testing Golvind's answer on the ShellExecute after this...)

enter image description here


Solution

  • Running the batch file manually (right-click and run as admin) works.

    Because you are running the 64-bit version of cmd when you start it manually.

    It shows oriental characters in the title bar and says not recognized as internal or external command.

    Because your application is 32-bit. A 32-bit application does not see the same System32 folder as 64-bit applications. You can access the 64-bit System32 folder in 32-bit applications with the virtual sysnative folder.

    #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
        }
    

    Or compile your application to 64-bit.