// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Diagnostics; using System.Text; using System.Threading; using Wox.Plugin.Common.Win32; namespace Wox.Plugin.Common { public static class ShellCommand { public delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam); private static bool containsSecurityWindow; public static Process RunAsDifferentUser(ProcessStartInfo processStartInfo) { if (processStartInfo == null) { throw new ArgumentNullException(nameof(processStartInfo)); } processStartInfo.Verb = "RunAsUser"; var process = Process.Start(processStartInfo); containsSecurityWindow = false; // wait for windows to bring up the "Windows Security" dialog while (!containsSecurityWindow) { CheckSecurityWindow(); Thread.Sleep(25); } // while this process contains a "Windows Security" dialog, stay open while (containsSecurityWindow) { containsSecurityWindow = false; CheckSecurityWindow(); Thread.Sleep(50); } return process; } private static void CheckSecurityWindow() { ProcessThreadCollection ptc = Process.GetCurrentProcess().Threads; for (int i = 0; i < ptc.Count; i++) { NativeMethods.EnumThreadWindows((uint)ptc[i].Id, CheckSecurityThread, IntPtr.Zero); } } private static bool CheckSecurityThread(IntPtr hwnd, IntPtr lParam) { if (GetWindowTitle(hwnd) == "Windows Security") { containsSecurityWindow = true; } return true; } private static string GetWindowTitle(IntPtr hwnd) { StringBuilder sb = new StringBuilder(NativeMethods.GetWindowTextLength(hwnd) + 1); _ = NativeMethods.GetWindowText(hwnd, sb, sb.Capacity); return sb.ToString(); } public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "") { var info = new ProcessStartInfo { FileName = fileName, WorkingDirectory = workingDirectory, Arguments = arguments, Verb = verb, }; return info; } } }