Esempio n. 1
0
 public void Dispose()
 {
     if (!WindowsApi.CloseDesktop(Handle))
     {
         WindowsHelpers.CheckLastError();
     }
 }
Esempio n. 2
0
 public void Dispose()
 {
     if (!WindowsApi.SetThreadDesktop(originalDesktop))
     {
         WindowsHelpers.CheckLastError();
     }
 }
Esempio n. 3
0
        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());
        }
Esempio n. 4
0
        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);
        }
Esempio n. 7
0
        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();
            }
        }
Esempio n. 10
0
        /// <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();
            }
        }
Esempio n. 11
0
        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");
                }
            }
        }
Esempio n. 12
0
        /// <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);
                }
            }
        }
Esempio n. 13
0
        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
                    }
                }
            }
        }
Esempio n. 17
0
        /// <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
                    }
                }
            }
        }
Esempio n. 18
0
 private static Process GetWindowProcess(IntPtr window)
 {
     WindowsApi.GetWindowThreadProcessId(window, out var processId);
     return(Process.GetProcessById((int)processId));
 }