2013-07-27 10 views
13

Ich versuche, die Gma.UserActivityMonitor Bibliothek in einem Projekt zu verwenden, und ich habe einen Fehler konfrontiert, den ich allein nicht überwinden kann.Gma.UserActivityMonitor & SetWindowsHookEx Fehler 126

In der HookManager.Callbacks.cs Datei gibt es eine statische Methode namens EnsureSubscribedToGlobalMouseEvents mit dem folgenden Code (mehr oder weniger):

var asm = Assembly.GetExecutingAssembly().GetModules()[0]; 
var mar = Marshal.GetHINSTANCE(asm); 
s_MouseHookHandle = SetWindowsHookEx(
    WH_MOUSE_LL, 
    s_MouseDelegate, 
    mar, 
    0); 
//If SetWindowsHookEx fails. 
if (s_MouseHookHandle == 0) 
{ 
    //Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set. 
    int errorCode = Marshal.GetLastWin32Error(); 
    //do cleanup 

    //Initializes and throws a new instance of the Win32Exception class with the specified error. 
    throw new Win32Exception(errorCode); 
} 

Die SetWindowsHookEx gibt immer 0 und den obigen Code hält mit der Meldung eine Ausnahme werfen The specified module could not be found und den Anruf zu Marshal.GetLastWin32Error gibt Code 126 zurück. Ich kann die mit dem ursprünglichen Projekt von Gma.UserActivityMonitor bereitgestellte Demo erfolgreich ausführen, aber da mein Projekt ein wenig zu kompliziert ist, um es hier zu erklären, kann ich nicht ins Detail gehen, um seinen Unterschied zu meinen zu erklären. Ich hoffe nur, dass jemand blind das Problem erraten kann.

BTW, in der FAQ des Projekts heißt es, dass andere ein Problem nahe bei mir haben (mit SetWindowsHookEx Fehler zurück), wenn die Enable Visual Studio hosting process nur geprüft wird, wenn das Projekt debuggt wird. Also habe ich diese Box in meiner deaktiviert und immer noch habe ich das gleiche Problem, und nicht nur im Debugging-Modus, sondern auch, wenn ich die Release-Datei im Windows Explorer doppelklicke (ohne Visual Studio).

Um mehr Informationen zu geben, in Demo-Projekt (das funktioniert gut) die asm Variable zeigt auf {Gma.UserActivityMonitor.dll} und das gleiche in meinem Projekt, die die Ausnahme ausgelöst wird!

+0

es könnte sich auf Bitness der beteiligten Prozesse beziehen ... – Yahia

+0

Könnten Sie bitte mehr erklären oder mich auf die richtige Ressource zeigen? – Mehran

+0

Beim Hooking wird normalerweise ein Teil des Codes Teil des Zielprozesses (der Zielprozesse). Dies kann auf verschiedene Arten erreicht werden, aber im Grunde kann jeder Unterschied in der Bissigkeit in Bezug auf Ihren Prozess, die süchtig machenden Prozesse und das OS zu Problemen und/oder fehlerhaftem Verhalten führen. – Yahia

Antwort

27

Diese Art von Code funktioniert nicht mehr auf .NET 4 und höher. Der Fehlercode, den Sie erhalten, ist ansonsten beschreibend, 126 = "Das angegebene Modul konnte nicht gefunden werden". Was sagt Ihnen, dass die Variable "mar" Junk enthält.

.NET 4 hatte eine ziemlich signifikante CLR-Änderung, es gibt nicht mehr vor, dass Jitted Code in nicht verwalteten Modulen lebt. So funktioniert Marshal.GetHINSTANCE() nicht mehr. Der Code wird dann schlampig, es vergisst, den Rückgabewert zu überprüfen, das Testen für (IntPtr) -1 ist erforderlich, um Fehler zu erkennen und ein Desaster zu deklarieren. Ziemlich häufig für Code, den Sie bei Codeproject finden, viele Fehler und Schlampereien, die von Mitwirkenden nicht behoben werden können. Nicht das SO-Modell :)

SetWindowsHookEx() ist ein wenig peinlich für die Low-Level-Hooks. Es erfordert ein gültiges Modulhandle und überprüft es, verwendet es jedoch nicht. Dies wurde in Windows behoben, irgendwo in der Nähe von Win7 SP1. Obwohl es sicherlich eine nützliche Lösung sein sollte, hat es das Problem sogar verschlimmert. Weil es jetzt auf Ihrem Computer funktioniert, aber nicht auf Ihrem Computer.

Anyhoo, die Lösung ist einfach, Sie müssen nur ein gültiges Modul Griff husten. Sie können aus einem Modul erhalten, die immer in einer verwalteten Anwendung ist, die Sie pinvoke LoadLibrary brauchen um es zu bekommen:

var mar = LoadLibrary("user32.dll"); 
s_MouseHookHandle = SetWindowsHookEx(
    WH_MOUSE_LL, 
    s_MouseDelegate, 
    mar, 
    0); 

Keine Notwendigkeit, rufen Sie Freelibrary(), bleibt das Modul geladen, bis Ihr Programm endet sowieso .

+0

Danke Hans, es hat perfekt funktioniert. Ich möchte nur hinzufügen, dass ich das Problem gefunden habe. Deine Antwort wird die Lösung sein, die ich verwenden werde, aber ich wollte dich nur nach deinen Gedanken zu meiner neuen Entdeckung fragen. Das Problem war, dass das "Platform target" meines Projekts auf x86 gesetzt wurde, während mein Betriebssystem Windows 7x64 ist. Andere Optionen wie 'x64' und' Any CPU' funktionieren auf meinem Rechner, aber Ihre Lösung funktioniert unabhängig vom 'Plattformziel', also werde ich damit fortfahren, da ich in meiner Lösung Win32-Projekte in C++ geschrieben habe. Glauben Sie, dass Ihre Lösung auch in anderen Betriebssystemen wie Windows XP, Vista oder Windows 8 stabil ist? – Mehran

+0

Ich habe in der Antwort ausdrücklich darauf hingewiesen, dass es das Ziel war, es unter Windows zu machen. –

+0

Entschuldigung, das habe ich verpasst. Ich danke dir sehr. – Mehran