当前位置: 首页 > 编程语言 > C#

Win7x6432位进程无法启动屏幕键盘(osk.exe)分享

时间:2023-04-10 16:36:57 C#

Win7x6432位进程无法启动屏幕键盘(osk.exe)x64上的32位进程启动osk.exe。最初代码只是使用:Process.Launch("osk.exe");由于目录虚拟化,这在x64上不起作用。我认为这不是问题,我只是禁用虚拟化,启动应用程序,然后再次启用它,我认为这是正确的做事方式。我还添加了一些代码,如果键盘已被最小化(效果很好),它会恢复键盘-代码(在示例WPF应用程序中)现在看起来像这样:使用System.Collections.Generic;使用系统。林克;使用系统文本;使用System.Windows;使用System.Windows.Controls;使用System.Windows.Data;使用System.Windows.Documents;使用System.Windows.Input;使用System.Windows.Media;Windows.Media.Imaging;使用System.Windows.Navigation;使用System.Diagnostics;使用System.Runtime.InteropServices;namespaceKeyboardTest{//////MainWindow.xaml的交互逻辑///publicpartialclassMainWindow:Window{[DllImport("kernel32.dll",SetLastError=true)]privatestaticexternboolWow64DisableWow64FsRedirection(refIntPtrptr);[DllImport("kernel32.dll",SetLastError=true)]publicstaticexternboolWow64RevertWow64FsRedirection(IntPtrprivateWow64FsRedirection)constUInt32WM_SYSCOMMAND=0x112;私有常量UInt32SC_RESTORE=0xf120;[DllImport("user32.dll",CharSet=CharSet.Auto)]staticexternIntPtrSendMessage(IntPtrhWnd,UInt32Msg,IntPtrwParam,IntPtrlParam);私有字符串OnScreenKeyboadApplication="osk.exe";publicMainWindow(){InitializeComponent();}privatevoidKeyboardButton_Click(objectsender,RoutedEventArgse){//获取屏幕键盘的名称stringprocessName=System.IO.Path.GetFileNameWithoutExtension(OnScreenKeyboadApplication);//检查应用程序是否未运行varquery=fromprocessinProcess.GetProcesses()whereprocess.ProcessName==processNameselectprocess;varkeyboardProcess=query.FirstOrDefault();//如果它不存在则启动它if(keyboardProcess==null){IntPtrptr=newIntPtr();;boolsucessfullyDisabledWow64Redirect=false;//如果我们在x64上,则禁用x64目录虚拟化,//否则键盘启动将失败。如果(System.Environment.Is64BitOperatingSystem){sucessfullyDisabledWow64Redirect=Wow64DisableWow64FsRedirection(refptr);}//好吧.exe位于windows/system文件夹中。所以我们可以直接调用它而不使用路径(Processosk=newProcess()){osk.StartInfo.FileName=OnScreenKeyboadApplication;osk.开始();osk.WaitForInputIdle(2000);//如果目录虚拟化被禁用,则重新启用它。如果(System.Environment.Is64BitOperatingSystem)如果(成功禁用Wow64Redirect)Wow64RevertWow64FsRedirection(ptr);}else{//如果已经是WlereadProinandclowindc,则将键盘置于最前面;varwindowSendMessage(windowHandle,WM_SYSCOMMAND,newIntPtr(SC_RESTORE),newIntPtr(0));但在大多数情况下,这段代码会在osk.Start()上抛出以下异常:FailedinSystem.Diagnostics。在Process.StartWithShellExecuteEx(ProcessStartInfostartInfo)中找到了指定的进程有什么问题,或替代解决方案吗?启动记事本似乎可以正常工作,只是无法使用屏幕键盘弹奏。对于您收到的确切错误消息,我没有非常可靠的解释。但是禁用重定向会破坏.NET框架。默认情况下,Process.Start()P/调用ShellExecuteEx()API函数来启动进程。该函数位于shell32.dll中,如果之前没有执行过,可能需要加载。当重定向被禁用时,你会得到错误的。解决方案是将ProcessStartInfo.UseShellExecute设置为false。你在这里不需要它。显然,禁用重定向是一种有风险的方法,其副作用是您无法预料的。有很多DLL可以按需加载。使用PlatformTarget=AnyCPU编译的非常小的帮助程序EXE应该可以解决您的问题。在64位操作系统上运行的32位应用程序应该启动64位版本的osk.exe。您将在下面找到用C#编写的代码,该代码可启动正确的屏幕键盘。privatestaticvoidShowKeyboard(){varpath64=@"C:Windowswinsxsamd64_microsoft-windows-osk_31bf3856ad364e35_6.1.7600.16385_none_06b1c513739fb828osk.exe";varpath32=@"C:windowssystem32osk.exe";变量路径=(Environment.Is64BitOperatingSystem)?路径64:路径32;Process.Start(路径);}正在发生的事情要求您从MTA线程启动osk.exe。原因似乎是对Wow64DisableWow64FsRedirection的调用只影响当前线程。但是,在某些情况下,Process.Start将从单独的线程创建新进程,例如,当UseShellExecute设置为false时,以及从STA线程调用时。下面的代码检查公寓状态,然后确保从MTA线路启动屏幕按键盘:usingSystem;使用系统诊断;使用System.IO;使用System.Runtime.InteropServices;使用系统线程;类程序{[DllImport("kernel32.dll",SetLastError=true)]privatestaticexternboolWow64DisableWow64FsRedirection(refIntPtrptr);[DllImport("kernel32.dll",SetLastError=true)]publicstaticexternboolWow64RevertWow64FsRedirection(IntPtrptr);[DllImport("user32.dll",CharSet=CharSet.Auto)]staticexternIntPtrSendMessage(IntPtrhWnd,UInt32Msg,IntPtrwParam,IntPtrlParam);私有常量UInt32WM_SYSCOMMAND=0x112;私有常量UInt32SC_RESTORE=0xf120;privateconststringOnScreenKeyboardExe="osk.exe";[STAThread]staticvoidMain(string[]args){Process[]p=Process.GetProcessesByName(Path.GetFileNameWithoutExtension(OnScreenKeyboardExe));if(p.Length==0){//我们必须从MTA线程启动oskif(Thread.CurrentThread.GetApartmentState()==ApartmentState.STA){ThreadStart开始=newThreadStart(StartOsk);线程thread=newThread(开始);thread.SetApartmentState(ApartmentState.MTA);线程。开始();线程.加入();}else{StartOsk();}}else{//如果进程终止,则可能存在竞争条件//与此同时->应添加适当的异常处理//SendMessage(p[0].MainWindowHandle,WM_SYSCOMMAND,newIntPtr(SC_RESTORE),newIntPtr(0));}}staticvoidStartOsk(){IntPtrptr=newIntPtr();;boolsucessfullyDisabledWow64Redirect=false;//如果我们在x64上,则禁用x64目录虚拟化,//否则键盘启动将失败。如果(System.Environment.Is64BitOperatingSystem){sucessfullyDisabledWow64Redirect=Wow64DisableWow64FsRedirection(refptr);}ProcessStartInfopsi=newProcessStartInfo();psi.FileName=OnScreenKeyboardExe;//我们必须使用ShellExecute从当前线程启动osk//使用psi.UseShellExecute=falseCreateProcessWithLogonAPI//会用于在单独的线程上处理进程创建//其中上面对Wow64DisableWow64FsRedirection的调用不会有任何效果。//psi.UseShellExecute=true;Process.Start(psi);//如果目录虚拟化被禁用,则重新启用它。如果(System.Environment.Is64BitOperatingSystem)如果(成功禁用Wow64Redirect)Wow64RevertWow64FsRedirection(ptr);这篇文章似乎包含一些真正的解决方案:http://www.dreamincode.net/forums/topic/174949-open-on-screen-keyboard-in-c%23/具体来说,我已经在Win7上试过了到目前为止,x64和WinXP32位,并且可以正常工作staticvoidStartOSK(){stringwindir=Environment.GetEnvironmentVariable("WINDIR");字符串osk=null;if(osk==null){osk=Path.Combine(Path.Combine(windir,"sysnative"),"osk.exe");如果(!File.Exists(osk)){osk=null;}}if(osk==null){osk=Path.Combine(Path.Combine(windir,"system32"),"osk.exe");如果(!File.Exists(osk)){osk=null;}}if(osk==null){osk="osk.exe";}Process.Start(osk);笨拙的方法:在旁边运行这个批处理文件(从64位资源管理器开始)::lab0TIMEOUT/T1>nulifexistsoskstart.tmpgotolab2gotolab0:lab2deloskstart.tmpOSKgotolab0createwhenkeyboard需要文件oskstart.tmpCambiarlaspropiedadesdelaaplicación。COMPILAR-Desmarcar检查更喜欢32位。更改应用程序属性Compila-取消选中“BEST32BITS”(或类似内容)您可以阅读此内容:http://blog.anthonybaker.me/2012/08/spawning-windows-on-screen-keyboard-osk.html或使用此内容其他应用程序的选项和从主应用程序午餐(运行)。对于那些面临“无法启动屏幕键盘”的人,请将项目的平台目标更改为任何CPU。以上是C#学习教程:Unabletostarttheon-screenkeyboard(osk.exe)froma32-bitprocessonWin7x64。如果对大家有用,需要进一步了解C#学习教程,还望大家多加关注~本文整理自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:

猜你喜欢