C++ -- system("start") mit Variablen nutzen

Prestige__

Mitglied
Hallo.

Ich habe seit ca. 2 Monaten ein Projekt am laufen. Es geht um eine Konsolenanwendung. Ich brauche hilfe bei einer Funktion, da ich noch halbwegs neu in C++ unterwegs bin. Also ich möchte in der Funktion system("start") eine Variable einbauen, weiß aber leider nicht wie dies funktionieren sollte. Das wäre der Befehl:

C++:
system(" start C:\\Users\\"  username  "\\Desktop\\AdSoleWare_Setup\\ASW-TE.bat");

"username ist die Variable die zwischen 'Users\\' und '\\Desktop' eingesetzt werden soll.
 

cwriter

Erfahrenes Mitglied
Also ich möchte in der Funktion system("start") eine Variable einbauen
Nö, möchtest du nicht.

weiß aber leider nicht wie dies funktionieren sollte
C++ oder C?

C++:
system(std::string("start C:\\Users\\" + std::string(username) +  "\\Desktop\\AdSoleWare_Setup\\ASW-TE.bat").c_str());

C:
char tmp[512]; //MUSS gross genug für den Pfad sein
sprintf(tmp, "start C:\\Users\\%s\\Desktop\\AdSoleWare_Setup\\ASW-TE.bat", username);
system(tmp);

Erläuterung dazu, warum du das nicht willst: system() ist weder wartbar, noch Plattformunabhängig, noch garantiert es irgendetwas (eigentlich sollte es mittlerweile entfernt werden, man kann damit ziemlichen Quatsch anstellen).

Für Windows bieten sich diese Optionen an:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb776886(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx

Gruss
cwriter
 

Prestige__

Mitglied
Also das heißt, ich müsste das so verwenden wenn ich das richtig verstanden habe:

C++:
CreateProcess(STARTP("ASW-TE"), 
            STARTP("C:\\Users\\%s\\Desktop\\AdSoleWare_Setup\\ASW-TE.bat"),

und das '%s' ergänzt den Nutznamen oder ist das falsch?
 

cwriter

Erfahrenes Mitglied
und das '%s' ergänzt den Nutznamen oder ist das falsch?
Nein, das %s ist dasselbe wie bei printf und scanf und kann entsprechend auch nur bei dieser Familie verwendet werden.

Hier hat es ein Beispiel:
https://stackoverflow.com/questions/25919451/use-createprocess-to-run-a-batch-file

Für "normale" Bytestrings kannst du CreateProcessA verwenden, also etwa so (Ungetestet):

C++:
    STARTUPINFO si = { sizeof(STARTUPINFO) };
    PROCESS_INFORMATION pi;
    if (!CreateProcessA(NULL, std::string("Pfadteil1" + std::string(username) + "Pfadteil2").c_str(), NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,
       NULL, NULL, &si, &pi))
   {
       std::cout << GetLastError();
       abort();
   }

Den String kannst du dir auch mit sprintf o.ä. zusammenbauen.

Gruss
cwriter
 

Prestige__

Mitglied
Okay ich werde das jetzt mal ausprobieren.

Und ich schreibe in C++.
Hab leider bei der vorherigen Antwort vergessen dies dazu zu schreiben ^^.

aja die 'std::' kann ich ja weglassen ohne auswirkung stimmts? Habe nämlich beim Code 'using namespace std;;' hinzugefügt.
 

cwriter

Erfahrenes Mitglied
aja die 'std::' kann ich ja weglassen ohne auswirkung stimmts? Habe nämlich beim Code 'using namespace std;;' hinzugefügt.
Kannst du, ja.
Generell wird using namespace nur empfohlen, wenn man wirklich sehr viel aus dem namespace benutzt, und am liebsten im möglichst engsten Scope (= Funktion).
Der Grund ist Namespace pollution:
Praktisch jede Library hat einen eigenen Stringtyp. Manche differenzieren noch mit Gross-/Kleinschreibung, aber wenn sf::String und std.:string durch using namespaces in den globalen Namespace gemappt werden, dann ist String und string schwer auseinanderzuhalten.
Daher: Zurückhaltung mit using namespace ist nie falsch.

Gruss
cwriter
 

Prestige__

Mitglied
In der Konsolenanwendung kommt sehr oft 'cout' vor. Da lohnt es sich meiner Meinung schon bei dieser einen Anwendung zu verwenden.

So.... Teil 2 :D...

Also ich hab das jetzt alles so eingebaut und etwas klappt da nicht so wie es sollte. Hier mal ein größerer Ausschnitt:

C++:
            if( number ==5) {
                  Beep(600, 400);
                  Beep(600, 400);
                  Beep(500, 100);
                  Beep(850, 200);
                  Beep(1000, 300);
                  system("cls");
                  cout << endl;
                  cout << " \033[32m\033[1mThe AdSoleWare Task Executer will check you installation.";
                  cout << " If something is missing or wrong the AdSoleWare Task Executer [ASW-TE] will";
                  cout << " fix or repair it. Important! For the ASW-TE you have to set your license key!";
                  cout << " You can set your license and update key in the main menu with the option";
                  cout << " '\033[35m1\033[32m\033[1m' and '\033[35m2\033[32m\033[1m'." << endl;
                  cout << endl;
                  cout << " Please enter your Username: Example: David (C:\ Users\ \033[35mDavid\033[32m\033[1m). Your Username:" << endl;
                  cin >> username;
                  cout << endl;
                  cout << " Thank you! Press any key to continue...";
                  cin.clear();
                  cin.ignore();
                  cin.get();

                  STARTUPINFO si = { sizeof(STARTUPINFO) };
                  PROCESS_INFORMATION pi;
                    if (!CreateProcessA(NULL, string("C:\\Users\\" + string(username) + "\\Desktop\\AdSoleWare_Setup\\ASW-TE.bat").c_str(), NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,
                        NULL, NULL, &si, &pi))
                   {
                        std::cout << GetLastError();
                        abort();
                   }

                  fstream f;
                  f.open("username.dat", ios::out);
                  f << username;
                  f.close();

Ich brauche das 'system("start")' oder 'CreateProcessA' um eben ein Tool, also eine Batch-Datei auszuführen. Ist der Code mit dem Pfad so richtig geschrieben?

Das hier wäre die Fehlermeldung :

Code:
||=== Build: default in AdSoleWare Setup (compiler: GNU GCC Compiler) ===|
C:\Users\Marcel\Desktop\AdSoleWare Development\AdSoleWare Application\adsoleware\AdSoleWare Setup.cpp||In function 'int main()':|
C:\Users\Marcel\Desktop\AdSoleWare Development\AdSoleWare Application\adsoleware\AdSoleWare Setup.cpp|363|warning: unknown escape sequence: '\040'|
C:\Users\Marcel\Desktop\AdSoleWare Development\AdSoleWare Application\adsoleware\AdSoleWare Setup.cpp|363|warning: unknown escape sequence: '\040'|
C:\Users\Marcel\Desktop\AdSoleWare Development\AdSoleWare Application\adsoleware\AdSoleWare Setup.cpp|373|warning: unknown escape sequence: '\A'|
C:\Users\Marcel\Desktop\AdSoleWare Development\AdSoleWare Application\adsoleware\AdSoleWare Setup.cpp|373|error: invalid conversion from 'const char*' to 'LPSTR {aka char*}' [-fpermissive]|
C:\Program Files (x86)\CodeBlocks\MinGW\include\winbase.h|1392|note: initializing argument 2 of 'BOOL CreateProcessA(LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, PVOID, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION)'|
||=== Build failed: 1 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|
 
Zuletzt bearbeitet:

cwriter

Erfahrenes Mitglied
Das hier wäre die Fehlermeldung
Deine Farbcodes sind nicht wirklich Standard, daher unknown escape sequence: \040.
Ein Backslash sollte verdoppelt werden, daher ist \A unknown, es sollte \\ASW-TE.bat sein (doppelter \, was du ja auch schon festgestellt hast).

Das mit dem const char*: Mach es einfachkeitshalber dreckig mit char*-cast, da die CreateProcessA-Variante gemäss Dokumentation das Argument nicht schreiben wird. Nicht schön, aber legal.

Du musst allerdings noch ein "cmd.exe /C " vor den Pfad setzen, damit es funktioniert (wie im Link).

Gruss
cwriter
 

Prestige__

Mitglied
Okay und... wie mache ich dies mit dem 'char*-cast'? Hättest du vielleicht ein Beispiel zum Code?

Die Farbcodes sind mit einer eigenen Header Datei eingebunden. Und laut der IDK ist der Fehler nur in der Zeile:

C++:
if (!CreateProcessA(NULL, string("C:\\Users\\" + string(username) + "\\Desktop\\AdSoleWare_Setup\\ASW-TE.bat").c_str(), NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,

Mit dem 'cmd.exe /C'.... sollte das so aussehen?

C++:
if (!CreateProcessA(NULL, string("cmd.exe /C C:\\Users\\" + string(username) + "\\Desktop\\AdSoleWare_Setup\\ASW-TE.bat").c_str(), NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,

Ich habe geschaut aber keinen wirklichen Fehler gefunden (der Code ist von vorher, muss das mit 'cmd.exe /C' noch testen
 

cwriter

Erfahrenes Mitglied
Okay und... wie mache ich dies mit dem 'char*-cast'? Hättest du vielleicht ein Beispiel zum Code?
Wider besseren Wissens:
C++:
if (!CreateProcessA(NULL, (char*)string("cmd.exe /C C:\\Users\\" + string(username) + "\\Desktop\\AdSoleWare_Setup\\ASW-TE.bat").c_str(), NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,NULL, NULL, &si, &pi))

Was ein Cast ist: Bitte suchen.

Eigentlich ist es ein bisschen gefährlich, ohne Kenntnis der Grundlagen mehr als Beispielprogramme zu machen. Casts, Funktionen und Pointer sind schlicht Grundlagen, ohne die alles andere schwierig ist.

Gruss
cwriter