Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Nachricht auf allen Desktops anzeigen - und wieder schließen (https://www.delphipraxis.net/117589-nachricht-auf-allen-desktops-anzeigen-und-wieder-schliessen.html)

xpmd 21. Jul 2008 15:54


Nachricht auf allen Desktops anzeigen - und wieder schließen
 
Hi Leute, ich habe ein Problem vor dem ich bereits seit einer Woche sitze. Mittlerweile sind mir die Lösungsansätze ausgegangen, vielleicht weiß ja jemand den "Trick", den ich benötige.

Das Problem bezieht sich rein auf Windows Vista. Unter Windows XP hat jeder der Lösungsansätze funktioniert. Drum poste ich jetz auch mal keien Code, da das Problem bei der Vorgehensweise sitzt und nicht im Code selbst.

Aufgabe:
Ich habe einen Dienst unter dem lokalen SYSTEM Account laufen. Dieser Dienst soll eine Nachricht z.B. MessageBox in JEDER aktiven Terminal-Session, der interaktiven Console sowie dem Logon-Screen anzeigen. Anschließend muss der Dienst dieses Fenster aber auch automatisch Schließen können. Und genau beim Schließen liegt das Problem!

Lösungsansatz 1:
Über WTSEnumSessions alle aktiven Terminal-Sessions auslesen. An jede Session dann per WTSSendMessage und MB_SERVICE_NOTIFICAION eine Nachricht schicken. Funktioniert soweit Prima - sowohl XP und Vista zeigen die Nachricht überall wie gewünscht an. Problem ist nun das Fenster wieder zu schließen: Ich habe probiert über EnumDesktops / OpenDesktop / EnumDesktopWindows alle Fenster durchzulaufen und das Entsprechende dann per PostMessage->WM_CLOSE zu schließen. Unter XP kein Problem. Unter Vista gibts aber, dank der Isolation der Session 0, keinen Zugriff auf die MessageBox. Auch SetThreadDesktop hilft nicht bzw schlägt fehl.

Lösungsansatz 2:
Habe nun einen Trick versucht: Die Funktion welche alle Desktops/Fenster durchläuft und das Nachrichtenfenster schließen soll, wurde in eine separate Exe ausgelagert. Anschließend wird für jede aktive Terminal-Session über WTSQueryUserToken der User ermittelt und mit CreateProcessAsUser diese Schließen-Exe unter jedem angemeldeten User gestartet. Geht unter Vista leider auch nicht, Die EnumDesktopWindows listet die MessageBox nicht auf.

Lösungsansatz 3:
Die Nachricht nicht per WTSSendMessage sondern als eigene Form anzeigen. EnumDesktops ermittelt alle aktiven Desktops. Anschließend wird für jede anzuzeigende Nachricht ein Thread gestartet, welcher mit SetThreadDesktop den jeweiligen Desktop setzt und die Form anzeigt. Anschließend wartet der Thread auf eine interne Nachricht um sein eigenes Fenster wieder zu schließen. Funktioniert unter XP wieder wunderbar. Unter Vista wird der Default-Desktop zwar übernommen, das Fenster erscheint allerdings nicht.

Ich bin am verzweifeln. Weiß evtl jemand noch einen Lösungsansatz? Für Ideen wäre ich sehr dankbar!

md

Apollonius 21. Jul 2008 15:59

Re: Nachricht auf allen Desktops anzeigen - und wieder schli
 
Die Ansätze 1 und 3 können gar nicht funktionieren: Die TS eines Prozesses kann nicht geändert werden.
Der Ansatz 2 ist korrekt. Hast du in der StartupInfo-Struktur Desktop und Window-Station angegeben? Hast du im Token die SessionID gesetzt?

xpmd 21. Jul 2008 16:11

Re: Nachricht auf allen Desktops anzeigen - und wieder schli
 
Merci für die flotte antwort. :thumb:

Ne hab ich nicht gemacht :oops: Werds morgen mal probieren und gib dann bescheid. Für heute hab ich erstmal genug :lol:

gore 21. Jul 2008 16:20

Re: Nachricht auf allen Desktops anzeigen - und wieder schli
 
> Die TS eines Prozesses kann nicht geändert werden.

Ich bin der Meinung, dass ich darüber schon was gelesen habe (ging evt. via einer WTS Funktion). Ich würde in jede aktive Session eine ShowAndCloseMsgbox.exe via CreateProcessAsUser injizieren. Datenaustausch zum Service via named pipes.

Apollonius 21. Jul 2008 16:24

Re: Nachricht auf allen Desktops anzeigen - und wieder schli
 
Ja und? Die TS eines neuen Prozesses wird mit dem Token festgelegt - sobald der Prozess läuft, ist sie fest. Nichts anderes habe ich behauptet.

NickelM 21. Jul 2008 17:41

Re: Nachricht auf allen Desktops anzeigen - und wieder schli
 
Sagt mal kann mann nicht vieleicht das Massage-Fenster mit dem WinSpy Programm von dem einem hier im Forum (sorry für das anreden, aber ich weiß grad net wer das nochmal war) verwenden und mal starten und versuchen das Handle rauszufinden und dan mit ShowWindow(Handle, sw_close); (soviel ich jetzt aus Kopf weiß) wieder schließen?????

Oder bin ich da voll auf dem Holzweg :oops:

Dezipaitor 21. Jul 2008 22:37

Re: Nachricht auf allen Desktops anzeigen - und wieder schli
 
Schreibe einen eigenen Prozess, der die Nachricht anzeigt und dann sich später selbst beendet.

Und dazu nehme:
Jwscl implementiert JwCreateProcessInSession

Die aktualisierte Version im SVN trunk Ordner funktioniert auch unter Windows 2000 Workstation.

Delphi-Quellcode:
{[B]JwCreateProcessInSession[/B] creates a new process in a user's session using various ways to
achieve success.
This procedure needs JwInitWellKnownSIDs to be called.
To run a process in another session you need to have SYSTEM rights.


@param ApplicationName defines the application to be run in the session
@param CommandLine defines the parameters for the application
@param CurrentDirectory defines the start folder of the app.
@param SessionID defines the target session where the new application is to be started.
@param CreationFlags defines creation flags that are delivered to CreateProcess parameter with
 same name
@param Desktop defines the target windowstation and desktop name. If empty
the default target is "winsta0\default"
@param StartupInfo defines startup info delivered to to CreateProcess parameter with
 same name. Don't forget to initialize the structure first before calling this procedure.
<code lang="delphi>
ZeroMemory(@StartupInfo, sizeof(StartupInfo));
</code>
@param WaitForProcess defines whether the procedure should wait for the process to end
and clean up all allocated resources or just return to the caller. In last case
the caller is responsible to free the returned token, the environment block and
the users profile
@param Output contains returned data in case parameter WaitForProcess is false.
The caller is responsible to free the contained member allocation
@param LogServer receives a log server instance. It is used to log events for
mostly debugging purposes. If this parameter is nil, no events are logged  

raises
 EJwsclProcessIdNotAvailable: will be raised if no token could be found
for the given SessionID
 EJwsclNilPointer: will be raised if JwInitWellKnownSIDs was not called before
}

new32 22. Jul 2008 20:51

OT: Nachricht auf allen Desktops anzeigen - und wieder schli
 
Zitat:

Zitat von Apollonius
Die TS eines neuen Prozesses wird mit dem Token festgelegt

Das Access-Token eines Prozesses lässt sich allesdings auch nach Prozessbeginn ändern! :wink:

Dezipaitor 22. Jul 2008 22:38

Re: OT: Nachricht auf allen Desktops anzeigen - und wieder s
 
Zitat:

Zitat von new32
Das Access-Token eines Prozesses lässt sich allesdings auch nach Prozessbeginn ändern! :wink:

Das funktioniert jedoch nicht mehr in Vista. Es geht nur solange der Prozess noch nicht gestartet wurde (CREATE_SUSPENDED)
und dann nicht mehr.

Apollonius 22. Jul 2008 23:23

Re: Nachricht auf allen Desktops anzeigen - und wieder schli
 
Klar lässt sich das Token ändern. Ein eventuelles Ändern der Session-ID wirkt sich aber nicht auf den Prozess aus. Es würde zu arg abstrusen Effekten führen, wenn man die Session eines Prozesses ändern könnte, während er läuft. Denk nur mal daran, dass er ein Handle zu einem Session-lokalen Objekt (z.B. Desktop) haben könnte. Dieses Handle verlöre seinen Sinn.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:49 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz