public void Dispose() { if (!WindowsApi.CloseDesktop(Handle)) { WindowsHelpers.CheckLastError(); } }
public void Dispose() { if (!WindowsApi.SetThreadDesktop(originalDesktop)) { WindowsHelpers.CheckLastError(); } }
private static IntPtr FindDescendantBy(IntPtr parent, string className = null, string text = null) { var matches = new List <IntPtr>(); WindowsApi.EnumChildWindows(parent, (handle, pointer) => { if ( (className == null || WindowsHelpers.GetWindowClassName(handle) == className) && (text == null || WindowsHelpers.GetWindowTextRaw(handle) == text) ) { matches.Add(handle); } return(true); }, IntPtr.Zero); if (matches.Count > 1) { throw new Exception($"Found {matches.Count} matching descendants."); } return(matches.FirstOrDefault()); }
private static string AssocQueryString(ApplicationAssociation association) { uint appNameLength = 0; var result = WindowsApi.AssocQueryString(WindowsApi.AssocF.None, WindowsApi.AssocStr.FriendlyAppName, association.ProgId, null, null, ref appNameLength); if (new[] { 2147943555, 2147942402 }.Contains(result)) // No application is associated with the specified file for this operation OR The system cannot find the file specified { return(null); } if (result != 1) { throw new Win32Exception((int)result); } var buffer = new StringBuilder((int)appNameLength); var bufferLength = (uint)buffer.Capacity; result = WindowsApi.AssocQueryString(WindowsApi.AssocF.None, WindowsApi.AssocStr.FriendlyAppName, association.ProgId, null, buffer, ref bufferLength); if (result != 0) { throw new Win32Exception((int)result); } return(buffer.ToString()); }
public static string GetWindowTextRaw(IntPtr hwnd) { var length = (int)WindowsApi.SendMessage(hwnd, WindowsApi.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero); var sb = new StringBuilder(length + 1); WindowsApi.SendMessage(hwnd, WindowsApi.WM_GETTEXT, (IntPtr)sb.Capacity, sb); return(sb.ToString()); }
public int?GetExitCode() { if (!WindowsApi.GetExitCodeProcess(processInformation.hProcess, out var exitCode)) { WindowsHelpers.CheckLastError(); } return(exitCode == 259 /* STILL_ACTIVE */ ? null : (int?)exitCode); }
public Desktop(string baseName) { Name = baseName + " " + DateTime.Now.Ticks.ToString(); //Ensuring this is unique since sometimes a name can't be reused later on Handle = WindowsApi.CreateDesktop(Name, null, null, 0, WindowsApi.ACCESS_MASK.DESKTOP_CREATEWINDOW, null); if (Handle == IntPtr.Zero) { WindowsHelpers.CheckLastError(); } }
public static string GetWindowClassName(IntPtr hwnd) { var result = new StringBuilder(256); var charactersCopied = WindowsApi.GetClassName(hwnd, result, result.Capacity); if (charactersCopied == 0) { CheckLastError(); } return(result.ToString()); }
public void Dispose() { if (!WindowsApi.CloseHandle(processInformation.hProcess)) { WindowsHelpers.CheckLastError(); } if (!WindowsApi.CloseHandle(processInformation.hThread)) { WindowsHelpers.CheckLastError(); } }
/// <summary> /// Switches to the <paramref name="newDesktopHandle"/> desktop. /// </summary> public DesktopContext(IntPtr newDesktopHandle) { originalDesktop = WindowsApi.GetThreadDesktop(WindowsApi.GetCurrentThreadId()); if (originalDesktop == IntPtr.Zero) { WindowsHelpers.CheckLastError(); } if (!WindowsApi.SetThreadDesktop(newDesktopHandle)) { WindowsHelpers.CheckLastError(); } }
public void CheckItem(int itemIndex) { var lvi = new WindowsApi.LVITEM { iItem = itemIndex, iSubItem = 0, stateMask = 8192, //TODO: Replace these with the proper constants state = 8192, }; using (var structBuffer = ProcessMemoryChunk.AllocStruct(process, lvi)) { if (WindowsApi.SendMessage(handle, WindowsApi.LVM_SETITEMSTATE, (IntPtr)itemIndex, structBuffer.Location) == IntPtr.Zero) { throw new Exception("Couldn't set list item state"); } } }
/// <remarks> /// Taken from https://github.com/kvakulo/Switcheroo/blob/master/ManagedWinapi/SystemListView.cs#L75 /// </remarks> public IEnumerable <string> GetListItems() { var listViewItemCount = (int)WindowsApi.SendMessage(handle, WindowsApi.LVM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero); for (var i = 0; i < listViewItemCount; ++i) { var lvi = new WindowsApi.LVITEM { cchTextMax = 512, iItem = i, iSubItem = 0, stateMask = 0xffffffff, mask = WindowsApi.LVIF_STATE | WindowsApi.LVIF_TEXT, }; using (var textBuffer = ProcessMemoryChunk.Alloc(process, lvi.cchTextMax * 2 /* Assuming 2-byte character size just in case */)) { lvi.pszText = textBuffer.Location; using (var structBuffer = ProcessMemoryChunk.AllocStruct(process, lvi)) { if (WindowsApi.SendMessage(handle, WindowsApi.LVM_GETITEM, IntPtr.Zero, structBuffer.Location) == IntPtr.Zero) { throw new Exception("Couldn't get list item"); } lvi = (WindowsApi.LVITEM)structBuffer.ReadToStructure(0, typeof(WindowsApi.LVITEM)); } //TODO: Check if pszText pointer location changed var titleBytes = textBuffer.Read(); var title = Encoding.Default.GetString(titleBytes); if (title.IndexOf('\0') != -1) { title = title.Substring(0, title.IndexOf('\0')); } yield return(title); } } }
private static ApplicationCapabilities TryGetCapabilities(string applicationCapabilityPath) { var result = new ApplicationCapabilities(); using (var key = Registry.CurrentUser.OpenSubKey(applicationCapabilityPath) ?? Registry.LocalMachine.OpenSubKey(applicationCapabilityPath)) { if (key == null) { return(null); } var rawApplicationName = key.GetValue("ApplicationName") as string; if (rawApplicationName != null) { var resourceValue = new StringBuilder(4096); var hresult = WindowsApi.SHLoadIndirectString(rawApplicationName, resourceValue, resourceValue.Capacity, IntPtr.Zero); result.ApplicationName = hresult == 0 ? resourceValue.ToString() : rawApplicationName; } var associations = new List <ApplicationAssociation>(); foreach (var subkeyName in new[] { "FileAssociations", "URLAssociations" }) { using (var subkey = key.OpenSubKey(subkeyName)) if (subkey != null) { foreach (var association in subkey.GetValueNames()) { var progId = subkey.GetValue(association) as string; associations.Add(new ApplicationAssociation { Association = association, ProgId = progId, }); } } } result.Associations = associations.ToArray(); } return(result); }
private static List <IntPtr> FindDescendantsBy(IntPtr parent, string className = null, string text = null) { var matches = new List <IntPtr>(); WindowsApi.EnumChildWindows(parent, (handle, pointer) => { if ( (className == null || WindowsHelpers.GetWindowClassName(handle) == className) && (text == null || WindowsHelpers.GetWindowTextRaw(handle) == text) ) { matches.Add(handle); } return(true); }, IntPtr.Zero); return(matches); }
public DesktopProcess(string commandLine, string desktopName) { var startupInfo = new WindowsApi.STARTUPINFO { cb = Marshal.SizeOf <WindowsApi.STARTUPINFO>(), lpDesktop = desktopName, }; if (!WindowsApi.CreateProcess( null, commandLine, null, null, true, 0, IntPtr.Zero, null, ref startupInfo, out processInformation )) { WindowsHelpers.CheckLastError(); } }
/// <param name="browser"></param> /// <exception cref="EnvironmentException"> /// When there is a problem with either <paramref name="browser"/> or the hosting environment. /// </exception> public static void Set(Browser browser) { // In Windows 10 version 1803, the old control-panel-style Default Programs screen has been replaced with a new one inside the Windows 10 settings app. // However, the Windows 10 settings app cannot be automated without the user seeing it or interacting with it, so that option is unreliable. // Fortunately, someone else has written a better alternative to this app (http://kolbi.cz/blog/?p=396). // So for these reasons, this app won't support this or later versions of Windows. if (OsInfo.Windows10Version >= 1803) { throw new EnvironmentException($"This app no longer works in this version of Windows."); } // This is needed since the control panel applet can crash if you give it an empty browser name if (String.IsNullOrWhiteSpace(browser.UniqueApplicationName)) { throw new EnvironmentException($"The given browser's unique application name is blank."); } using (var desktop = new Desktop("Default Browser Changer")) { var encodedBrowserName = Uri.EscapeDataString(browser.UniqueApplicationName); var desktopProcess = new DesktopProcess(@"control.exe /name Microsoft.DefaultPrograms /page pageDefaultProgram\pageAdvancedSettings?pszAppName=" + encodedBrowserName, desktop.Name); var exitCode = Wait(() => desktopProcess.GetExitCode()); //TODO: Replace this with WaitForSingleObject if (exitCode != 1) //Control.exe always returns 1 regardless of whether it had valid arguments. { throw new Exception("control.exe returned " + exitCode); } using (new DesktopContext(desktop.Handle)) { IntPtr window; try { // The window is located by class name rather than caption since the caption is locale-dependent. window = Wait(() => WindowsApi.FindWindow("CabinetWClass" /* Windows Explorer */, IntPtr.Zero)); } catch (TimeoutException timeout) { throw new EnvironmentException("The control panel applet didn't open. Try logging out and then logging in again.", timeout); } try { var listViewHandle = Wait(() => { var matches = FindDescendantsBy(window, className: "SysListView32"); var expectedListBoxCount = 1; if (matches.Count > expectedListBoxCount) { throw new Exception($"Found {matches.Count} list box(es), but expected {expectedListBoxCount}."); } return(matches.FirstOrDefault()); }); var listView = new ListView(listViewHandle); var save = Wait(() => { var matches = FindDescendantsBy(window, className: "Button"); if (matches.Count == 0) { return(default(IntPtr)); } var expectedButtonCount = 3; // Select All, Save, Cancel if (matches.Count != expectedButtonCount) { throw new Exception($"Found {matches} button(s), but expected {expectedButtonCount}."); } return(matches[1]); }); var browserAssociations = browser.Associations .Intersect(new[] { ".htm", ".html", "HTTP", "HTTPS" }, StringComparer.OrdinalIgnoreCase) .ToArray(); int[] checkboxIndices; try { checkboxIndices = Wait(() => { var itemIndices = ( from item in listView.GetListItems().Select((text, index) => new { text, index }) where browserAssociations.Contains(item.text, StringComparer.InvariantCultureIgnoreCase) select item.index ).ToArray(); if (itemIndices.Length < browserAssociations.Length) { return(null); } else { return(itemIndices); } }); } catch (TimeoutException timeout) { throw new EnvironmentException($"Didn't find all of the following extensions and protocols: {String.Join(", ", browserAssociations)}.", timeout); } foreach (var i in checkboxIndices) { listView.CheckItem(i); } WindowsApi.SendMessage(save, WindowsApi.BM_CLICK, IntPtr.Zero, IntPtr.Zero); } finally { WindowsApi.SendMessage(window, WindowsApi.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); //Just in case it doesn't close itself } } } }
/// <param name="browser"></param> /// <exception cref="EnvironmentException"> /// When there is a problem with either <paramref name="browser"/> or the hosting environment. /// </exception> public static void Set(Browser browser) { // This is needed since the control panel applet can crash if you give it an empty browser name if (String.IsNullOrWhiteSpace(browser.UniqueApplicationName)) { throw new EnvironmentException($"The given browser's unique application name is blank."); } using (var desktop = new Desktop("Default Browser Changer")) { var encodedBrowserName = Uri.EscapeDataString(browser.UniqueApplicationName); var desktopProcess = new DesktopProcess(@"control.exe /name Microsoft.DefaultPrograms /page pageDefaultProgram\pageAdvancedSettings?pszAppName=" + encodedBrowserName, desktop.Name); var exitCode = Wait(() => desktopProcess.GetExitCode()); //TODO: Replace this with WaitForSingleObject if (exitCode != 1) //Control.exe always returns 1 regardless of whether it had valid arguments. { throw new Exception("control.exe returned " + exitCode); } using (new DesktopContext(desktop.Handle)) { IntPtr window; try { window = Wait(() => WindowsApi.FindWindow(IntPtr.Zero, "Set Program Associations")); } catch (TimeoutException timeout) { throw new EnvironmentException("The control panel applet didn't open. Try logging out and then logging in again.", timeout); } try { var listViewHandle = Wait(() => FindDescendantBy(window, className: "SysListView32")); var listView = new ListView(listViewHandle); var save = Wait(() => FindDescendantBy(window, text: "Save")); var browserAssociations = browser.Associations .Intersect(new[] { ".htm", ".html", "HTTP", "HTTPS" }, StringComparer.OrdinalIgnoreCase) .ToArray(); int[] checkboxIndices; try { checkboxIndices = Wait(() => { var itemIndices = ( from item in listView.GetListItems().Select((text, index) => new { text, index }) where browserAssociations.Contains(item.text, StringComparer.InvariantCultureIgnoreCase) select item.index ).ToArray(); if (itemIndices.Length < browserAssociations.Length) { return(null); } else { return(itemIndices); } }); } catch (TimeoutException timeout) { throw new EnvironmentException($"Didn't find all of the following extensions and protocols: {String.Join(", ", browserAssociations)}.", timeout); } foreach (var i in checkboxIndices) { listView.CheckItem(i); } WindowsApi.SendMessage(save, WindowsApi.BM_CLICK, IntPtr.Zero, IntPtr.Zero); } finally { WindowsApi.SendMessage(window, WindowsApi.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); //Just in case it doesn't close itself } } } }
private static Process GetWindowProcess(IntPtr window) { WindowsApi.GetWindowThreadProcessId(window, out var processId); return(Process.GetProcessById((int)processId)); }