有时我会收到客户的错误报告,我无法解释.在Delphi中的Application.Run()之后,我收到以下错误:
EOSError: System error: Code:_5 Access denied Call Stack Information: ------------------------------------------------------------------- |Address |Module |Unit |Class |Procedure |Line | ------------------------------------------------------------------- |Running Thread: ID=4352; Priorität=0; Klasse=; [Main Thread] | |-----------------------------------------------------------------| |772B291F|USER32.dll | | |GetKeyState | | |772B7B96|USER32.dll | | |GetPropA | | |772B7B5A|USER32.dll | | |GetPropA | | |772A7BC5|USER32.dll | | |DispatchMessageA| | |772A7BBB|USER32.dll | | |DispatchMessageA| | |00A6D804|Program.exe|Program.dpr| | |803[369]| // Application.Run -------------------------------------------------------------------
和
EOsError: A call to an OS function Failed Call Stack Information: ------------------------------------------------------------------- |Address |Module |Unit |Class |Procedure |Line | ------------------------------------------------------------------- |Running Thread: ID=2712; Priorität=0; Klasse=; [Main Thread] | |-----------------------------------------------------------------| |7E379758|USER32.dll | | |GetCursorPos | | |7E379ED9|USER32.dll | | |GetKeyState | | |7E37B3FC|USER32.dll | | |CallNextHookEx | | |7E380078|USER32.dll | | |GetPropA | | |7E380042|USER32.dll | | |GetPropA | | |7E3696C2|USER32.dll | | |DispatchMessageA| | |7E3696B8|USER32.dll | | |DispatchMessageA| | |00A6E823|Program.exe|Program.dpr| | |803[369]| //Application.Run -------------------------------------------------------------------
在这两种情况下,从Eurekalog提交的屏幕截图都是黑色的.
任何人都可以解释一下,这会导致GetCursorPos或GetKeyState失败的原因是什么?
解决方法
GetCursorPos
的文档说:
The input desktop must be the current desktop when you call GetCursorPos. Call OpenInputDesktop to determine whether the current desktop is the input desktop. If it is not,call SetThreadDesktop with the HDESK returned by OpenInputDesktop to switch to that desktop.
在解锁工作站时,最常见的是犯规.在我的代码中,我将GetCursorPos替换为此变体:
function GetCursorPos(var lpPoint: TPoint): BOOL; stdcall; (* The GetCursorPos API in user32 fails if it is passed a memory address >2GB which breaks LARGEADDRESSAWARE apps. We counter this by calling GetCursorInfo instead which does not suffer from the same problem. In addition we have had problems with GetCursorPos failing when called immediately after a password protected screensaver or a locked workstation re-authenticates. This problem initially appeared with XP SP1 and is brought about because TMouse.GetCursorPos checks the return value of the GetCursorPos API call and raises an OS exception if the API has Failed. *) var CursorInfo: TCursorInfo; begin CursorInfo.cbSize := SizeOf(CursorInfo); Result := GetCursorInfo(CursorInfo); if Result then begin lpPoint := CursorInfo.ptScreenPos; end else begin lpPoint := Point(0,0); end; end;
您可以使用自己喜欢的代码挂钩机制来替换GetCursorPos.我是这样做的:
RedirectProcedure(@Windows.GetCursorPos,@CodePatcher.GetCursorPos);
使用RedirectProcedure,如下所述:Patch routine call in delphi
事实证明,在我的特定情况下,GetCursorPos会失败,但GetCursorInfo不会失败.但正如评论中指出的那样,有些情况下GetCursorInfo也会失败.在这种情况下,您可能会发现安排补丁函数不返回False是有利的.
至于GetKeyState,我不确定那个.它很可能类似,但GetKeyState是我个人不熟悉的API.