blockierendes Shellexecute



  • Hallo,

    ich suche schon geraume Zeit um mit Shellexecute, WinExec o. CreateProcess einen blockierenden Aufruf eines externen Programmes zu starten, finde jedoch die Parameter dafür nirgends.
    Ich vermute, es hat zumindest bei Shellexecute etwas mit dem Handle zu tun, bin mir aber nicht sicher....
    Ich möchte ein kleines Konsolenprogramm aufrufen, und die Aufrufende Applikation soll solange warten, bis die Konsole terminiert. Dafür muss ja der Programmausführungszeiger der Hauptapplikation an die Konsole übergeben werden, oder liege ich da falsch?

    Weiß jemand wie das geht?

    Ich nutze Borland c++ 2006

    Gruß,
    R



  • ShellExecuteEx
    WaitForSingleObject



  • vielen Dank!



  • Es sei mir bitte noch eine Frage erlaubt:
    Wie kann ich mit ShellexecutEx die Prozesspriorität des erzeugten Prozesses beeinflussen?
    Momentan rufe ich so das Unterprogramm (Konsolenanwendung) auf. Ich möchte gerne diesem Unterprogramm nur IDLE-CPU-Zeit gewähren...

    SHELLEXECUTEINFO ExecInfo1;
    		HWND h1;
    		ExecInfo1.cbSize = sizeof(SHELLEXECUTEINFO);
    		ExecInfo1.fMask = SEE_MASK_NOCLOSEPROCESS;
    		ExecInfo1.hwnd = GetActiveWindow();
    		ExecInfo1.lpVerb = "open";
    		ExecInfo1.lpFile = "cmd.exe";
    		ExecInfo1.lpParameters = options.c_str();
    		ExecInfo1.nShow = SW_SHOW;
    		ExecInfo1.hInstApp = h1;
    		ShellExecuteEx(&ExecInfo1);
    		WaitForSingleObject(ExecInfo1.hProcess, INFINITE);
    

  • Mod

    Was bezweckst Du damit?
    Wenn kein anderer Prozess was zu tun hat und Deiner hat was zu tun, dann bekommt er alles was er braucht.

    Das rumspielen in den Prozessprioritäten macht IMHO gar keinen Sinn für normale Programme. Es macht evtl. Sinn für manche Threads...

    Ansonsten hast Du SetPriorityClass und das Handle des Prozesses hast Du auch:
    http://msdn2.microsoft.com/en-us/library/ms686219(VS.85).aspx

    Aber beantworte erstmal die Frage: Was bezweckst Du damit?
    Ich vermute Du liegst mit einigen Annahmen über die Funktionesweise von Windows falsch.



  • Hallo,

    natürlich ist es möglich, dass meine Annahmen zur Funktionsweise von Windows falsch sind, ist aber für meinen Fall hier eigentlich unerheblich.

    Hintergrund der Frage ist folgende:
    Ich habe Fernzugriff auf einen Windowsrechner, auf dem ein Apache, Datenbank und regelmäßige nächtliche Backups laufen. Weiterhin ist ein FTP-Server installiert.
    Die meiste Zeit liegt die CPU-Auslastung bei 20-30% und 70-80% liegen brach.

    Ich würde nun gerne CPU-Intensive Tasks auf diesem Rechner ausführen und somit die brachliegenden Ressourcen nutzen, ohne dass der Betrieb der sonstigen Aufgaben im geringsten beeinträchtigt wird.
    Deswegen möchte ich den Childprozessen die Priorität IDLE geben, und nehme damit natürlich in Kauf, dass diese Prozesse eventuell stehen bleiben, nämlich wenn andere höherprioritäre Tasks die CPU-Zeit brauchen.

    Ich glaube, dass sich die Zuweisung der CPU-Zeit wie folgt "funktioniert":
    100% der CPU wird verteilt auf n Tasks. Task 0 ist der sog. Idletask.
    Die Tasks 1 bis n haben Prioritäten 1 bis 5 (glaube ich).
    Wie jetzt genau sich der Anspruch der Tasks auf die CPU-Zeit errechnen läßt, weiß ich nicht, aber es hat mit der Anzahl, den Prioritäten, und der Tatsächlich genutzten CPU-Zeit zu tun. Da gibt es sicher eine Formel für, um das auszurechnen. Wenn aber 5 Tasks gleicher Priorität sehr viel rechnen müssen, so bekommen alle Fünf 20%.

    Liege ich mit diesem o.a. Schrieb gar sehr falsch? 😉

    Gruß
    R


  • Mod

    Deine Annahme ist falsch.

    Grob erklärt: Wenn ein Thread mit höherer Prio da ist bekommt er die Prozessorzeit! Sind immer Prozesse mit höherer Prio vorhanden, die Rechenzeit wollen, dann kommen Prozesse niedrriger Prio nie an die Reihe!
    Für jede Threadprio gibt es eine Liste von Threads die warten. Windows nimmt einfach die erste nicht leer Queue mit der höchsten Prio und den ersten Thread und aktiviert ihn...
    (und ja es gibt einen prioboost für lamg wartende Threads)

    Wenn kein Thread da ist der was rechnen will, passiert auch nichts.
    Wenn also Dein Prozess nur wartet "WaitForSingleObject" bekommt er niemals Rechenzeit!
    Wenn Du also Rechenzeit freigeben willst für andere Prozesse, dann lege Deine Threads und Prozesse so an, dass sie WaitForSingleObject/GetMessage etc verwenden. Dann machen Sie nur dann etwas, wenn auch was zu tun ist.

    Siehe:
    http://mirror.sweon.net/madchat/vxdevl/papers/winsys/wk_internals/threadscheduling.pdf
    http://www.microsoft.com/mspress/books/sampchap/4354c.aspx



  • Hallo Martin,

    vielen Dank für die Links, die werde ich mir heute Abend einmal durchlesen. Bevor ich dies aber mache, erlaube mir bitte noch eine kurze Frage:

    Martin Richter schrieb:

    Wenn also Dein Prozess nur wartet "WaitForSingleObject" bekommt er niemals Rechenzeit!

    Aber doch nur wenn man davon ausgeht, dass andere Prozesse permanent 100% brauchen, oder?
    Da bei mir die CPU-Auslastung bei 20-30% liegt, würden in 70-80% der Fälle (Takte, Zuweisungsoperationen oder wie immer man das bezeichnen mag) die Queues der höherwertigen Prozesse leer sein, und somit mein Idle-Prozess ganz unten drankommen, oder nicht?

    Gruß
    R


  • Mod

    Mit WaitForSingleObject bekommt er niemals Rechenzeit!

    Vielleich verstehe ich Dich nicht ganz:
    Wenn Dein Prozess 20%-30% braucht, dann braucht er die auch, wenn Du ihn niedriger einstufst! Er kommt evtl. nur seltener dran. Da aber 80% Deiner Kapazität brach liegt würde Dein Prozess selbst in niedrigster Stufe 20%-30% fressen!



  • Nein, Nein, die 20-30% Systemauslastung sind ohne meine Tasks.
    Also System, Datenbank, Webserver und FTP-Server verursachen eine Auslastung von 20-30%.

    Die verbleibenden 70%-80% wollte ich mit meiner Anwendung benutzen. Diese sollten auch den Idle-Prozessen also ganz unten in der Hackordnung zur Verfügung stehen.

    Naja, vielen Dank jedenfalls für den Hinweis auf SetPriorityClass.
    Ich mache es jetzt so:

    void call_external_program(AnsiString command)
    {
    		SHELLEXECUTEINFO ExecInfo;
    		HWND h;
    		ExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    		ExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    		ExecInfo.hwnd = GetActiveWindow();
    		ExecInfo.lpVerb = "open";
    		ExecInfo.lpFile = "cmd.exe";
    		ExecInfo.lpParameters = command.c_str();
    		ExecInfo.nShow = SW_SHOW;
    		ExecInfo.hInstApp = h;
    		[b]SetPriorityClass( ExecInfo.hProcess, IDLE_PRIORITY_CLASS );[/b]
    		ShellExecuteEx(&ExecInfo);
    		WaitForSingleObject(ExecInfo.hProcess, INFINITE);
    }
    


  • void call_external_program(AnsiString command)
    {
            SHELLEXECUTEINFO ExecInfo;
            HWND h;
            ExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
            ExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
            ExecInfo.hwnd = GetActiveWindow();
            ExecInfo.lpVerb = "open";
            ExecInfo.lpFile = "cmd.exe";
            ExecInfo.lpParameters = command.c_str();
            ExecInfo.nShow = SW_SHOW;
            ExecInfo.hInstApp = h;
            SetPriorityClass( ExecInfo.hProcess, IDLE_PRIORITY_CLASS );// hier ist hProcess noch nicht gültig!!!
            ShellExecuteEx(&ExecInfo); // nach diesem Aufruf ist hProcess gültig!!!
            WaitForSingleObject(ExecInfo.hProcess, INFINITE);
    }
    

    Siehe Kommentare.



  • Danke für den Hinweis - hätte ich nicht sofort bemerkt! 😃


Anmelden zum Antworten