Не удалось выполнить командный файл из службы Windows C ++ - PullRequest
0 голосов
/ 29 мая 2018

Я пытаюсь выполнить командный файл из моей службы C ++ Windows.Этот пакетный файл просто создает пустой файл, используя echo. 2>EmptyFile.txt.

Мой сервисный код выглядит следующим образом:

        PROCESS_INFORMATION procHandles;
        STARTUPINFOA startWinInfo;
        BOOL    result;

        char * cmdname = "C:\\Windows\\System32\\cmd.exe";
        char * cmdargs = "C:\\Users\\user\\Desktop\MyBatFile.bat";

        DWORD    procFlags;
        DWORD    waitStatus = 0;
        DWORD    procStatus = 0;
        DWORD    winErrCode;
        DWORD    inloop = 1;

        memset(&startWinInfo, 0, sizeof(startWinInfo));
        startWinInfo.cb = sizeof(startWinInfo);
        startWinInfo.lpTitle = "Slaved Console";

        procFlags = (CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE |
            CREATE_NEW_PROCESS_GROUP);

        procHandles.hProcess = INVALID_HANDLE_VALUE;
        procHandles.hThread = INVALID_HANDLE_VALUE;
        procHandles.dwProcessId = 0;
        procHandles.dwThreadId = 0;

        result = CreateProcessA(
            cmdname, cmdargs, NULL, NULL, 0, procFlags, NULL,
            NULL, &startWinInfo, &procHandles);

        if (result == 0)
        {
            winErrCode = GetLastError();
            exit(255);        // error with CreateProcessA()
        }


        waitStatus = WaitForInputIdle(procHandles.hProcess, 6000);
        inloop = GetExitCodeProcess(procHandles.hProcess, &procStatus);

        while (procStatus == STILL_ACTIVE && inloop)
        {
            waitStatus = WaitForSingleObject(procHandles.hProcess, 30000);
            if (waitStatus == WAIT_TIMEOUT)
            {
                inloop = 1;
            }
            else if (waitStatus == WAIT_OBJECT_0)
            {
                inloop = GetExitCodeProcess(procHandles.hProcess, &procStatus);
            }
            else
            {
                inloop = 0;    // some type of wait abandon or error ...
                exit(254);
            }
        }
        CloseHandle(procHandles.hProcess);
        CloseHandle(procHandles.hThread);

        exit(procStatus);

Он продолжает давать мне WAIT_TIMEOUT и не выполняет пакетный файл.Кто-нибудь может мне помочь с этим?

1 Ответ

0 голосов
/ 29 мая 2018
  • , если мы хотим выполнить bat-файл в cmd, и для выхода необходимо использовать переключатель /C в командной строке, который выполняет команду, указанную в строке, а затем завершает .
  • путь к файлу bat в общем случае должен быть заключен в "" на случай, если в пути существуют пробелы;
  • нам вообще не нужен вызов WaitForInputIdle.особенно для не графического процесса.если вы проверите результат этого вызова - вы можете заметить, что он завершился с ошибкой ERROR_NOT_GUI_PROCESS
  • для ожидания (и нужно ли ждать?) завершения процесса - необходимого и достаточного ожидания для дескриптора процесса.не нужно звонить GetExitCodeProcess и сравнивать код выхода с STILL_ACTIVE.и здесь не нужно никаких циклов
  • не требуется ноль init PROCESS_INFORMATION - это только параметр
  • не нужно жестко задавать путь к cmd.exe , но получитьво время выполнения, по запросу ComSpec переменная окружения
  • всегда намного лучше использовать W API вместо A

просто коддля выполнения bat файл может выглядеть как

ULONG cfd(PCWSTR BatFileName)
{
    WCHAR ApplicationName[MAX_PATH];
    if (!GetEnvironmentVariable(L"comspec", ApplicationName, RTL_NUMBER_OF(ApplicationName)))
    {
        return GetLastError();
    }

    SIZE_T cch = wcslen(BatFileName);

    PWSTR CommandLine = (PWSTR)alloca(cch * sizeof(WCHAR) + sizeof(L"/c \"\""));

    swprintf(CommandLine, L"/c \"%s\"", BatFileName);

    PROCESS_INFORMATION procHandles;
    STARTUPINFO startWinInfo = { sizeof(startWinInfo) };

    if (CreateProcess(ApplicationName, CommandLine, NULL, NULL, 0, 
        CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE |
        CREATE_NEW_PROCESS_GROUP, NULL,
        NULL, &startWinInfo, &procHandles))
    {
        CloseHandle(procHandles.hThread);

        switch ( WaitForSingleObject(procHandles.hProcess, 3000))
        {
        case WAIT_OBJECT_0:
            break;
        default:
            TerminateProcess(procHandles.hProcess, 0); 
        }
        CloseHandle(procHandles.hProcess);

        return 0;
    }

    return GetLastError();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...