C# - Tastenkombinationen sperren
lima-city → Forum → Programmiersprachen → Programmieren mit .NET & Mono
anwendung
beispiel
benutzer
code
halten
interface
kombination
laufen
leben
manager
problem
programm
programmstart
starten
string
system
vordergrund
windows
workstation
zeiterfassung
-
Ich befinde mich gerade in der Programmierung einer Zeiterfassung.
Im Prinzip ist sie eigentlich bereits fertig, nur eine Kleinigkeit fehlt noch.
Und zwar, soll sich diese Zeiterfassung ständig im Vordergrund halten und in keinster Weise schließen lassen.
Das mit dem Vordergrund, habe ich ja bereits mit "TopMost = true" gelöst....das Problem ist aber, dass der User immer noch Tastenkombinationen wie "Alt + F4", "Strg + Esc", "Alt + Esc", "Alt + Tab", "Linke oder rechte Windows-Taste" und meinen persönlichen Favouriten "Strg + Alt + Entf" zum beenden des Programmes drücken kann.
Die einzige Kombination, die ich bisher erfolgreich sperren konnte, war "Alt + F4"....und zwar durch folgenden Code:
protected override bool ProcessDialogKey(Keys keyData) { if (keyData == (Keys.Alt | Keys.F4)) { return (true); } else { return (base.ProcessDialogKey(keyData)); } }
Ich habe selbige Vorgangsweise auch mit allen anderen Kombinationen versucht, aber offensichtlich springt dieses Code-Schnipsel nur auf "Alt + F4" an und blockiert sie.
Ich habe es daraufhin mit Hooks versucht:
//STRG+ESC if (((NativeMethods.GetKeyState(VK_CONTROL) & 0x8000) != 0) && lParam.vkCode == VK_ESC) AllowKey = false; //ALT+ESC if (((NativeMethods.GetKeyState(VK_MENU) & 0x8000) != 0) && lParam.vkCode == VK_ESC) AllowKey = false; //ALT+TAB if (((NativeMethods.GetKeyState(VK_MENU) & 0x8000) != 0) && lParam.vkCode == VK_TAB) AllowKey = false; //ALT+F4 if (((NativeMethods.GetKeyState(VK_MENU) & 0x8000) != 0) && lParam.vkCode == VK_F4) AllowKey = false; // left win und right win if ((lParam.vkCode == 91) || (lParam.vkCode == 92)) AllowKey = false; // STRG+ALT+ENTF //if (((NativeMethods.GetKeyState(VK_CONTROL) & 0x8000) != 0) && // ((NativeMethods.GetKeyState(VK_MENU) & 0x8000) != 0) && lParam.vkCode == VK_DEL) // AllowKey = false;
Hier funktioniert "Strg + Alt + Entf" (wie erwartet) sowieso nicht....das System setzt sich bei dieser Kombination durch.
Bei allen anderen Kombinationen werden mir folgende Fehlermeldung angezeigt:
Invalid token ')' in class, struct, or interface member declaration
Invalid token '=' in class, struct, or interface member declaration
Invalid token '==' in class, struct, or interface member declaration
Habe ich irgendwas vergessen?
Wenn es nicht möglich ist, "Strg + Alt + Entf" zu deaktivieren, wäre das auch kein Problem.
Dann könnte man noch immer mit folgendem Code des Task Manager deaktivieren:
regKey = Registry.CurrentUser.OpenSubKey( @"Software\Microsoft\Windows\CurrentVersion\Policies\System", true); if (regKey == null) regKey = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System"); regKey.SetValue("DisableTaskMgr", 1, RegistryValueKind.DWord);
Aber alle anderen Kombinationen wären mir wichtig.
Blickt da jemand durch?
Beitrag zuletzt geändert: 29.4.2010 14:00:14 von adelwoehrer -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Schau dir das mal an, das sollte funktionieren - damit wird ein Hook auf Low Level Ebene gesetzt, der diese Tasten abfangen könnten müsste:
http://tamaspiros.co.uk/2007/12/20/c-disable-ctrl-alt-del-alt-tab-alt-f4-start-menu-and-so-on/ -
Ah super, danke! =)
Habe allerdings in den Kommentaren von diesem Code-Beispiel einige Beschwerden gefunden, das dieser Code nicht funktioniert.
Werd es selbst mal testen, aber soweit ich mitbekommen habe, läuft die Sperrung von "Strg + Alt + Entf" nur, wenn man den Compiler, nicht den Debugger benutzt.
Naja, Hauptsache irgendwie. ;-D
Gebe dann Feedback innerhalb der nächsten 24h.
FEEDBACK:
Durch den Code konnte ich "Strg + Alt + Entf" und das "Startmenü" deaktivieren.
Alles andere funktioniert nicht....der Code wird anscheinend einfach ignoriert....zwar brav mitkompiliert, aber ignoriert.
Man kann also noch immer "Alt + F4", "Alt + Esc", "Strg + Esc" und die "Windowstasten" drücken.
Beitrag zuletzt geändert: 30.4.2010 8:18:12 von adelwoehrer -
Hm ... ich glaube du willst mit deinem Programm ein Problem lösen, dass eigentlich an einer anderen Stelle gelöst werden müsste.
Soweit ich verstanden habe willst du quasi, dass das Ding läuft und der Benutzer nur dein Programm sieht und sonst nichts starten etc. kann oder die Workstation locken etc.
Sowas bewerkstelligt man normalerweise mit Group Policies etc., d.h. man verbietet dem Workstation-Dienstbenutzer z.B. den Task Manager zu starten oder andere Dinge. Soetwas kann der Administrator machen ... denke nicht das sich das Programm solche Rechte selbst geben kann (Virengefahr etc).
-
Sowas bewerkstelligt man normalerweise mit Group Policies etc., d.h. man verbietet dem Workstation-Dienstbenutzer z.B. den Task Manager zu starten oder andere Dinge.
Die Group Policies sind bereits geregelt....nur nicht zu meinen Gunsten.
Das heißt, ich muss eine andere Möglichkeit finden, bin aber in den Rechten sehr eingeschränkt.
Ich bin zwar selbst Administrator und könnte mich um dieses Problem kümmern, allerdings vergebe ich an einen PC, der von "Bauern" benutzt wird, ungern mehr Rechte, als nötig sind.
Diese Zeiterfassung wird in einem Stall aufgestellt.
Die Leute haben keinerlei Erfahrungen mit PCs, bringen es aber trotzdem zustande, das Programm mit Tastenkombinationen zu schließen, die sie mal irgendwo aufgeschnappt haben....und dann wird gesurft.
Wenn sie mit surfen fertig sind, wird die Zeiterfassung nicht wieder "maximiert", sondern sie machen einfach einen weiteren Doppelklick auf die *.exe.
Somit laufen dann 2 Zeiterfassungen.
Es kommt immer wieder vor, das ich am Abend die PCs kontrolliere und 10 - 15 Zeiterfassungen darauf laufen....diese Leute verstehen das nicht und man kann ihnen den Umgang mit solchen Geräten auch nicht erklären.
Und deshalb muss dieses Programm (leider) Idiotensicher gemacht werden.
Am besten wäre es da natürlich, wenn das Programm diesen idiotensicheren Part selbst übernimmt, da wir es ja noch auf anderen Systemen installieren möchten und ansonsten alles ständig neu konfigurieren müssten.
Eine weitere Möglichkeit wäre auch, den Prozess im Task-Manager zu verstecken.
Ich google aber schon 2 Tage und anscheinend ist auch das so gut wie unmöglich....
Beitrag zuletzt geändert: 30.4.2010 10:58:24 von adelwoehrer -
Vielleicht hilft es dir, wenn du einfach die Anwendung immer im Vordergrund hälst. Du könntest auf das Resize oder Minimize Event reagieren und wenn du das bekommt wieder das Fenster maximieren.
Um dein Programm um Leben zu halten bräuchtest du einen Task im Scheduler oder ein Service, dass prüft, ob deine exe läuft und diese sonst startet (Klasse Process).
Beim Programmstart deiner Exe solltest du checken, ob keine anderen Instanzen davon existieren (Klasse Process oder möglicherweise auch eine static Variable?) -wenn eine existiert, entweder die alte beenden (Process Kill) oder eine aktuelle beenden (Exit).
Zusätzlich empfiehlt sich beim Programmstart einen Thread anzulegen, der einfach im Sekundentakt schaut, ob verdächtige Prozesse laufen - z.B. iexlore.exe, firefox.exe, opera.exe etc um diese bei Beidarf auch zu killen.
Damit sollte den Benutzern ziemlich schnell der Spaß verdorben werden und Policies sollten nicht mehr unbedingt notwendig sein.
Ich hoffe dir damit ein paar Anregungen gegeben zu haben :-) Bei Bedarf kann ich dir gerne noch schreiben, wie du mit Process die laufenden Tasks kontrollieren und killen kannst.
Schöne Grüße
Joe -
Vielleicht hilft es dir, wenn du einfach die Anwendung immer im Vordergrund hälst.
Das ist bereits der Fall.
Es geht nur darum, dass man die Anwendung mit den nötigen Tastenkombinationen immer noch schließen kann.
Um dein Programm um Leben zu halten bräuchtest du einen Task im Scheduler oder ein Service, dass prüft, ob deine exe läuft und diese sonst startet (Klasse Process).
Ich habe versucht, ein zweites Programm parallel und für den Nutzer versteckt am Laufen zu halten, das prüft, ob die Zeiterfassung noch läuft.
Das endete leider damit, dass das Programm immer der Meinung war, dass die Zeiterfassung NICHT läuft....was zur Folge hatte, dass der PC bei einer respektablen Zahl von 300 Zeiterfassungen abgestürzt ist. xD
Zusätzlich empfiehlt sich beim Programmstart einen Thread anzulegen, der einfach im Sekundentakt schaut, ob verdächtige Prozesse laufen - z.B. iexlore.exe, firefox.exe, opera.exe etc um diese bei Beidarf auch zu killen.
Das ist eine super Idee!
Sachen zum Absturz zu bringen beherrsche ich toll....sollte also kein Problem sein, diverse Browser geschlossen zu halten.
Ich habe mal nach den nötigen Codes gegoogelt und glaube, ich hab alles was ich brauche.
Ne PN wär allerdings trotzdem nicht schlecht, falls du die Zeit aufbringen kannst....wie gesagt....wenn es darum geht, Sachen abstürzen zu lassen, bin ich ne Eins.
Beitrag zuletzt geändert: 30.4.2010 17:09:04 von adelwoehrer -
Hier ein Beispiel, wie du Notepad am Leben halten kannst (stürzt auch garantiert nicht ab)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { while (true) { var processes = Process.GetProcessesByName("Notepad"); if (processes.Length == 0) { /* * Pfad zur Exe * Hier kompletten Pfad eintragen. * Bei Notepad nicht notwendig, da ein Path darauf gesetzt ist (DOS: SET PATH) */ string filename = "notepad.exe"; string arguments = ""; var psi = new ProcessStartInfo(filename, arguments); psi.WindowStyle = ProcessWindowStyle.Maximized; Process.Start(psi); } Thread.Sleep(1000); } } } }
Und hier noch ein Beispiel, wie du bestimmte Programm anhand einer definierten Liste abschiessen kannst:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string[] killProgramme = new string[]{ "iexplore", "chrome", "firefox", "notepad"}; while (true) { var processes = Process.GetProcesses(); var filteredProcesses = processes.Where(p => killProgramme.Contains(p.ProcessName)); foreach(var process in filteredProcesses) { process.Kill(); } Thread.Sleep(500); } } } }
Beitrag zuletzt geändert: 30.4.2010 19:18:29 von postkarten -
Sehr schön, das sollte so klappen. =)
Dann geb ich diesem Programm noch einen grußeligen Systemnamen, damit es auch sicher nicht beendet wird und das Schließen der Zeiterfassung sollte sich erledigt haben.
Ich hatte bisher aber immer das Problem, dass sich die Konsolenanwendung nach einmaligem Ausführen der while-Schleife geschlossen hat, weil sie offenbar für sich befunden hat, dass die zugewiesene Aufgabe (Zeiterfassung neu starten) erledigt ist.
Das heißt, wenn der Benutzer die Zeiterfassung einmal schließt, wird sie neu gestartet.
Beim zweiten mal aber nicht....wieso sich jetzt dieses Programm selbst schließt, ist mir zwar schleierhaft, aber gibt es einen Befehl, um sicher zu gehen, dass es offen bleibt? (ohne mit einem dritten Programm zu checken )
Beitrag zuletzt geändert: 30.4.2010 19:23:01 von adelwoehrer -
Durch das While(true) läuft das Consolenprogramm ewig ... ich kann jetzt nicht sagen wo es in deinem Programm gehakt hat, aber probier den Code den ich gepostet habe einmal aus, der wird ewig laufen.
Wobei das Überwachungsprogramm besser keine Consolenanwendung ist sondern eine Forms Anwendung - diese kann man so einstellen, dass diese in der Taskleiste ausgeblendet und nur mehr im Task Manager sichtbar ist.
Bewährt hat sich ein Name wie svchost - da gibt es alleine schon von Windows aus zig Prozesse im Taskmanager - wenn da einer anfängt auszuprobieren Tasks abzuschießen ist bald das System kaputt :-)
Beitrag zuletzt geändert: 30.4.2010 21:57:31 von postkarten -
Hmm....ne, auch bei ner direkten Kopie von deinem Code, schließt sich das Konsolenprogramm.
Aber das ist ja auch kein Problem, schließlich macht das eine Windows Forms Anwendung nicht....und wie du schon sagtest, lässt sich die auch bis auf den Prozess prima verstecken.
Ist zwar nicht ganz das, was ich anfänglich wollte, aber es funktioniert...und ein funktionierendes System soll man bekanntlich nicht ersetzen. -
Noch eines: wenn sich das Konsolenprogramm schließt muss das heißen, dass eine Exception geworfen wird, sonst dürfte er die while Schleife nie verlassen. Lege mal ein Try-Catch um das While und setze einen Breakpoint in die Exception oder zeig eine MessageBox - wäre interessant, was für ein Fehler da bei dir geworfen wird. Vermutlich stimmt dann der Pfad zur Exe nicht oder sowas.
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage