Почему я не могу запустить пакетный файл из службы с помощью system() в Windows Server 2008?

У меня есть программа C++, которая работает как служба на 64-разрядной машине с Windows Server 2008. Эта программа пытается запустить командный файл с помощью следующей команды:

system(C:\pathtofile\file.bat)

В 32-битной Windows Server 2003 это работало нормально (пакетный файл был выполнен), но в Windows Server 2008 пакетный файл не выполняется, и я получаю возвращаемое значение 0xC0000142 (у меня был пакетный файл, записывающий некоторый текст в файл как тест, чтобы увидеть, если он выполняется). Я на самом деле получаю то же возвращаемое значение, даже если я пытаюсь выполнить то, что не существует.

Я прочитал об изоляции сеанса 0 в Windows Server 2008, поэтому я использовал psexec для запуска командной строки в сеансе 0 в качестве того же пользователя домена, который указан как пользователь "Вход в систему" ​​для службы:

psexec -i 0 -u DOMAIN\serviceuser -p passwd cmd.exe

Затем я смог успешно выполнить командный файл из командной строки.

Пользователь домена, который указан как пользователь "Вход в систему" ​​для службы, находится в группе "Администраторы". Также, если я запускаю приложение C++ вручную (не как сервис), оно запускает командный файл.

Так есть ли что-то в изоляции Session 0, которая делает вызов system() не работающим при работе в качестве службы? Или какое-то другое объяснение изменения поведения? Я знаю, что system() не обязательно лучший способ сделать это в любом случае, но я ищу фактическую причину, по которой это больше не работает.

1 ответ

Решение

Из того, что я теперь понимаю о проблеме, причина того, что вы не можете запустить командный файл из службы с помощью system() в Windows Server 2008, заключается в том, что Windows рассматривает любую попытку вызова cmd.exe (как это было бы для запуска вашего пакета). файл) как попытка запуска интерактивного сервиса. Из-за изоляции сеанса 0 это недопустимо и просто не удастся, даже если вы не думаете, что ваш командный файл является интерактивным или имеет графический интерфейс (который меня отбрасывал).

Я понял, как получить эффект, который искал, используя CreateProcess. Ключевым моментом здесь является то, что вы должны установить для параметра dwCreationFlags значение CREATE_NO_WINDOW. Так что мой (упрощенный) вызов в итоге выглядел примерно так:

CreateProcess(NULL,   // No module name (use command line)
    L"C:\\Windows\\System32\\cmd.exe /C myfile.bat", // Call cmd.exe with /C flag
    NULL,           // Process handle not inheritable
    NULL,           // Thread handle not inheritable
    FALSE,          // Set handle inheritance to FALSE
    CREATE_NO_WINDOW,              // Use CREATE_NO_WINDOW!!!
    NULL,           // Use parent's environment block
    NULL,           // Use parent's starting directory 
    &si,            // Pointer to STARTUPINFO structure
    &pi )           // Pointer to PROCESS_INFORMATION structure
Другие вопросы по тегам