/// <summary> /// Sets the system theme to a custom .theme file /// </summary> /// <param name="filename">the path the the .theme file that should be set as the system theme</param> public static void SetCustomTheme(string filename) { //validate input if (filename == null) { throw new ArgumentNullException("filename"); } if (!File.Exists(filename)) { throw new FileNotFoundException("The specified theme file could not be found", filename); } if (Path.GetExtension(filename).ToLowerInvariant() != ".theme") { throw new ArgumentException("The theme file must have a .theme extention.", "filename"); } //Copy the file to another location before setting the theme //The reason for this is that if the custom theme is left after the test //executes the Automation Harness may delete the current theme which //gives and error that prevents the system from restoring the default theme string destFilename = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.InternetCache), Path.GetFileName(filename)); File.Copy(filename, destFilename, true); //Get the active window since the window activation will be lost by lauching the display properties IntPtr activehWnd = GetForegroundWindow(); ApplicationMonitor appMonitor = new ApplicationMonitor(); try { //invoke the theme and handle the dispay config UI appMonitor.RegisterUIHandler(new ChangeThemesUIHandler(), "rundll32", null, UIHandlerNotification.Visible); appMonitor.StartProcess(destFilename); if (!appMonitor.WaitForUIHandlerAbort(60000)) { throw new TimeoutException("The 60 second timeout occured while waiting for themes to change."); } } finally { //Stop the AppMonitor (this will kill rundll32 if it has not exited... hopefuly this wont leave the machine in a bad state if it a timeout occurs appMonitor.Close(); //Restore the active window if (activehWnd != IntPtr.Zero) { SetForegroundWindow(activehWnd); } } }
/// <summary> /// Start Host /// </summary> /// <param name="startupUri"></param> public void StartHost(string startupUri) { if (monitor != null) { throw new InvalidOperationException("You must first Close the Host before calling StartHost again."); } DictionaryStore.StartServer(); //use a custom startup page if (!string.IsNullOrEmpty(startupUri)) { DictionaryStore.Current[UiaDistributedTestcaseHost.StartupUriId] = startupUri; } monitor = new ApplicationMonitor(); GetHwndUIHandler handler = new GetHwndUIHandler(); // register for iexplore and have your app set the title monitor.RegisterUIHandler(handler, "iexplore", "RegExp:(Ready)", UIHandlerNotification.TitleChanged); //Clear the Click Once cache so the app is always re-activated ApplicationDeploymentHelper.CleanClickOnceCache(); //run the app monitor.StartProcess(xbapFileName); //wait for the UIHandler to return abort or timeout in 90 seconds if (!monitor.WaitForUIHandlerAbort(90000) || handler.topLevelhWnd == IntPtr.Zero) { throw new TimeoutException("A timeout occured while waiting for the XamlBrowserHost to navigate to the startUpPage"); } // monitor.StopMonitoring(); //Get the remoteHost object // //if we timedout then let the caller know that the app is not hosting this object //if (remoteHost == null) // throw new InvalidOperationException("The launched application did not create a host object in the Harness remote site"); //set the host hwnd hWndHost = handler.topLevelhWnd; }
/// <summary> /// Performs the Activation step /// </summary> /// <returns>returns true if the rest of the steps should be executed, otherwise, false</returns> protected override bool BeginStep() { //Create ApplicationMonitor appMonitor = new ApplicationMonitor(); // If defined, set a value in property bag. Used for communication test variations to target app if (PropertyBagValue != "") { // Update this code to allow > 1 prop bag values being set at once string[] values = PropertyBagValue.Trim().Split('='); if (values.Length == 2) { DictionaryStore.Current[values[0].Trim()] = values[1].Trim(); } else { throw new System.ArgumentException("Values must be a single 'foo=bar' format"); } } if (hostingPolicyResetter != null) { hostingPolicyResetter.Dispose(); } if (StrictHostingMode) { hostingPolicyResetter = HostingRuntimePolicyHelper.SetHostingRuntimePolicyValues( doNotLaunchV3AppInV4Runtime: true); } else { hostingPolicyResetter = HostingRuntimePolicyHelper.SetHostingRuntimePolicyValues( doNotLaunchV3AppInV4Runtime: false); } // upload files to FileHost is specified and scheme is not local if (Scheme != ActivationScheme.Local) { if (SupportFiles.Length > 0) { // Create host to copy files to... fileHost = new FileHost(UserDefinedDirectory, (Scheme == ActivationScheme.HttpInternetExternal)); // Upload each file foreach (SupportFile suppFile in SupportFiles) { // Whether to copy foo\bar\baz.xbap to the foo\bar created on the remote machine or just flattened fileHost.PreserveDirectoryStructure = suppFile.PreserveDirectoryStructure; if (suppFile.IncludeDependencies && !string.IsNullOrEmpty(suppFile.TargetDirectory)) { GlobalLog.LogEvidence("TargetDirectory with IncludeDependencies not yet implemented"); throw new NotImplementedException("TargetDirectory with IncludeDependencies not yet supported"); } if (suppFile.CustomTestScratchServerPath == null) { if (suppFile.IncludeDependencies) { fileHost.UploadFileWithDependencies(suppFile.Name); } else { fileHost.UploadFile(suppFile.Name, suppFile.TargetDirectory); } } else { fileHost.UploadFileNonDefaultServer(suppFile.Name, suppFile.CustomTestScratchServerPath); } } } // If no support files are listed, check the parent steps to see if one is a FileHostStep. // If this is the case, no need to upload the files as the FileHostStep has already. // Don't set throttle rate; this should be set in the markup for the parent's filehost. else { LoaderStep parent = this.ParentStep; while (parent != null) { if (parent.GetType() == typeof(Microsoft.Test.Loaders.Steps.FileHostStep)) { this.fileHost = ((FileHostStep)parent).fileHost; break; } // Failed to find it in the immediate parent: try til we hit null or the right one parent = parent.ParentStep; } } } // register UIHandlers foreach (UIHandler handler in UIHandlers) { if (handler.NamedRegistration != null) { appMonitor.RegisterUIHandler(handler, handler.NamedRegistration, handler.Notification); } else { appMonitor.RegisterUIHandler(handler, handler.ProcessName, handler.WindowTitle, handler.Notification); } } string param = ""; if (FileName.StartsWith("&") && FileName.EndsWith("&")) { param = DictionaryStore.Current[FileName.Substring(1, FileName.Length - 2)]; if (param == null) { throw new InvalidOperationException(FileName + " is not defined in the property bag; cannot be used to launch app"); } } else { // Allows for launching things in %program files%, which is localized. param = Environment.ExpandEnvironmentVariables(FileName); } if (Scheme != ActivationScheme.Local) { FileHostUriScheme hostScheme = FileHostUriScheme.Unc; if (Scheme != ActivationScheme.HttpInternetExternal) { hostScheme = (FileHostUriScheme)Enum.Parse(typeof(FileHostUriScheme), Scheme.ToString()); } param = fileHost.GetUri(FileName, hostScheme).ToString(); } // Clear the fusion cache by default. Can be disabled for custom ClickOnce scenarios if (ClearFusionCache) { ApplicationDeploymentHelper.CleanClickOnceCache(); } // Clear IE History but only if specified (defaults to false). Only matters for history-based navigation if (ClearIEHistory) { ApplicationDeploymentHelper.ClearIEHistory(); } // Launch the appropriate handler... switch (Method) { case ActivationMethod.Launch: { // This only works for local paths for security reasons. if (PresentationHostDebugMode) { param = Path.GetFullPath(param); // Workaround ... for some reason on XP64 there's no guarantee that it will actually find PresHost // Even though it verily is in the SysWOW64 directory. Solution... find the right one before we try string presHostPath = "presentationhost.exe"; if ((Environment.OSVersion.Version.Major == 5)) { presHostPath = (Directory.GetFiles(Environment.GetEnvironmentVariable("SystemRoot"), "PresentationHost.exe", SearchOption.AllDirectories))[0]; } appMonitor.StartProcess(presHostPath, " -debug \"" + param + "\""); } else { // Launch process with specified arguments. If shell: specified, then start that way. // If the arguments are for the URL, directly concatenate them. if ((Arguments.Length > 6) && (Arguments.ToLowerInvariant().StartsWith("shell:"))) { appMonitor.StartProcess(param, Environment.ExpandEnvironmentVariables(Arguments.Substring(6))); } else if ((Arguments.Length > 11) && (Arguments.ToLowerInvariant().StartsWith("currentdir:"))) { appMonitor.StartProcess(param, Path.Combine(Environment.CurrentDirectory, Arguments.Substring(11))); } else { appMonitor.StartProcess(param + Arguments); } } break; } case ActivationMethod.Navigate: { // If local we need to fully qualify the path if (Scheme == ActivationScheme.Local) { param = Path.GetFullPath(param); } // Fail to IE, since it has far more tests. string defaultBrowserExecutable = "iexplore.exe"; try { defaultBrowserExecutable = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Clients\StartMenuInternet", null, "iexplore.exe").ToString(); } catch (Exception) { try { defaultBrowserExecutable = Registry.GetValue(@"HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet", null, "iexplore.exe").ToString(); } catch (Exception) { // Do nothing, some machines have been seen in weird states where this is undefined. Log it anyways. GlobalLog.LogDebug("Unable to get StartMenuInternet key, FireFox or other non-standard browser tests may be affected. Contact Microsoft if this is the case"); } } // Handle the case where this value exists but isnt set to anything usable. IE is far more common so fall back to it. if (string.IsNullOrEmpty(defaultBrowserExecutable)) { defaultBrowserExecutable = "iexplore.exe"; } // start the default browser... currently just FF or IE. if (defaultBrowserExecutable.ToLowerInvariant().Contains("iexplore")) { // Create & register IE navigation handler // IE can be strange: About:NavigateIE sometimes gets a cancelled navigation // Workaround: Be less sensitive about the window title we trigger on. appMonitor.RegisterUIHandler(new NavigateIE(param + Arguments), "iexplore", "RegExp:(Internet Explorer)", UIHandlerNotification.All); appMonitor.StartProcess("iexplore.exe", "about:NavigateIE"); } else if (defaultBrowserExecutable.ToLowerInvariant().Contains("firefox")) { if (Scheme == ActivationScheme.Unc) { param = param.Replace("file:", "").Replace("/", @"\"); } } else { throw new InvalidOperationException("Don't know how to navigate an instance of \"" + defaultBrowserExecutable + "\" browser!!! Contact Microsoft with this message."); } break; } // GOTO used here for fallthrough since there's only 2 lines difference. case ActivationMethod.EHome: goto case ActivationMethod.EHomeFullScreen; case ActivationMethod.EHomeFullScreen: { // If local we need to fully qualify the path if (Scheme == ActivationScheme.Local) { param = Path.GetFullPath(param); } // Get a reference to the path for the ehome exe... string eHomePath = Environment.GetEnvironmentVariable("SystemRoot") + "\\ehome\\ehshell.exe"; // Fail hard if EHome isnt present on the system. // Need to mark testcases accurately in test DB to avoid this. if (!File.Exists(eHomePath)) { throw new InvalidOperationException("\"Ehome\" or \"EHomeFullScreen\" method selected but case was run on non-Media-Center-enabled SKU! \n Contact Microsoft for more info on this issue."); } // Construct args with path to content to launch (MUST be a Uri) string eHomeArgs = "/url:\"" + param + "\""; // Tack on the argument for full screen if requested if (Method == ActivationMethod.EHomeFullScreen) { eHomeArgs += " /directmedia:general"; } // Start MCE... appMonitor.StartProcess(eHomePath, eHomeArgs); break; } } // Store the activation path into the property bag. This way apps or child steps can directly figure out the deployment URI DictionaryStore.Current["ActivationStepUri"] = param; return(true); }
/// <summary> /// Change the theme, style, and color scheme to match a defined appearance /// </summary> /// <param name="appearance">the desired defined appearance</param> public static void SetAppearance(DesktopAppearance appearance) { if (appearance == GetAppearance()) { return; } else if ((!new ArrayList(GetAvailableAppearances()).Contains(appearance))) { throw new ArgumentException("The appearance '" + appearance + "' is not currently available.", appearance.ToString()); } string themeName = GetTheme(); string styleFilename = null; // This is only needed if a change in color scheme is required (for Luna and Aero) UIHandler appearanceUIHandler = null; if (appearance == DesktopAppearance.LunaNormalColor || appearance == DesktopAppearance.LunaMetallic || appearance == DesktopAppearance.LunaHomestead) { // First ensure the theme is set to Luna if (themeName.ToLowerInvariant() != LunaString.ToLowerInvariant()) { SetTheme(LunaString); themeName = GetTheme(); if (themeName.ToLowerInvariant() != LunaString.ToLowerInvariant()) { throw new ArgumentException("Failed to change to the theme '" + LunaString + "'.", appearance.ToString()); } } // Build the path for the Luna.msstyles file styleFilename = Path.Combine(themeDirectory, themeName + @"\" + themeName + ".msstyles"); if (!File.Exists(styleFilename)) { throw new ArgumentException("The msstyles file '" + styleFilename + "' does not exist.", appearance.ToString()); } string lunaResourceString = ""; // Get the localized string to select in the color scheme menu if (appearance == DesktopAppearance.LunaMetallic) { lunaResourceString = Microsoft.Test.Loaders.ResourceHelper.GetUnmanagedResourceString(styleFilename, 1001); } else if (appearance == DesktopAppearance.LunaHomestead) { lunaResourceString = Microsoft.Test.Loaders.ResourceHelper.GetUnmanagedResourceString(styleFilename, 1002); } else { lunaResourceString = Microsoft.Test.Loaders.ResourceHelper.GetUnmanagedResourceString(styleFilename, 1000); } // Use the UIHandler for the XP Appearance dialog appearanceUIHandler = new ChangeXPAppearanceUIHandler(lunaResourceString); } else if (appearance == DesktopAppearance.AeroWithoutComposition || appearance == DesktopAppearance.AeroWithComposition) { // First ensure the theme is set to Aero if (themeName.ToLowerInvariant() != AeroString.ToLowerInvariant()) { SetTheme(AeroString); themeName = GetTheme(); if (themeName.ToLowerInvariant() != AeroString.ToLowerInvariant()) { throw new ArgumentException("Failed to change to the theme '" + AeroString + "'.", appearance.ToString()); } } // Build the path to Aero.msstyles styleFilename = Path.Combine(themeDirectory, themeName + @"\" + themeName + ".msstyles"); if (!File.Exists(styleFilename)) { throw new ArgumentException("The msstyles file '" + styleFilename + "' does not exist.", appearance.ToString()); } // Use the UIHandler for the Vista Appearance dialog appearanceUIHandler = new ChangeVistaAppearanceUIHandler(appearance); } else if (appearance == DesktopAppearance.Royale) { // Change the theme to Royale if (themeName.ToLowerInvariant() != RoyaleString.ToLowerInvariant()) { SetTheme(RoyaleString); themeName = GetTheme(); if (themeName.ToLowerInvariant() != RoyaleString.ToLowerInvariant()) { throw new ArgumentException("Failed to change to the theme '" + RoyaleString + "'.", appearance.ToString()); } } } else if (appearance == DesktopAppearance.WindowsClassic) { // Change the theme to Classic if (themeName.ToLowerInvariant() != WindowsClassicString.ToLowerInvariant()) { SetTheme(WindowsClassicString); themeName = GetTheme(); if (themeName.ToLowerInvariant() != WindowsClassicString.ToLowerInvariant()) { throw new ArgumentException("Failed to change to the theme '" + WindowsClassicString + "'.", appearance.ToString()); } } } if (appearanceUIHandler != null) { //Get the active window since the window activation will be lost by lauching the display properties IntPtr activehWnd = GetForegroundWindow(); ApplicationMonitor appMonitor = new ApplicationMonitor(); try { //invoke the msstyles file and handle the dispay config UI appMonitor.RegisterUIHandler(appearanceUIHandler, "rundll32", null, UIHandlerNotification.Visible); appMonitor.StartProcess(styleFilename); if (!appMonitor.WaitForUIHandlerAbort(60000)) { throw new TimeoutException("The 60 second timeout occured while waiting for themes to change."); } } finally { //Stop the AppMonitor (this will kill rundll32 if it has not exited... hopefuly this wont leave the machine in a bad state if it a timeout occurs appMonitor.Close(); //Restore the active window if (activehWnd != IntPtr.Zero) { SetForegroundWindow(activehWnd); } } } if (GetAppearance() != appearance) { throw new Exception("Unable to change appearance."); } }