СМ. ОБНОВЛЕНИЕ В КОНЦЕ
Я пытаюсь запустить следующий пакетный файл (с именем boot_time.bat, в том же каталоге, что и .exe):
@echo off
cd %1
For /F %%I in ('Cscript boot_time.vbs //Nologo') Do Set var=%%I
set DATETIME=%var:~0,4%/%var:~4,2%/%var:~6,2% %var:~8,2%:%var:~10,2%:%var:~12,2%.%var:~15,3%
echo %DATETIME%
Пакетный файл принимает один аргумент, это текущий рабочий каталог. Его цель - получить время загрузки системы через скрипт boot_time.vbs и отформатировать его в общий формат даты. Для полноты, вот содержимое файла vbs:
set objWMI = GetObject("winmgmts:\\.\root\cimv2")
set colOS = objWMI.InstancesOf("Win32_OperatingSystem")
for each objOS in colOS
Wscript.Echo objOS.LastBootUpTime
NEXT
Хотя я ценю комментарии об альтернативных (читай: более простых) способах получения времени загрузки системы, будьте уверены, что я изучил все возможности (с которыми я сталкивался), и ни один из них не соответствует требованиям для системы.
Теперь суть вопроса. Когда я пытаюсь запустить файл .bat через C ++, CreateProcess () возвращает 1, но пакетный файл не запускается (я подтвердил это, заменив содержимое boot_time.bat на простой 'start calc', который по-прежнему отказывается запускаться ). Оскорбительный код:
//run batch file
stringstream commandStream;
commandStream << "/C " //close window on termination
<< "\"" << batchFile.c_str() << "\" " //batch file path inside ""
<< "\"" << processPath.c_str() << "\" " //working directory as argument inside ""
<< ">" //redirect
<< "\"" << outFile.c_str() << "\""; //output file inside ""
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
BOOL ret = CreateProcess("cmd.exe", const_cast<char*>(commandStream.str().c_str()), NULL, NULL, TRUE, NULL, NULL, processPath.c_str(), &si, &pi);
WaitForSingleObject( pi.hProcess, INFINITE );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
Все пути и аргументы командной строки в порядке (я могу отладить, распечатать их и вставить в cmd.exe, где они работают как положено). Шагая по коду, CreateProcess () возвращает 1, и все работает как обычно, однако пакетный файл никогда не запускается.
За долгие часы поисков в сети я натолкнулся на шепот проблем, когда дело доходит до запуска командного файла из службы, но я:
а) больше не может найти указанный шепот,
б) подумал бы, что CreateProcess ("cmd.exe", ...) запускает не пакетный файл, а исполняемый файл, а остальное оставляет до командной строки.
Итак, есть идеи, что происходит?
О, я использую VC ++ 6
ОБНОВЛЕНИЕ 1:
Если я поставлю галочку «Разрешить сервису взаимодействовать с рабочим столом» и изменил CreateProcess (), чтобы не скрывать окно консоли (через CREATE_NEW_CONSOLE), я получаю долю секунды в командной строке. Итак, CreateProcess () создает процесс cmd.exe, но cmd.exe отказывается запускать командный файл.
ОБНОВЛЕНИЕ 2:
После предложения Гейба я переосмыслил свой процесс и несколько упростил его, пытаясь отследить виновника. Я удалил командный файл и объединил его в файл VBS, который теперь:
set objWMI = GetObject("winmgmts:\\.\root\cimv2")
set colOS = objWMI.InstancesOf("Win32_OperatingSystem")
Dim bootTime
for each objOS in colOS
bootTime = objOS.LastBootUpTime
bootTime = mid(bootTime,1,4) & "/" & Mid(bootTime,5,2) & "/" & Mid(bootTime,7,2) & " " & Mid(bootTime,9,2) & ":" & Mid(bootTime,11,2) & ":" & Mid(bootTime,13,2) & "." & Mid(bootTime,16,3)
Wscript.Echo bootTime
NEXT
Код на С ++ в основном не изменился, просто изменил командную строку для вызова WScript.exe вместо cmd.exe. Я получаю полные пути для всех файлов, что приводит к следующей строке:
"C:\WINDOWS\System32\Wscript.exe" //Nologo "c:\<repository_dir>\boot_time.vbs" >"C:\WINDOWS\TEMP\rts5FD.tmp"
(repository_dir намеренно не указывать имен). Кроме того, я использую только Wscript для тестирования, так как он открывает окно сообщения. Правильное использование будет с Cscript.exe, с выводом, перенаправленным во временный файл.
CreateProcess не вызывает всплывающее окно с сообщением, запускается прямо из командной строки.