无法从C ++ Windows服务执行批处理文件

时间:2018-05-29 09:04:23

标签: c++ windows winapi

我正在尝试从我的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 :(得分:0)

  • 如果我们想在cmd中执行bat文件并退出,则需要使用/C切换 命令行,其中执行string和string指定的命令 然后终止
  • 一般情况下,bat文件的路径必须包含在""中 路径中存在空格;
  • 我们根本不需要致电WaitForInputIdle。特别是对于不gui 处理。如果你检查这个电话的结果 - 你可以注意到它失败了 错误ERROR_NOT_GUI_PROCESS
  • 等待(并且需要等待?)进程终止 - 必要和 足够等待进程句柄。不需要打电话 GetExitCodeProcess并将退出代码与STILL_ACTIVE进行比较。 此处也不需要任何循环
  • 不需要零初始化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();
}
相关问题