.exe Datei starten

05/20/2017 21:39 Guron#1
Hallo!

Ich lerne seit gestern C++ und wollte beim starten des Programms eine .exe starten lassen. Nur leider funktioniert das nicht so gut. Entweder wird das Verzeichnis mitsamt exe als CMD geöffnet oder die Whitespaces im filename machen mir ein Strich durch die Rechnung. Bei einem CreateProcess bekomme ich meine geschriebene Meldung mit der Errorzahl 2. Kann mir BITTE jemand helfen? Ich sitze seit 2-3 Stunden daran ein pimmeliges Programm zu öffnen.

Snippets kann ich nicht zeigen, weil anscheinend alles falsch war.
05/20/2017 21:42 Beni#2
Schick uns doch trotzdem ein Snippet, damit wir wenigstens eine Idee bekommen. Die Errormeldung nochmal 1:1 hier rein kopiert (zusammen mit dem Code) dürfte einiges helfen.

Hast du schon mal nach dem Error gegoogelt? (Wie man z.B whitespaces in Filenames escaped?)
05/20/2017 21:53 wurstbrot123#3
Errorcode 2 = ERROR_FILE_NOT_FOUND The system cannot find the file specified.

Heisst es gibt sehr wahrscheinlich fehler beim ersten Parameter.

Versuch mal den kompletten Pfad zur exe zu übergeben zb c:\ordner\hey.exe
05/20/2017 22:02 Guron#4
Quote:
Originally Posted by Beni View Post
Schick uns doch trotzdem ein Snippet, damit wir wenigstens eine Idee bekommen. Die Errormeldung nochmal 1:1 hier rein kopiert (zusammen mit dem Code) dürfte einiges helfen.

Hast du schon mal nach dem Error gegoogelt? (Wie man z.B whitespaces in Filenames escaped?)
Wie ich whitespaces escape versteh' ich noch nicht so ganz. Finde das teilweise aber auch etwas komisch mit den \


Hier mein Code:
Code:
	
	// additional information
	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	// set the size of the structures
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi, sizeof(pi));

	// start the program up
	CreateProcess((LPCWSTR) "C:\\Program Files(x86)\\Steam\\steamapps\\common\\Shakes & Fidget\\Shakes and Fidget.exe",   // the path
		NULL,        // Command line
		NULL,           // Process handle not inheritable
		NULL,           // Thread handle not inheritable
		FALSE,          // Set handle inheritance to FALSE
		0,              // No creation flags
		NULL,           // Use parent's environment block
		NULL,           // Use parent's starting directory 
		&si,            // Pointer to STARTUPINFO structure
		&pi             // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
	);
	// Close process and thread handles. 
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	while (true); 

    return 0;
Quote:
Originally Posted by wurstbrot123 View Post
Errorcode 2 = ERROR_FILE_NOT_FOUND The system cannot find the file specified.

Heisst es gibt sehr wahrscheinlich fehler beim ersten Parameter.

Versuch mal den kompletten Pfad zur exe zu übergeben zb c:\ordner\hey.exe
Hab ich gemacht, nur gibt es Probleme mit der Verlinkung, dem whitespace und dem backslash. Code steht oben. Errormeldung:

Hier wird bei C:\ das Backslash mit einem " ersetzt und ich weiß beim besten Willen nicht wieso.

Edit:
Wenn ich die exe starte passiert einfach gar nichts. Code wurde editiert.
05/20/2017 22:14 florian0#5
Die Leerzeichen musst du meines Wissens auch nicht escapen. Nur die Backslashes.
Das Escape-Zeichen ist der Backslash. Damit in C:\Program... der Backslash nicht versucht das P zu escapen, musst du den Backslash escapen. Etwa so C:\\Program.... Und das eben für alle Backslashes.
05/21/2017 17:32 Guron#6
Ein Kollege hat mir geholfen. Tatsächlich musste ich, wie florian0 bereits gesagt hat, die Whitespaces nicht escapen. Bei system musste ich das komischerweise schon und auch hat sich abundzu einfach mal ein " eingeschlichen. Wieso und warum weiß ich immer noch nicht. Statt dem typ LPCWSTR muss ich einfach L angeben. Siehte code:

Code:
// start the program up
	CreateProcess(L"C:\\Program Files (x86)\\Steam\\steamapps\\common\\Shakes & Fidget\\Shakes and Fidget.exe",   // the path
		NULL,        // Command line
		NULL,           // Process handle not inheritable
		NULL,           // Thread handle not inheritable
		FALSE,          // Set handle inheritance to FALSE
		0,              // No creation flags
		NULL,           // Use parent's environment block
		NULL,           // Use parent's starting directory 
		&si,            // Pointer to STARTUPINFO structure
		&pi             // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
	);
Danke trotzdem für eure Hilfe!
05/21/2017 20:08 florian0#7
Die WinAPI existiert in zwei Ausführungen, eine für ASCII (A) und eine für Wide-Characters (W). Jenachdem für welche WinAPI dein Projekt kompiliert wird, wählt die Windows.h (und alle unter-dateien dieser) die passenden Funktionen für A oder W aus.

Wird ein Projekt für ASCII kompiliert, wird CreateProcess zur CreateProcessA und der erste Parameter ist dann vom Typ LPCSTR (aka. "const char*"). Für Wide-Characters wird CreateProcessW verwendet und hier kommt dann der LPCWSTR (aka. "const wchar_t*") zum Einsatz.
Das macht auch Sinn, denn bei ASCII sind schließlich die Zeichen durch ein einziges Byte beschrieben, während Wide-Characters pro Zeichen zwei Byte verwendet.

Wird dein Projekt für Wide-Characters kompiliert, dann werden nicht automatisch alle Zeichenketten zu Wide-Characters. Denn ASCII-Zeichenketten sind ja ebenso erlaubt, funktionieren nur meist nicht mehr ohne Umwege mit der WinAPI. Daher bleiben alle Zeichenketten ASCII und du als Entwickler musst definieren, welche Zeichenketten nun zu Wide-Characters werden müssen.

Das tust du mit dem vorangestellten L. Naturlich hat das einige Nachteile, schließlich ist dein Projekt jetzt fest auf Wide-Characters (oder ASCII) entwickelt und kann nicht so ohne weiteres anders kompiliert werden. Wie viel Sinn es macht, ein Projekt zwischen ASCII und Wide-Characters wechseln zu lassen, sei mal da hingestellt, aber Microsoft hat dafür einen Ausweg gefunden.

Mit dem Makro "TEXT" entscheidet die WinAPI für dich, ob nun ein L vor deinen String kommt, oder nicht.

Code:
MessageBox(0, TEXT("Titel"), TEXT("Hallo Welt!"), MB_OK);

Zum Escaping
Generell müssen bei Windows Whitespaces immer extra gequotet werden. Unzählbar viele Programme, auch von Microsoft selbst, weisen zum Teil fatale Schwachstellen auf, nur weil an dieser stelle geschlampt wurde.

Das Problem hierbei ist, dass der Interpreter für den Aufruf des Programms so ausgelegt ist, dass nach dem ersten "echten" Whitespace der Pfad zum Programm abgeschlossen ist und danach die Parameter kommen.

Das hier klappt noch.
Code:
C:\test.exe arg1 arg2 arg3
Das hier gibt schon Probleme
Code:
C:\mein test.exe arg1 arg2 arg3
Der Interpreter liest hier "Programm ist C:\mein mit den Parametern test.exe arg1 arg2 arg3"

Gelöst wird das in der Regel so:
Code:
"C:\mein test.exe" arg1 arg2 arg3
(Ob man Whitespaces auch escapen kann, weiß ich nicht. Unter Linux gehts jedenfalls, unter Windows bekomm ichs gar nich hin. Vielleicht gibts da en Trick ...). Jedenfalls ist das die Lösung, die alle verwenden wenn sie Leerzeichen im Pfad haben oder erwarten.


CreateProcess stellt hier ein Ausnahme da, denn: Hier wird der Name zur ausführbaren Datei explizit angegeben, getrennt von den Parametern. Hier liegt es damit an der WinAPI, das "Beste" draus zu machen.
05/22/2017 10:40 Guron#8
Quote:
Originally Posted by florian0 View Post
Die WinAPI existiert in zwei Ausführungen, eine für ASCII (A) und eine für Wide-Characters (W). Jenachdem für welche WinAPI dein Projekt kompiliert wird, wählt die Windows.h (und alle unter-dateien dieser) die passenden Funktionen für A oder W aus.

Wird ein Projekt für ASCII kompiliert, wird CreateProcess zur CreateProcessA und der erste Parameter ist dann vom Typ LPCSTR (aka. "const char*"). Für Wide-Characters wird CreateProcessW verwendet und hier kommt dann der LPCWSTR (aka. "const wchar_t*") zum Einsatz.
Das macht auch Sinn, denn bei ASCII sind schließlich die Zeichen durch ein einziges Byte beschrieben, während Wide-Characters pro Zeichen zwei Byte verwendet.

Wird dein Projekt für Wide-Characters kompiliert, dann werden nicht automatisch alle Zeichenketten zu Wide-Characters. Denn ASCII-Zeichenketten sind ja ebenso erlaubt, funktionieren nur meist nicht mehr ohne Umwege mit der WinAPI. Daher bleiben alle Zeichenketten ASCII und du als Entwickler musst definieren, welche Zeichenketten nun zu Wide-Characters werden müssen.

Das tust du mit dem vorangestellten L. Naturlich hat das einige Nachteile, schließlich ist dein Projekt jetzt fest auf Wide-Characters (oder ASCII) entwickelt und kann nicht so ohne weiteres anders kompiliert werden. Wie viel Sinn es macht, ein Projekt zwischen ASCII und Wide-Characters wechseln zu lassen, sei mal da hingestellt, aber Microsoft hat dafür einen Ausweg gefunden.

Mit dem Makro "TEXT" entscheidet die WinAPI für dich, ob nun ein L vor deinen String kommt, oder nicht.

Code:
MessageBox(0, TEXT("Titel"), TEXT("Hallo Welt!"), MB_OK);

Zum Escaping
Generell müssen bei Windows Whitespaces immer extra gequotet werden. Unzählbar viele Programme, auch von Microsoft selbst, weisen zum Teil fatale Schwachstellen auf, nur weil an dieser stelle geschlampt wurde.

Das Problem hierbei ist, dass der Interpreter für den Aufruf des Programms so ausgelegt ist, dass nach dem ersten "echten" Whitespace der Pfad zum Programm abgeschlossen ist und danach die Parameter kommen.

Das hier klappt noch.
Code:
C:\test.exe arg1 arg2 arg3
Das hier gibt schon Probleme
Code:
C:\mein test.exe arg1 arg2 arg3
Der Interpreter liest hier "Programm ist C:\mein mit den Parametern test.exe arg1 arg2 arg3"

Gelöst wird das in der Regel so:
Code:
"C:\mein test.exe" arg1 arg2 arg3
(Ob man Whitespaces auch escapen kann, weiß ich nicht. Unter Linux gehts jedenfalls, unter Windows bekomm ichs gar nich hin. Vielleicht gibts da en Trick ...). Jedenfalls ist das die Lösung, die alle verwenden wenn sie Leerzeichen im Pfad haben oder erwarten.


CreateProcess stellt hier ein Ausnahme da, denn: Hier wird der Name zur ausführbaren Datei explizit angegeben, getrennt von den Parametern. Hier liegt es damit an der WinAPI, das "Beste" draus zu machen.
ich liebe dich
05/22/2017 14:49 Underfisk#9
btw for compatibility in URL path, try to use more
PHP Code:
path = @"C:\.." 
instead of using c:\\
05/22/2017 15:01 Jeoni#10
Quote:
Originally Posted by Underfisk View Post
btw for compatibility in URL path, try to use more
PHP Code:
path = @"C:\.." 
instead of using c:\\
That is not C or C++ standard, but works for C#. It may also work for C++ / CLI, I don't know, but when compiling regular C++ or C, that won't work.
With best regards
Jeoni
05/23/2017 09:05 Underfisk#11
@[Only registered and activated users can see links. Click Here To Register...] there's problably an equivalent so :) and its quite best practise instead of his absolute path
05/23/2017 10:51 florian0#12
Are verbatim strings really supported by MSVC? I cant remember ever using them ...
(Maybe if using their raped C++ extension called Visual C++ ...)

[Only registered and activated users can see links. Click Here To Register...], this would be your way to go.