2013-07-27 25 views
13

Tôi đang cố gắng sử dụng thư viện Gma.UserActivityMonitor trong một dự án và tôi đã gặp phải lỗi mà tôi không thể tự khắc phục được.Gma.UserActivityMonitor & SetWindowsHookEx lỗi 126

Trong tập tin HookManager.Callbacks.cs có một phương pháp tĩnh gọi EnsureSubscribedToGlobalMouseEvents với đoạn mã sau (nhiều hơn hoặc ít hơn):

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); 
} 

Các SetWindowsHookEx luôn trả 0 và mã ở trên giữ ném một ngoại lệ với thông điệp The specified module could not be found và cuộc gọi đến Marshal.GetLastWin32Error trả lại mã 126. Tôi có thể chạy demo thành công được cung cấp với dự án ban đầu của Gma.UserActivityMonitor nhưng vì dự án của tôi hơi phức tạp để giải thích ở đây tôi không thể đi vào chi tiết giải thích sự khác biệt của nó với tôi. Tôi chỉ hy vọng một người nào đó mù có thể đoán được vấn đề.

BTW, trong Câu hỏi thường gặp của dự án nói rằng những người khác có vấn đề gần gũi với tôi (với SetWindowsHookEx lỗi trả về) khi Enable Visual Studio hosting process chỉ được chọn khi dự án được gỡ lỗi. Vì vậy, tôi bỏ chọn hộp đó trong tôi và vẫn còn tôi đang gặp vấn đề tương tự, và không chỉ trong chế độ gỡ lỗi mà còn khi tôi nhấp đúp vào tập tin phát hành trong Windows Explorer (không có Visual Studio tham gia).

Để cung cấp thêm thông tin, trong dự án demo (hoạt động tốt), các điểm biến số asm đến {Gma.UserActivityMonitor.dll} và giống như trong dự án của tôi mà ngoại lệ được ném!

+0

nó có thể liên quan đến độ bit của các quy trình liên quan ... – Yahia

+0

Bạn có thể giải thích thêm hoặc chỉ cho tôi đúng tài nguyên không? – Mehran

+0

Hooking thường liên quan đến một số mã trở thành một phần của quá trình mục tiêu (es). Điều này có thể đạt được theo những cách khác nhau nhưng về cơ bản bất kỳ sự khác biệt nào về tính bit của quy trình của bạn, quy trình nối và hệ điều hành có thể dẫn đến các vấn đề và/hoặc hành vi erratci. – Yahia

Trả lời

27

Loại mã này không hoạt động nữa trên .NET 4 trở lên. Mã lỗi bạn nhận được là mô tả khác, 126 = "Không thể tìm thấy mô-đun được chỉ định". Trong đó cho bạn biết rằng biến "mar" chứa rác.

.NET 4 có thay đổi CLR khá đáng kể, nó không còn giả vờ rằng mã jitted sống bên trong các mô-đun không được quản lý. Vì vậy, Marshal.GetHINSTANCE() không hoạt động nữa. Các mã sau đó được cẩu thả, nó quên để kiểm tra giá trị trả lại, kiểm tra nó cho (IntPtr) -1 là cần thiết để phát hiện thất bại và tuyên bố thảm họa. Khá phổ biến đối với mã bạn tìm thấy ở Codeproject, rất nhiều lỗi và sloppiness không thể được cố định bởi những người đóng góp. Không phải mô hình SO :)

SetWindowsHookEx() hơi khó xử lý đối với các móc mức thấp. Nó đòi hỏi một trình xử lý mô-đun hợp lệ và kiểm tra nó, nhưng không thực sự sử dụng nó. Điều này đã được sửa trong Windows, một nơi nào đó xung quanh Win7 SP1. Mặc dù chắc chắn có ý định sửa chữa hữu ích nhưng nó thực sự làm cho vấn đề trở nên tồi tệ hơn. Bởi vì bây giờ nó có thể hoạt động trên máy tính của bạn nhưng không hoạt động trên máy tính của người dùng của bạn.

Anyhoo, việc sửa chữa rất đơn giản, bạn chỉ cần ho một tay cầm mô-đun hợp lệ. Bạn có thể lấy một từ một mô-đun mà luôn luôn hiện diện trong một ứng dụng quản lý, bạn sẽ cần phải pinvoke LoadLibrary để có được nó:

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

Không cần phải gọi FreeLibrary(), mô-đun mà vẫn nạp cho đến khi chương trình của bạn chấm dứt nào .

+0

Cảm ơn Hans, nó hoạt động hoàn hảo. Tôi chỉ muốn thêm rằng tôi đã tìm ra được vấn đề. Của bạn sẽ là giải pháp tôi sẽ sử dụng nhưng tôi chỉ muốn hỏi ý kiến ​​của bạn về khám phá mới của tôi nếu bạn hài lòng. Vấn đề là mục tiêu nền tảng của dự án của tôi được đặt thành x86 trong khi hệ điều hành của tôi là Windows 7x64. Các lựa chọn khác như 'x64' và' Any CPU' hoạt động trên máy tính của tôi nhưng giải pháp của bạn hoạt động bất kể 'Target target' nên tôi sẽ đi với điều đó vì tôi có các dự án Win32 được viết bằng C++ trong giải pháp của mình. Bạn có nghĩ rằng giải pháp của bạn là rắn ngay cả trong các hệ điều hành khác như WindowsXP, Vista hoặc Windows 8? – Mehran

+0

Tôi đã chỉ ra một cách rõ ràng trong câu trả lời rằng làm cho nó hoạt động trên bất kỳ phiên bản Windows nào là mục tiêu. –

+0

Xin lỗi tôi đã bỏ lỡ điều đó. Cảm ơn bạn rất nhiều. – Mehran

Các vấn đề liên quan