Unable to launch onscreen keyboard (osk.exe) from a 32-bit process on Win7 x64

前端 未结 6 1299
抹茶落季
抹茶落季 2020-12-03 14:08

90% of the time I am unable to launch osk.exe from a 32bit process on Win7 x64. Originally the code was just using:

Process.Launch(         


        
6条回答
  •  长情又很酷
    2020-12-03 14:29

    Certain things are going on under the hood that require you to start osk.exe from an MTA thread. The reason seems to be that a call to Wow64DisableWow64FsRedirection only affects the current thread. However, under certain conditions, Process.Start will create the new process from a separate thread, e.g. when UseShellExecute is set to false and also when being called from an STA thread as it seems.

    The code below checks the apartment state and then makes sure to start the On-Screen Keyboard from an MTA thread:

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Threading;
    
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
    
    
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, 
            UInt32 Msg, 
            IntPtr wParam, 
            IntPtr lParam);
        private const UInt32 WM_SYSCOMMAND = 0x112;
        private const UInt32 SC_RESTORE = 0xf120;
    
        private const string OnScreenKeyboardExe = "osk.exe";
    
        [STAThread]
        static void Main(string[] args)
        {
            Process[] p = Process.GetProcessesByName(
                Path.GetFileNameWithoutExtension(OnScreenKeyboardExe));
    
            if (p.Length == 0)
            {
                // we must start osk from an MTA thread
                if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
                {
                    ThreadStart start = new ThreadStart(StartOsk);
                    Thread thread = new Thread(start);
                    thread.SetApartmentState(ApartmentState.MTA);
                    thread.Start();
                    thread.Join();
                }
                else
                {
                    StartOsk();
                }
            }
            else
            {
                // there might be a race condition if the process terminated 
                // meanwhile -> proper exception handling should be added
                //
                SendMessage(p[0].MainWindowHandle, 
                    WM_SYSCOMMAND, new IntPtr(SC_RESTORE), new IntPtr(0));
            }
        }
    
        static void StartOsk()
        {
            IntPtr ptr = new IntPtr(); ;
            bool sucessfullyDisabledWow64Redirect = false;
    
            // Disable x64 directory virtualization if we're on x64,
            // otherwise keyboard launch will fail.
            if (System.Environment.Is64BitOperatingSystem)
            {
                sucessfullyDisabledWow64Redirect = 
                    Wow64DisableWow64FsRedirection(ref ptr);
            }
    
    
            ProcessStartInfo psi = new ProcessStartInfo();
            psi.FileName = OnScreenKeyboardExe;
            // We must use ShellExecute to start osk from the current thread
            // with psi.UseShellExecute = false the CreateProcessWithLogon API 
            // would be used which handles process creation on a separate thread 
            // where the above call to Wow64DisableWow64FsRedirection would not 
            // have any effect.
            //
            psi.UseShellExecute = true;
            Process.Start(psi);
    
            // Re-enable directory virtualisation if it was disabled.
            if (System.Environment.Is64BitOperatingSystem)
                if (sucessfullyDisabledWow64Redirect)
                    Wow64RevertWow64FsRedirection(ptr);
        }
    }
    

提交回复
热议问题