我正在尝试从我的应用程序中运行屏幕上键盘。它在Windows 32位下正确工作,但在Win 7 64位下不正确。
unit Unit5;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ShellAPI;
type
TForm5 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
class function IsWOW64: Boolean;
{ Public declarations }
end;
var
Form5: TForm5;
implementation
{$R *.dfm}
procedure TForm5.FormCreate(Sender: TObject);
var path:String;
res : Integer;
function GetSysDir: string;
var
Buf: array[0..MAX_PATH] of Char;
Len: UINT;
S: String;
begin
{$IFNDEF WIN64}
if TForm5.IsWOW64 then
begin
Len := GetWindowsDirectory(Buf, MAX_PATH);
if Len = 0 then RaiseLastOSError;
SetString(S, Buf, Len);
Result := IncludeTrailingPathDelimiter(S) + 'Sysnative\';
Exit;
end;
{$ENDIF}
Len := GetSystemDirectory(Buf, MAX_PATH);
if Len = 0 then RaiseLastOSError;
SetString(S, Buf, Len);
Result := IncludeTrailingPathDelimiter(S);
end;
begin
path := GetSysDir;
path := path + 'osk.exe';
res := ShellExecute(self.Handle,'open',Pchar(path),nil,nil,SW_NORMAL);
if res <> 42 then
begin
ShowMessage(path);
RaiseLastOSError;
end;
end;
class function TForm5.IsWOW64: Boolean;
type
TIsWow64Process = function( // Type of IsWow64Process API fn
Handle: THandle;
var Res: BOOL
): BOOL; stdcall;
var
IsWow64Result: BOOL; // result from IsWow64Process
IsWow64Process: TIsWow64Process; // IsWow64Process fn reference
begin
// Try to load required function from kernel32
IsWow64Process := GetProcAddress(
GetModuleHandle('kernel32'), 'IsWow64Process'
);
if Assigned(IsWow64Process) then
begin
// Function is implemented: call it
if not IsWow64Process(GetCurrentProcess, IsWow64Result) then
RaiseLastOSError;
// Return result of function
Result := IsWow64Result;
end
else
// Function not implemented: can't be running on Wow64
Result := False;
end;
end.
在x64下运行应用程序将显示路径C:\Windows\Sysnative\osk.exe,并引发“调用OS函数失败”错误。
在windows目录上搜索显示存在osk.exe。
发布于 2014-04-17 08:27:47
在UAC下,osk有一些特别之处。此代码与错误代码740,ERROR_ELEVATION_REQUIRED
失败,请求的操作需要提升。
var
si: TStartupInfo;
pi: TProcessInformation;
....
si.cb := SizeOf(si);
GetStartupInfo(si);
Win32Check(CreateProcess('C:\Windows\system32\osk.exe', nil, nil, nil,
False, 0, nil, nil, si, pi));
这在具有UAC的机器上的32位和64位进程下都失败。您可以在这里找到一些关于这个问题的讨论:https://web.archive.org/web/20170311141004/http://blog.delphi-jedi.net/2008/05/17/the-case-of-shellexecute-shellexecuteex-createprocess-and-oskexe/
因此,您的问题与32位或64位无关,而是因为您的XP系统没有UAC。
更广泛地说,我认为这应该足以说服你不要再打电话给ShellExecute
了。它只存在于16位兼容性,在报告错误时是非常无用的。如果需要错误,请打电话给ShellExecuteEx
。然而,由于我们正在开始一个新的过程,CreateProcess
通常是正确的调用API。
也就是说,在这种特殊情况下,osk的设计不能由CreateProcess
以编程方式启动。它确实需要由ShellExecute
或ShellExecuteEx
调用。这允许shell执行其UAC魔术。现在,事实证明,魔术不可能发生在32位WOW64进程。然后,解决方案是通过调用ShellExecuteEx
从64位进程启动osk。
这是你的解决办法:
ShellExecuteEx
来打开osk
。ShellExecuteEx
来打开osk
。ShellExecuteEx
打开osk
。因为您似乎没有使用Delphi的64位版本,所以需要找到64位编译器。您可以使用64位fpc或64位C++编译器。以下C++程序就足够了:
#include <Windows.h>
#include <Shellapi.h>
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
SHELLEXECUTEINFOW sei = { sizeof(sei) };
sei.lpVerb = L"open";
sei.lpFile = L"osk.exe";
sei.nShow = SW_SHOW;
ShellExecuteExW(&sei);
}
您可以使用64位C++编译器编译它,然后从32位WOW64进程调用它。我知道,它确实有实际工作的优点!
发布于 2019-01-14 11:28:23
Function Wow64DisableWow64FsRedirection(Var Wow64FsEnableRedirection: LongBool): LongBool; StdCall;
External 'Kernel32.dll' Name 'Wow64DisableWow64FsRedirection';
Var
Wow64FsEnableRedirection: LongBool;
begin
if Wow64DisableWow64FsRedirection(Wow64FsEnableRedirection) then ShellExecute(0,nil, 'osk.exe', nil, nil, SW_show);
end;
发布于 2018-11-04 12:48:25
另一个简单得多的选项是在ShellExecute中使用ShellExecute,如下所示:
{
If UTExistFile(GetWindowsSystemDir() + '\OSK.exe') then
// we can "see" OSK.exe in the System32 folder, so we are running on
// 32-bit Windows, so no problem accessing OSK.EXE in System32.
ShellExecute(Application.Handle, // HWND hwnd
'open', // LPCTSTR lpOperation
LPCTSTR(GetWindowsSystemDir() + '\OSK.exe'), // LPCTSTR lpFile
'', // LPCTSTR lpParameters
'', // LPCTSTR lpDirectory,
SW_Show) // INT nShowCmd
else
// Use SysNative to get at OSK.EXE. This will not work for 64-bit OS
// before Vista (e.g. XP), but it won't lock or crash your system and at
// least you can compile and run the application on all versions of Windows;
// both 32 and 64 bit.
ShellExecute(Application.Handle, // HWND hwnd
'open', // LPCTSTR lpOperation
LPCTSTR(GetWindowsDir() + '\SysNative\OSK.EXE'), // LPCTSTR lpFile
'', // LPCTSTR lpParameters
'', // LPCTSTR lpDirectory,
SW_Show) ; // INT nShowCmd
}
它在64位Windows 10上运行得很好。理论上,我还没有尝试过其他版本的操作系统,这应该适用于所有版本的操作系统,除了64位的前Vista版本,在这种情况下OSK不会显示,但是32位编译的应用程序将在所有版本的Windows 32位和64位上运行。
https://stackoverflow.com/questions/23116149
复制相似问题