private static void CloseAndWaitForWindow() { // close the window Keyboard.Press(Key.Alt); Keyboard.Press(Key.F4); Keyboard.Release(Key.F4); Keyboard.Release(Key.Alt); int counter = 0; int max = 20; bool found = true; while (counter < max && found) { Thread.Sleep(1000); counter++; found = false; foreach (var process in Process.GetProcesses()) { if (process.ProcessName.ToLower() == ThemeProcessName) { IntPtr hWnd = WindowEnumerator.FindFirstWindowWithCaption(process, "personalization"); if (hWnd != IntPtr.Zero) { found = true; break; } } } } }
/// <remarks> /// For the case of OS versons 6.1 and above the process for setting /// the theme is as follows: /// /// 1. launch the .theme file (theme is automatically selected) /// 2. wait for explorer to launch the 'personalization' child window /// 3. close the 'personalization' window /// /// Unlike MonitorProcess, explorer.exe is already running and a subwindow is launched for /// this process. /// </remarks> private static void SetThemeThroughExplorer(string themeFilename) { // Get the active window since the window activation will be lost // by lauching the ControlPanel.Personalization window. IntPtr activehWnd = IntPtr.Zero; ManualResetEvent waitEvent = new ManualResetEvent(false); System.Timers.Timer timer = null; bool enterFlag = true; try { // initialize the wait event waitEvent.Reset(); activehWnd = NativeMethods.GetForegroundWindow(); // set the actual theme which launches the personalization window Process themeChangeProcess = new Process(); themeChangeProcess.StartInfo.FileName = themeFilename; themeChangeProcess.Start(); // wait for the window to activate timer = new System.Timers.Timer(1500); timer.Elapsed += (s, e) => { if (enterFlag) { enterFlag = false; foreach (var process in Process.GetProcesses()) { if (process.ProcessName.ToLower() == ThemeProcessName) { IntPtr hWnd = WindowEnumerator.FindFirstWindowWithCaption(process, "personalization"); if (hWnd != IntPtr.Zero) { // first make sure it's active int maxCounter = 20; int counter = 0; IntPtr foregroundHWnd = NativeMethods.GetForegroundWindow(); Console.WriteLine("Thread: " + Thread.CurrentThread.ManagedThreadId + ", foregourndHWnd: " + foregroundHWnd + ", hWnd: " + hWnd); while ((foregroundHWnd != hWnd || !NativeMethods.IsWindowVisible(hWnd)) && counter < maxCounter && timer != null) { Console.WriteLine("Thread: " + Thread.CurrentThread.ManagedThreadId + ", restore the window. hWnd: " + hWnd + ", foregroundHWnd: " + foregroundHWnd); NativeMethods.ShowWindow(hWnd, NativeMethods.SW_RESTORE); Thread.Sleep(500); NativeMethods.BringWindowToTop(hWnd); Thread.Sleep(500); foregroundHWnd = NativeMethods.GetForegroundWindow(); counter++; } if (foregroundHWnd == hWnd) { timer.Stop(); CloseAndWaitForWindow(); waitEvent.Set(); } break; } } } enterFlag = true; } }; timer.Start(); waitEvent.WaitOne(60000, false); } finally { enterFlag = false; if (timer != null) { timer.Stop(); timer.Dispose(); timer = null; } // Restore the active window if (activehWnd != IntPtr.Zero) { NativeMethods.SetForegroundWindow(activehWnd); } } }