Seite 1 von 1

Externes Programm starten unter Linux ohne Qt

Verfasst: 8. September 2008 19:53
von FaS
Hallo!

Ich möchte unter Linux ohne Qt-Bibliotheken zu benutzen ein externes Programm starten, nicht blockierend, und in einem anderen Verzeichnis.

Unter Windows funktioniert folgender Code:

Code: Alles auswählen

#include <windows.h>

int main( int argc, char ** argv )
{
  STARTUPINFOA stStartUp;
  PROCESS_INFORMATION stProcInfo;
  memset(&stStartUp, 0, sizeof (stStartUp));
  stStartUp.cb = sizeof(stStartUp);
  
  if( !CreateProcessA(
    "<program>", 0, 0, 0, TRUE, DETACHED_PROCESS, 0,
    "<directory>", &stStartUp, &stProcInfo
    ) )
    return EXIT_FAILURE;
  return EXIT_SUCCESS;
}
Hab für Linux provisorisch das versucht, aber der wechselt nicht in das Verzeichnis, sagt jedenfalls das aufgerufene Programm:

Code: Alles auswählen

int main( int argc, char ** argv )
{
  system("cd <directory>");
  system("<program>");
  return EXIT_SUCCESS;
}
Danke,
FaS

Verfasst: 9. September 2008 10:21
von RHBaum
das system startet eine eigene Prozessumgebung ....
jede prozessumgebung bekommt alle Umgebungsvariablen kopiert, vom aufrufenden prozess. Wenn du also innerhalb deines systems das aktuelle verzeichnis wechselst, gilt das nur in dem prozess. nach beenden (system kehrt zurueck) werden die prozessumgebung und damit alle variablen verworfen ....

Das ist der Grund, warum dein verzeichnisswechseln da ned funktioniert !

Loesungsmöglichkeiten:
- das aktuelle verzeichniss fuer den aufrufenden Prozess schon aendern, so das das korrekte verzeichnis an den (bei dir) 2. sytemaufruf kopiert wird. Siehe posix funktionen (chdir oder ähnlich muesste die heissen) an.

- den systemaufruf fuer dein programm in einen fork und exec aufruf aufspalten. bei den exec varianten gibt es eine version wo man nen eigenes set an umgebungsvariablen definieren kann

- dein programm ned direkt sondern ueber ne batch/script aufrufen wo das verzeichniss einstellst und das wiederum ueber dein system ...

Ciao ...

Verfasst: 9. September 2008 14:46
von FaS
nach beenden (system kehrt zurueck) werden die prozessumgebung und damit alle variablen verworfen ....
Tja das geschieht aber garnicht ;-) Der bleibt bei system("<program>"); hängen, bis das aufgerufene Programm beendet wird.

Trotzdem, mit chdir() funktioniert das. Aber nicht so ganz wie ich das mir gewünscht habe:
a) Mit system() wird ein neuer Unterprozess erstellt, der aufrufende bleibt als übergeordneter bestehen.
b) Mit execv() wird der aktuelle Prozess quasi mit dem neuen überschrieben, in ps wird aber der aufrufende angezeigt und nicht der neue.
c) In fork() sehe ich keinen Nutzen, der aufrufende Teilprozess wird zwar beispielsweise die Konsole freigeben (blockiert also nicht, das ist ja gut), aber Ausgaben werden trotzdem auf sie geleitet, und die Unschönheiten aus a) oder b) sind noch da.

Naja wenns nicht anders geht, auch nicht soo wild..
Danke für deine Vorschläge!

Hab dann aber noch eine Frage zu execv():

Code: Alles auswählen

int main( int argc, char **argv )
{
  chdir( "bin/linux" );
  return execv( "Food", argv );
}
Der Parameter-Vektor sollte ja nach pronix.de nullterminiert sein (also der Vektor, nicht die Strings (die sowieso)). Nun denke ich, ist dies argv nicht, deshalb gibt es ja argc, oder? Trotzdem gibt es einige Beispiel im Netz, wo argv einfach übergeben wurde. Geht das nun doch?

Verfasst: 9. September 2008 15:00
von macman
FaS hat geschrieben:Tja das geschieht aber garnicht ;-) Der bleibt bei system("<program>"); hängen, bis das aufgerufene Programm beendet wird.
Du weißt aber schon das man unter Linux einen Process im Hintergrund starten kann, oder? Wie war das noch gleich? Mit einem & hintendran? Ist schon zu lange her :-(

Verfasst: 9. September 2008 15:08
von FaS
Ach mann. Zu lange.

Also ich bin nun zufrieden. Falls jemand das mit dem argv für die Nachwelt klären möchte, lasse ich den Thread mal noch ungelöst..