"explorer.exe" per CreateProcess öffnet Arbeitsplatz
-
Normalerweise legt man den Primären Desktop fest auf dem dann auch der Taskbar erscheint.
Zudem, wie bitte schaftst Du es, dass ein neuer Explorer mit Taskbar erzeugt wird, wenn ein Prozessbereits besteht?
Den Taskbar kann man nicht zweimal starten... oder schießt Du den ab?Das wäre natürlich ein ganz mieses Ding.
-
Jeder Desktop kann einen eigenen explorer.exe Prozess mit eigener Taskleiste haben. Auf diese Weise funktioniert auch "Desktops" von Sysinternals.
-
desktops schrieb:
Jeder Desktop kann einen eigenen explorer.exe Prozess mit eigener Taskleiste haben. Auf diese Weise funktioniert auch "Desktops" von Sysinternals.
Upps. Ich habe das mit Monitoren verwechselt... Monitor!=Desktop...
Sorry!
-
desktops schrieb:
Poste mal deinen Code. Ich habe mal genau dasselbe ausprobiert und es hat funktioniert, dass der neue Desktop dann eine Taskleiste hatte. Vielleicht hast du irgendetwas anders gemacht.
ZeroMemory(&_explorerSI, sizeof(_explorerSI)); ZeroMemory(&_explorerPI, sizeof(_explorerPI)); _explorerSI.cb = sizeof(_explorerSI); _explorerSI.lpTitle = _deskName; _explorerSI.lpDesktop = _deskName; // _explorerSI.wShowWindow = SW_HIDE; // ÄNDERT LEIDER NICHTS! _deskHandle = CreateDesktop(_deskName, NULL, NULL, 0, GENERIC_ALL, NULL); CreateProcess(NULL, _explorerPath, NULL, NULL, false, 0, NULL, NULL, &_explorerSI, &_explorerPI);
Das ist in der Funktion prepare() Funktion meiner Klasse VirtualDesk. Die Membervariablen werden per Konstruktor gesetzt. Mit prepare() wird der neue, virtuelle Desktop nur noch vorbereitet für den Gebrauch.
Kannst du mal deine Funktion posten, dann kann ich die mit meiner Klasse abgleichen
Bei mir klappt auch alles! Der Desktop wird erstellt, mit SwitchDesktop(HDESK) und SetThreadDesktop(HDESK) wird auch tatsächlich zum Desktop gewechselt.
!NUR! dieses blöde Arbeitsplatz/Bibliotheken Fenster nervt!
Wie ich eben festgestellt habe, öffnet sich das besagte Fenster nur, wenn ich das Programm mehrmals starte.Meine Theorie ist, dass der Prozess, den ich erstelle, nachdem der Desktop geschlossen wurde, immernoch existiert. Aber auch wenn ich ihn mit TerminateProcess(HANDLE, UINT) beende, ändert sich nichts an meinem Endproblem. Habe ich keine Rechte, um die explorer.exe zu beenden?
Danke fürs Lesen und eine ruhige und schöne Nacht noch
DerCoder
-
Auf jeden Fall gilt, dass ein Desktop solange existiert, bis alle Prozesse auf diesem Desktop beendet wurden und alle Handles zu dem Desktop geschlossen wurden. Das solltest du auf jeden Fall bedenken, wenn du weiter an deinem Programm arbeitest.
Dein Problem mit TerminateProcess resultiert wahrscheinlich daraus, dass TerminateProcess nur das Beenden des Prozesses einleitet, nicht aber darauf wartet, bis der Prozess beendet wurde. Du solltest also nach dem TerminateProcess noch mit WaitForSingleObject auf das Ende des Prozesses warten.
Hast daran gedacht, am Ende alle Handles der PROCESS_INFORMATION Struktur zu schließen?
-
Okay, das klingt logisch.
Wenn der Desktop wieder gelöscht werden soll, muss die destroy() Funktion aufgerufen werden, die wie folgt aussieht:
TerminateProcess(_explorerPI.hProcess, 0); WaitForSingleObject(_explorerPI.hProcess, 3000); // Soll ich INFINITE nehmen? CloseDesktop(_deskHandle); CloseHandle(_deskHandle); CloseHandle(_explorerPI.hProcess); CloseHandle(_explorerPI.hThread);
Gibt es eigentlich eine Funktion, mit der ich alle Prozesse, die auf einem Desktop laufen, enumerieren kann? Was ich nämlich damit erreichen möchte, ist, dass wenn der Desktop mit destroy() oder dem Destruktor gelöscht wird, die laufenden Prozesse "gesichert" werden und auf den Hauptdesktop verschoben werden.
Achja, was mir grad auch noch einfällt: Wenn mein Programm beendet wird und bereits auf einen anderen Desktop gewechselt wurde (also der aktuelle Desktop ist nicht der Hauptdesktop!!!), wie komme ich dann an das Handle des Hauptdesktops bzw. kann ich überhaupt noch auf den Hauptbildschirm wechseln?
Das sind wieder ne Menge Fragen, aber ich habe leider im Internet keine Antworten darauf gefunden.
Danke und liebe Grüße, DerCoder
-
Also ich würde schon einen Timeout für WaitForSingleObject nehmen, vielleicht 5000 Millisekunden. Aber das musst du selbst entscheiden.
Den Handle des Hauptdesktops bekommst du, indem du den Desktop mit dem Namen "Default" mit OpenDesktop öffnest. Alternativ kannst du den Desktop, auf dem dein Prozess gestartet wurde, mit GetThreadDesktop abfragen.
Die Prozesse auf einem bestimmten Desktop abzufragen scheint ziemlich schwierig zu sein. Du musst alle Prozesse durchlaufen (mit CreateToolhelp32Snapshot, Process32First und Process32Next) und bei jedem Prozess prüfen, ob der Prozess zu deinem Desktop gehört. Dann musst du die Threads durchlaufen (CreateToolhelp32Snapshot, Thread32First, Thread32Next). Du kannst dann mit GetThreadDesktop einen Handle zu dem Desktop eines Threads bekommen. Mit diesem Handle kannst du den Namen des Desktops bekommen, indem du GetUserObjectInformation mit nIndex auf UOI_NAME gesetzt aufrufst. Diesen Namen musst du dann case insensitive mit Namen deines Desktops vergleichen.
Soweit ich weiß, ist es nicht möglich, den Desktop, auf dem ein fremder Prozess läuft zu ändern. SetThreadDesktop funktioniert ja auch nur mit eigenen Threads. Und wenn ein Fenster auf einem bestimmten Desktop erstellt wurde, kann es dann auch nicht plötzlich auf einen anderen Desktop verschoben werden.
-
Tausend Dank für deine ausführlichen Erläuterungen!
Ich habe ein Timeout von 5000ms probiert und auch INFINITE... nichts.
Der von mir erstellte Prozess wird partout nicht beendet. Mir fallen absolut keine weiteren Ideen ein.Kann ich eigentlich alle offenen Desktops abfragen?
-
Das kann ich mir dann auch nicht erklären.
Alle Desktops kannst du mit EnumnDesktops durchlaufen.
-
Alles klar!
Du weißt gar nicht, wie dankbar ich dir für deine ausführlichen Beiträge bin. Du hast mir wirklich viel weiter geholfenSuper Forum, super Member!
Liebe Grüße, DerCoder