.NET
VB.NET: Eigene oder Fremde Prozesse vor dem Benutzer verstecken
Posted on .In diesem Beitrag gehts es darum wie man Programme bzw Prozesse vor dem Benutzer verstecken kann. Ich hatte schon oft den fall, dass ein bestimmtes Programm unbedingt laufen musste, und keine Funktion bat, die es ausblenden ließ. Diese Anwendung nahm dann auchnoch Platz inder Taskleiste weg und man lief Gefahr, diese ausversehen zu beenden.
Dieses Problem kann man natürlich sehr einfach lösen, indem man diese Anwendung ausblendet! Was bei Mac OS mit einem einfachen Rechtsklick geht muss man bei Windows leider selbst machen. Aber gut, erstellen wir ein neues Windows Forms Projekt und plazieren auf dem Formular zwei Buttons und zwei Listbox – Objekte! (Siehe Bild)
Die Obere Liste soll uns später alle sichtbaren Fenster anzeigen und die untere alle von uns Versteckten.
Freundlicherweise stellt und Microsoft in der Win32 API eine Funktion zur Verfügung, die uns viel Arbeit erspart und das Verstecken der Fenster für uns übernimmt! Die Funktion die wir brauchen befindet sich in der User32.dll und nennt sich ShowWindow. Diese müssen wir ersteinmal importieren:
Imports System.Runtime.InteropServices Public Class frmMain _ Public Shared Function ShowWindow(ByVal hWnd As IntPtr,_ ByVal nCmdShow As Integer) As Long End Function End ClassDiese Funktion benötigt zwei Parameter, erstens ist hWnd, welches das Handle des Fensters enthällt welches wir ansprechen wollen und der zweite Parameter nCmdShow den Befehl den wir an das Fenster übergeben wollen!
Eigentlich sid wir schon fertig, denn wir können nun diese Funktion aufrufen und als Parameter z.B. Me und vbHide angeben und somit unser eigenes Formular verstecken! OK – das ist ja auch leicht! Denn das Handle von unserem eigenen Fenster kennen wir ja durch z.B. Me.Handle – aber wie kommen wir an das Handle eines anderen Fensters?
Zu unserem Glück bietet das .NET Framework hier sehr mächtige APIs die es und schnell ermöglichen auf die Prozess Strukturen von Windows zu zugreifen! Erstellen wir also noch einen Button auf dem Formular und nennen ihn „Aktualisieren“. In dessen Klick-Event kommt nun folgender Code rein:
Private Sub Button3_Click(ByVal sender As System.Object,_ ByVal e As System.EventArgs) Handles Button3.Click Dim pl As Process() = Process.GetProcesses Me.ListBox1.Items.Clear() For Each p As Process In pl If p.MainWindowTitle <> "" Then Me.ListBox1.Items.Add(p.MainWindowTitle) End If Next End Sub
Wenn wir das Programm nun starten erhalten wir in Listbox1 alle Aktiven Prozesse, die dem Benutzer ein Fenster. also eine GUI bereitstellen. Aber nun im Detail: zuerst deklarieren wir pl – die als Typ einen Prozess-Array bekommt. In dieses Array können nun Prozess Objekte eingegeben werden, was wir auch sogleich tun durch die Anweisung Process.GetProcesses. Dadurch werden alle zur Zeit laufenden Prozesse in diesem Array gespeichert! Übrigens soll pl ProzessList heißen.
In der anschließenden For Each Schleife prüfen wir jeden Prozess persönlich ob sein Fenster (p.MainWindowTitle) einen Wert hat. Denn nur die Prozesse die hier einen Wert haben sind auch sichtbar! – Ausnahmen bilden hier die Formulare ohne Titel und der Windows Explorer von Windows Vista – Bill Gates selbst weis warum die Explorer Fenster keinen Titel haben!
Gut, Schritt eins haben wir geschafft, wir sehen alle offenen Fenster. Jetzt wollen wir diese auch verstecken können! Hier muss man aber aufpassen, denn wenn man ein Fenster verstecken will muss man dessen Handle angeben, sobalt das Fenster versteckt ist, hats dementsprechend auch kein Fenster-Handle mehr, da das Fenster ja weg ist! Deswegen ist es super wichtig, das Handle von JEDEM Fenster, dass man versteckt zu speichern da sonst nurnoch ein Beenden durch den Taskmanager bleibt!
Nun erstellen wir mit einem Doppelklick auf Button1 (Verstecken) das entsprechende Klick-Ereignis und geben folgenden Code ein:
Dim Windows As List(Of IntPtr) = New List(Of IntPtr) Dim Titles As List(Of String) = New List(Of String) Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim pl As Process() = Process.GetProcesses 'Nur wenn ein Fenster gewählt wurde If ListBox1.Text <> "" Then For Each p As Process In pl 'Den Prozess suchen der gewählt wurde If p.MainWindowTitle = ListBox1.Text Then 'Den Handle sichern Windows.Add(p.MainWindowHandle) 'Den Namen des Fenster sichern Titles.Add(p.MainWindowTitle) 'Das gewählte Fenster verstecken ShowWindow(p.MainWindowHandle, vbHide) 'Den Titel des Versteckten Fensters in die Liste schreiben ListBox2.Items.Add(p.MainWindowTitle) End If Next End If 'Unsere Liste aktualisieren Button3_Click(Me, e) End Sub
Hier machen wir eigentlich nichts anderes als in der Aktualisieren Funktion, nur prüfen wir hier ob der Fenstertitel (MainWindowTitle) dem in der ListBox1 gewähltem Fenster entspricht. Danach wird das Handle des Fensters gespeichert in der dafür erstellten Liste Windows, gleich danach wird auchnoch der Name des Prozesses gesichert in der Liste Titles. Und anschließen rufen wir unsere importierte Funktion ShowWindow auf und übergeben das Handle des gewählten Fensters und den Befehl zum Verstecken!
So, nun können wir alle uns sichtbaren Fenster verstecken! Es fehlt also nur noch die Funktion um diese wieder sichtbar zu machen! Diese sieht den anderen beiden ziemlich ähnich:
Private Sub Button2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button2.Click Dim pl As Process() = _ Process.GetProcessesByName(ListBox2.Text) For Each p As Process In pl 'Den gewählten Prozess anzeigen ShowWindow(CLng(Windows(Titles.IndexOf(ListBox2.Text))), vbNormalFocus) 'Den gespeicherten Handle entfernen Windows.RemoveAt(Titles.IndexOf(ListBox2.Text)) 'Den gespeicherten Titel entfernen Titles.RemoveAt(Titles.IndexOf(ListBox2.Text)) 'Eintrag aus der Liste entfernen ListBox2.Items.RemoveAt(ListBox2.SelectedIndex) Next 'Liste aktualisieren Button3_Click(Me, e) End SubHier suchen wir uns nicht erst alle Prozesse heraus sondern nehmen direkt den richtigen, da wir dessen Prozessnamen ja schon kennen (ListBox2). Und dann läuft das gleich Spielchen ab nur rückwärts. Erst machen wir das Fenster wieder sichtbar mit dem Handle aus der Liste Windows und dem Befehl vbNormalFocus. Dann läschen wir dieses Fenster aus allen Listen und auch aus unserer Liste mit den versteckten Fenstern!
Eine Anmerkung noch: Dieses Vorgehen versteckt ein Fenster vor dem benutzer! Dieser Prozess läuft weiterhin im Hintergrund und ist auch im TaskManager sichtbar! Wenn ihr auch diesen Austricksen wollt müsst ihr schon tiefer in die Trick-Kiste greifen, denn das geht nicht mehr so einfach, oder sogar garnicht, zumindest nicht mit einer Managed-Code Sprache wie VB.NET es eine ist!
Dieses DemoProjekt Herunterladen: hideprocessdemo
Sebastian Gross
http://www.bigbasti.comSebastian Gross arbeitet in Bielefeld als Softwareentwickler für .NET und Java im Bereich Web.Als Fan der .NET-Plattform lässt er sich kein Userguppen Treffen und Community Event im Raum OWL entgehen.Dabei hat er eine besondere Vorliebe für das ASP.NET MVC Framework und für das Test Driven Development (TDD) entwickelt.
Author Udo
Posted at 22:28 22. Mai 2009.
Warum machst Du keinen Dienst daraus ? Welchen Sinn soll es machen, einen Prozess vor dem Benutzer in der Prozessliste zu verbergen oder gar Formulare einer Forms-Anwendung zu verstecken ?
Author Basti
Posted at 02:12 23. Mai 2009.
Hi Udo,
wie gesagt, ist der Gedanke hier, dass man fremde Prozesse versteckt, zb Solche, die nicht als Dienst laufen und Platz auf dem Bildschirm oder in der Taskleiste blokieren! Ich habe öfters die Situation, dass einige Programme laufen müssen, und diese über keine „Verbergen“ Funktion verfügen und somit einfach nur stören!
Wenn man selber das Programm schriebt, macht es natürlich mehr Sinn es als Dienst zu gestalten.
MfG