SEE UPDATE AM ENDEMultithreaded-Dienst ausgeführt werden Batch-Datei über Createprocess()
Ich versuche, die folgende Batchdatei (mit dem Namen boot_time.bat, im selben Verzeichnis wie die EXE) auszuführen:
@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%
Die Stapeldatei benötigt ein Argument, das aktuelle Arbeitsverzeichnis. Der Zweck besteht darin, die Startzeit des Systems über das Skript boot_time.vbs abzurufen und in ein gemeinsames Datumsformat zu formatieren. Für completenesses willen, sind hier die Inhalte der vbs-Datei:
set objWMI = GetObject("winmgmts:\\.\root\cimv2")
set colOS = objWMI.InstancesOf("Win32_OperatingSystem")
for each objOS in colOS
Wscript.Echo objOS.LastBootUpTime
NEXT
Während ich Kommentare über alternative schätzen (sprich: einfachere) Methoden, um die Systemstartzeit abgerufen werden, seien Sie versichert, ich alle Möglichkeiten erkundet haben (die ich habe rüberkommen) und keines entspricht den Anforderungen für das System.
Nun, der Kern des Problems. Wenn ich versuche, die .bat-Datei über C++ auszuführen, gibt CreateProcess() 1 zurück, aber die Stapeldatei wird nicht ausgeführt (ich habe dies verifiziert, indem ich den Inhalt von boot_time.bat durch einen einfachen 'start calc' ersetzt habe, der immer noch nicht ausgeführt werden kann)). Die problematischen Code:
//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);
Die Pfade und Befehlszeilenargumente sind alle in Ordnung (ich kann sie debuggen drucken und in cmd.exe einfügen, wo sie wie erwartet). Beim Durchlaufen des Codes gibt CreateProcess() 1 zurück und alles läuft wie normal, jedoch wird die Stapeldatei nie ausgeführt.
In meinen vielen Stunden die interwebs Suche ich auf Einflüsterungen von Fragen gekommen sind, wenn es darum geht, eine Batch-Datei von einem Dienst zu laufen, aber ich:
a) nicht mehr die Einflüsterungen finden,
b) würde denken, dass CreateProcess ("cmd.exe", ...) keine Batch-Datei, sondern eine Exe ausführt und den Rest bis zur Eingabeaufforderung belässt.
Also, irgendeine Idee, was ist los?
Oh, ich bin VC läuft ++ 6
UPDATE 1:
Wenn ich tick 'mit Desktop erlauben zu interagieren', und ändern Sie Createprocess(), um nicht das Konsolenfenster zu verstecken (via CREATE_NEW_CONSOLE) , Bekomme ich einen Bruchteil einer Sekunde, in der die Eingabeaufforderung erscheint. CreateProcess() erstellt also einen cmd.exe-Prozess, aber cmd.exe weigert sich, die Batchdatei auszuführen.
UPDATE 2:
Nach Gabe Vorschlag überlegte ich meinen Prozess und vereinfachte es etwas in einem Versuch, den Schuldigen aufzuspüren. Ich habe die Batch-Datei entfernt und consolodated es in die VBS-Datei, die nun:
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
Die C++ Code ist weitgehend unverändert, nur die Befehlszeile geändert WScript.exe ruft statt cmd.exe. Ich erhalte die vollständig qualifizierten Pfade für alle Dateien, die auf die folgende Zeichenfolge führt:
"C:\WINDOWS\System32\Wscript.exe" //Nologo "c:\<repository_dir>\boot_time.vbs" >"C:\WINDOWS\TEMP\rts5FD.tmp"
(repository_dir vorsätzliches Namen wegzulassen). Außerdem verwende ich nur Wscript, um zu testen, wie es ein Meldungsfeld öffnet. Die korrekte Verwendung erfolgt mit Cscript.exe, wobei die Ausgabe in die temporäre Datei umgeleitet wird.
CreateProcess bewirkt nicht, dass das Meldungsfenster angezeigt wird, wenn es direkt über die Befehlszeile ausgeführt wird.
Zunächst funktioniert es, wenn Sie Ihr Programm von der Befehlszeile statt als Dienst ausführen? Zweitens sollten Sie 'commandStream' drucken und sicherstellen, dass das Ausführen aus dem Arbeitsverzeichnis Ihres Programms funktioniert. – Gabe
Ein offensichtliches Problem ist, dass das VBS-Skript nicht ausgeführt wird, wenn es sich auf einem anderen Laufwerksbuchstaben des Arbeitsverzeichnisses des Dienstes befindet, in dem Sie 'cd/d% 1' verwenden. – Gabe
Ich werde das/d hinzufügen, danke (aber das Skript befindet sich im selben Ordner, also ist das zur Zeit kein Problem). Ja, ich habe versucht, die Ausgabe des Befehls stream aus dem Arbeitsverzeichnis (und jedem anderen Verzeichnis auszuführen, da sich die CD% 1 in das Arbeitsverzeichnis ändert) und es hat gut funktioniert. –