Hello GitHub

This commit is contained in:
Howard Wolosky
2019-01-28 16:24:37 -08:00
parent 456fe5e355
commit c13b8a099e
822 changed files with 276650 additions and 75 deletions

View File

@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Calculator.UIAutomationLibrary
{
public class Constants
{
/// <summary>
/// The path to the certificate file.
/// </summary>
public const string CertificateFileName = @"Calculator.cer";
/// <summary>
/// The path to the appxbundle file.
/// </summary>
public const string PackageFileName = @"Calculator.appxbundle";
/// <summary>
/// The path to the appxbundle file.
/// </summary>
public const string VCLibsPackageFileName = @"Microsoft.VCLibs.appx";
/// <summary>
/// The path to the appxbundle file.
/// </summary>
public const string WinUIPackageFileName = @"Microsoft.UI.Xaml.appx";
/// <summary>
/// Name of the CoreWindow.
/// </summary>
public const string AppWindowName = "Calculator";
/// <summary>
/// Name of the process executable.
/// </summary>
public const string ProcessName = "Calculator.exe";
/// <summary>
/// The package name.
/// </summary>
public const string PackageName = "Microsoft.WindowsCalculator";
/// <summary>
/// The package family name for the app to test.
/// </summary>
public const string PackageFamilyName = PackageName + "_8wekyb3d8bbwe";
/// <summary>
/// The package App User Model Id.
/// </summary>
public const string PackageAppUserModelId = PackageFamilyName + "!App";
/// <summary>
/// AutomationId for the top level UI element.
/// </summary>
public const string TopLevelWindowAutomationId = "CalculatorWindow";
/// <summary>
/// Event fired when the first page is loaded.
/// </summary>
public const string AppLaunchEndETWEventName = "AppLaunchEnd";
/// <summary>
/// App Provider GUID for ETW Events
/// </summary>
public static readonly Guid CalculatorETWProviderGUID = new Guid("0905CA09-610E-401E-B650-2F212980B9E0");
/// <summary>
/// Event fired when a calculator mode change is complete.
/// </summary>
public const string AppModeChangeEndETWEventName = "ModeChangeEnd";
/// <summary>
/// Event fired when the History panel is opened by flyout or by changing pivot tabs.
/// </summary>
public const string HistoryBodyOpenedETWEventName = "HistoryBodyOpened";
/// <summary>
/// Event fired when the Memory panel is opened by flyout or by changing pivot tabs.
/// </summary>
public const string MemoryBodyOpenedETWEventName = "MemoryBodyOpened";
/// <summary>
/// Event fired when the About flyout control is loaded.
/// </summary>
public const string AboutFlyoutOpenedETWEventName = "AboutFlyoutOpened";
/// <summary>
/// Event fired when the Nav Bar control is opened.
/// </summary>
public const string NavBarOpenedETWEventName = "NavBarOpened";
/// <summary>
/// Margin used to click in the gutter beneath the History and Memory lists
/// </summary>
public const int ClickMargin = 10;
}
}

View File

@@ -0,0 +1,101 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.OneCoreUap.Test.AppModel;
using WEX.Logging.Interop;
namespace Calculator.UIAutomationLibrary
{
public class EtwHelper
{
private static bool etwServiceWasInstalled = false;
/// <summary>
/// Installs and starts the Etw.Service so that Tests may utilize Etw Waiters.
/// Wex.Services.exe is part of TAEF.
/// </summary>
public static void InstallAndStartETWService()
{
etwServiceWasInstalled = ServiceHelper.IsInstalled("Etw.Service");
if (!etwServiceWasInstalled)
{
string wexServices = Path.Combine(TAEFHelper.GetTestDeploymentDirectory(), "Wex.Services.exe");
if (!File.Exists(wexServices))
{
throw new FileNotFoundException(wexServices);
}
Log.Comment("Attempting to install Etw.Service...");
var startInfo = new ProcessStartInfo();
startInfo.FileName = wexServices;
startInfo.Arguments = "/install:Etw.Service";
var process = new Process();
process.StartInfo = startInfo;
if (process.Start())
{
process.WaitForExit();
Log.Comment("Completed installation of Etw.Service");
}
else
{
throw new Exception("ETW service was not able to be installed. Process didn't start.");
}
}
Log.Comment("Attempting to start Etw.Service...");
ServiceHelper.Start("Etw.Service");
Log.Comment("Etw.Service started");
}
/// <summary>
/// Stops the Etw.Service.
/// </summary>
public static void StopAndRemoveETWService()
{
if (ServiceHelper.IsInstalled("Etw.Service"))
{
Log.Comment("Attempting to stop Etw.Service...");
ServiceHelper.Stop("Etw.Service");
Log.Comment("Etw.Service stopped");
// if we installed the Etw.Service as part of this test we should also remove it.
// This prevents cases where TDP is upgraded but the service tregistration is referencing the old
// location that no longer exists.
if (!etwServiceWasInstalled)
{
string wexServices = Path.Combine(TAEFHelper.GetTestDeploymentDirectory(), "Wex.Services.exe");
if (!File.Exists(wexServices))
{
throw new FileNotFoundException(wexServices);
}
Log.Comment("Attempting to remove Etw.Service...");
var startInfo = new ProcessStartInfo();
startInfo.FileName = wexServices;
startInfo.Arguments = "/remove:Etw.Service";
var process = new Process();
process.StartInfo = startInfo;
if (process.Start())
{
process.WaitForExit();
Log.Comment("Completed removal of Etw.Service");
}
else
{
throw new Exception("ETW service could not be removed. Process didn't start.");
}
}
}
}
}
}

View File

@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
namespace Calculator.UIAutomationLibrary
{
public static class Impersonater
{
public static void RunAs(RunAsUser user, Action action)
{
IntPtr errorInfo;
SafeAccessTokenHandle restrictedToken;
GetRunAsUserToken getRunAsUserToken = ResolveGetRunAsUserTokenMethod();
Marshal.ThrowExceptionForHR(getRunAsUserToken(user, out restrictedToken, out errorInfo), errorInfo);
WindowsIdentity.RunImpersonated(restrictedToken, action);
}
public static void RunAs<T>(RunAsUser user, Func<T> function)
{
IntPtr errorInfo;
SafeAccessTokenHandle restrictedToken;
GetRunAsUserToken getRunAsUserToken = ResolveGetRunAsUserTokenMethod();
Marshal.ThrowExceptionForHR(getRunAsUserToken(user, out restrictedToken, out errorInfo), errorInfo);
WindowsIdentity.RunImpersonated(restrictedToken, function);
}
// From: https://microsoft.visualstudio.com/EngSys/_git/validation.taef?path=%2Fsrc%2FTAEF%2FCommon%2FPublished%2FRunAsFromSystem.h&version=GBdevelop
public enum RunAsUser
{
ElevatedUser,
User,
RestrictedUser,
LowIL,
InteractiveUser,
};
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetRunAsUserToken(RunAsUser user, out SafeAccessTokenHandle token, out IntPtr errorInfo);
// GetRunAsUserToken is defined in a namespace so we have to do some tricks to use P/Invoke.
// We got the actual exported method name by running dumpbin /exports TE.Common.dll
private static GetRunAsUserToken ResolveGetRunAsUserTokenMethod()
{
IntPtr teCommonDll = IntPtr.Zero;
try
{
teCommonDll = LoadLibrary(@"TE.Common.dll");
IntPtr x64GetRunAsUserToken = GetProcAddress(teCommonDll, "?GetRunAsUserToken@TestExecution@WEX@@YAJW4RunAsUser@12@PEAPEAXPEAPEAUIErrorInfo@@@Z");
if (x64GetRunAsUserToken != IntPtr.Zero)
{
return Marshal.GetDelegateForFunctionPointer<GetRunAsUserToken>(x64GetRunAsUserToken);
}
IntPtr x86GetRunAsUserToken = GetProcAddress(teCommonDll, "?GetRunAsUserToken@TestExecution@WEX@@YGJW4RunAsUser@12@PAPAXPAPAUIErrorInfo@@@Z");
if (x86GetRunAsUserToken != IntPtr.Zero)
{
return Marshal.GetDelegateForFunctionPointer<GetRunAsUserToken>(x86GetRunAsUserToken);
}
IntPtr armGetRunAsUserToken = GetProcAddress(teCommonDll, "?GetRunAsUserToken@TestExecution@WEX@@YAJW4RunAsUser@12@PAPAXPAPAUIErrorInfo@@@Z");
if (armGetRunAsUserToken != IntPtr.Zero)
{
return Marshal.GetDelegateForFunctionPointer<GetRunAsUserToken>(armGetRunAsUserToken);
}
IntPtr arm64GetRunAsUserToken = GetProcAddress(teCommonDll, "?GetRunAsUserToken@TestExecution@WEX@@YAJW4RunAsUser@12@PEAPEAXPEAPEAUIErrorInfo@@@Z");
if (arm64GetRunAsUserToken != IntPtr.Zero)
{
return Marshal.GetDelegateForFunctionPointer<GetRunAsUserToken>(arm64GetRunAsUserToken);
}
throw new Exception("Unable to find the GetRunAsUserToken function in DLL 'TE.Common.dll'");
}
finally
{
if (teCommonDll != IntPtr.Zero)
{
FreeLibrary(teCommonDll);
}
}
}
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
}

View File

@@ -0,0 +1,84 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using Microsoft.OneCoreUap.Test.AppModel;
using WEX.Logging.Interop;
using Windows.Foundation;
using Windows.Management.Deployment;
namespace Calculator.UIAutomationLibrary
{
public class InstallHelper
{
public static void InstallCertFile(string certFilePath)
{
// Ensure cert exists.
if (!File.Exists(certFilePath))
{
throw new FileNotFoundException(certFilePath);
}
// For some reason, attempting to use CertificateHelper.InstallFromSignedPackage() to install
// the certificate associated with the appx package fails with the error:
// "A certificate chain could not be built to a trusted root authority."
// The reason is that the cert needs to be installed in 'StoreName.TrustedPeople',
// but DeploymentHelper.AddPackage() attempts to install it in 'StoreName.Root'.
// Therefore, the cert has been installed manually beforehand.
Log.Comment($"Starting install of certificate at {certFilePath}");
X509Certificate2 certificate = new X509Certificate2(certFilePath);
X509Store trustedPeopleStore = new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine);
trustedPeopleStore.Open(OpenFlags.MaxAllowed);
trustedPeopleStore.Add(certificate);
Log.Comment($"Completed install of certificate");
}
/// <summary>
/// Upgrades the appx/appxbundle from the path if needed.
/// </summary>
public static void InstallPackage(string appxFilePath, params string[] dependencyAppxFilePaths)
{
// Ensure the files exist.
if (!File.Exists(appxFilePath))
{
throw new FileNotFoundException(appxFilePath);
}
foreach (var path in dependencyAppxFilePaths.Where(p => !File.Exists(p)))
{
throw new FileNotFoundException(path);
}
Log.Comment($"Starting install of app package at {appxFilePath}");
PackageManager packageManager = new PackageManager();
var deploymentOperation = packageManager.AddPackageAsync(
new Uri(appxFilePath),
dependencyAppxFilePaths.Select(d => new Uri(d)),
DeploymentOptions.ForceApplicationShutdown | DeploymentOptions.ForceTargetApplicationShutdown | DeploymentOptions.ForceUpdateFromAnyVersion);
WaitForDeploymentOperation(deploymentOperation);
Log.Comment("Completed install of app package");
}
/// <summary>
/// Waits for a deployment operation to complete
/// </summary>
private static void WaitForDeploymentOperation(IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> operation)
{
ManualResetEvent isCompletedEvent = new ManualResetEvent(false);
operation.Completed = (IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> asyncInfo, AsyncStatus asyncStatus) =>
{
isCompletedEvent.Set();
};
isCompletedEvent.WaitOne();
}
}
}

View File

@@ -0,0 +1,139 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Calculator.UIAutomationLibrary
{
internal static class NativeMethods
{
internal const int GW_OWNER = 4;
internal delegate bool EnumThreadWindowsCallback(IntPtr hWnd, IntPtr lParam);
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
internal static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr extraData);
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
internal static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
internal static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
internal static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
internal static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
[DllImport("api-ms-win-ntuser-ie-window-l1-1-0.dll", SetLastError = true)]
internal static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors);
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ControlService(IntPtr hService, SERVICE_CONTROL dwControl, ref SERVICE_STATUS lpServiceStatus);
[DllImport("api-ms-win-service-management-l1-1-0.dll")]
internal static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseServiceHandle(IntPtr hSCObject);
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport("api-ms-win-service-management-l1-1-0.dll", SetLastError = true)]
internal static extern bool QueryServiceStatus(IntPtr hService, ref SERVICE_STATUS dwServiceStatus);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct SERVICE_STATUS
{
public int dwServiceType;
public int dwCurrentState;
public int dwControlsAccepted;
public int dwWin32ExitCode;
public int dwServiceSpecificExitCode;
public int dwCheckPoint;
public int dwWaitHint;
}
internal static uint STANDARD_RIGHTS_REQUIRED = 0xF0000;
internal static uint SC_MANAGER_CONNECT = 0x0001;
internal static uint SC_MANAGER_CREATE_SERVICE = 0x0002;
internal static uint SC_MANAGER_ENUMERATE_SERVICE = 0x0004;
internal static uint SC_MANAGER_LOCK = 0x0008;
internal static uint SC_MANAGER_QUERY_LOCK_STATUS = 0x0010;
internal static uint SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020;
internal static uint SC_MANAGER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SC_MANAGER_CONNECT |
SC_MANAGER_CREATE_SERVICE |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_LOCK |
SC_MANAGER_QUERY_LOCK_STATUS |
SC_MANAGER_MODIFY_BOOT_CONFIG);
internal static uint SERVICE_QUERY_CONFIG = 0x0001;
internal static uint SERVICE_CHANGE_CONFIG = 0x0002;
internal static uint SERVICE_QUERY_STATUS = 0x0004;
internal static uint SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
internal static uint SERVICE_START = 0x0010;
internal static uint SERVICE_STOP = 0x0020;
internal static uint SERVICE_PAUSE_CONTINUE = 0x0040;
internal static uint SERVICE_INTERROGATE = 0x0080;
internal static uint SERVICE_USER_DEFINED_CONTROL = 0x0100;
internal static uint SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SERVICE_QUERY_CONFIG |
SERVICE_CHANGE_CONFIG |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS |
SERVICE_START |
SERVICE_STOP |
SERVICE_PAUSE_CONTINUE |
SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL);
[Flags]
internal enum SERVICE_CONTROL : uint
{
STOP = 0x00000001,
PAUSE = 0x00000002,
CONTINUE = 0x00000003,
INTERROGATE = 0x00000004,
SHUTDOWN = 0x00000005,
PARAMCHANGE = 0x00000006,
NETBINDADD = 0x00000007,
NETBINDREMOVE = 0x00000008,
NETBINDENABLE = 0x00000009,
NETBINDDISABLE = 0x0000000A,
DEVICEEVENT = 0x0000000B,
HARDWAREPROFILECHANGE = 0x0000000C,
POWEREVENT = 0x0000000D,
SESSIONCHANGE = 0x0000000E
}
internal enum SERVICE_STATE : int
{
SERVICE_STOPPED = 0x00000001,
SERVICE_START_PENDING = 0x00000002,
SERVICE_STOP_PENDING = 0x00000003,
SERVICE_RUNNING = 0x00000004,
SERVICE_CONTINUE_PENDING = 0x00000005,
SERVICE_PAUSE_PENDING = 0x00000006,
SERVICE_PAUSED = 0x00000007
}
}
}

View File

@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
namespace Calculator.UIAutomationLibrary
{
public class PerfConstants
{
/// <summary>
/// Path where the regions, wprprofiles and wpaprofiles will be deployed to by the spkg.
/// </summary>
public const string ConfigDirectory = @"Config\";
/// <summary>
/// Our FunGates source, where we can view test results.
/// </summary>
public const string FunGatesSource =
#if DEBUG
"TestSite";
#else
"Utility Apps Performance Tests";
#endif
/// <summary>
/// The Windows Performance Recorder profile. These strings must have the config directory prefix.
/// For use with the WPRProfileFile test attribute.
/// </summary>
public const string AppLifecycleWPRProfile = ConfigDirectory + "AppLifecycle.Profile.wprp";
/// <summary>
/// The regions of interest file that contains the events we are interested in measuring.
/// </summary>
public const string AppLifecycleRegions = ConfigDirectory + "AppLifecycle.regions.xml";
/// <summary>
/// These are uses with the DataSource test property to specify iteration info.
/// </summary>
public const string AppLifecycleInterationsSource = "Table:" + ConfigDirectory + "AppLifecycle.Iterations.xml#PerformanceConfigurations";
}
}

View File

@@ -0,0 +1,156 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Calculator.UIAutomationLibrary
{
public class ServiceHelper
{
public static void Start(string serviceName, int timeoutInMilliSeconds = 30000)
{
IntPtr hService = IntPtr.Zero;
IntPtr hSCManager = IntPtr.Zero;
try
{
hSCManager = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
if (IntPtr.Zero == hSCManager)
{
throw new Exception($"Start: Cannot Open OpenSCManager, {Marshal.GetLastWin32Error()}");
}
hService = NativeMethods.OpenService(hSCManager, serviceName, NativeMethods.SERVICE_ALL_ACCESS);
if (IntPtr.Zero == hService)
{
throw new Exception($"Start: Cannot Open Service, {Marshal.GetLastWin32Error()}");
}
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
{
throw new Exception($"Start: Unable to query status of Service, {Marshal.GetLastWin32Error()}");
}
if (serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_RUNNING &&
serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_START_PENDING)
{
if (!NativeMethods.StartService(hService, 0, null))
{
throw new Exception($"Start: Service cannot be started, {Marshal.GetLastWin32Error()}");
}
}
WaitForStatus(hService, NativeMethods.SERVICE_STATE.SERVICE_RUNNING, TimeSpan.FromMilliseconds(timeoutInMilliSeconds));
}
finally
{
if (IntPtr.Zero != hService)
{
NativeMethods.CloseServiceHandle(hService);
}
if (IntPtr.Zero != hSCManager)
{
NativeMethods.CloseServiceHandle(hSCManager);
}
}
}
public static void Stop(string serviceName, int timeoutInMilliSeconds = 30000)
{
IntPtr hSCManager = IntPtr.Zero;
IntPtr hService = IntPtr.Zero;
try
{
hSCManager = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
if (IntPtr.Zero == hSCManager)
{
throw new Exception($"Stop: Cannot Open OpenSCManager, {Marshal.GetLastWin32Error()}");
}
hService = NativeMethods.OpenService(hSCManager, serviceName, NativeMethods.SERVICE_ALL_ACCESS);
if (IntPtr.Zero == hService)
{
throw new Exception($"Stop: Cannot Open Service, {Marshal.GetLastWin32Error()}");
}
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
{
throw new Exception($"Stop: Unable to query status of Service, {Marshal.GetLastWin32Error()}");
}
if (serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_STOPPED &&
serviceStatus.dwCurrentState != (int)NativeMethods.SERVICE_STATE.SERVICE_STOP_PENDING)
{
if (!NativeMethods.ControlService(hService, NativeMethods.SERVICE_CONTROL.STOP, ref serviceStatus))
{
throw new Exception($"Stop: Service cannot be stopped, {Marshal.GetLastWin32Error()}");
}
}
WaitForStatus(hService, NativeMethods.SERVICE_STATE.SERVICE_STOPPED, TimeSpan.FromMilliseconds(timeoutInMilliSeconds));
}
finally
{
if (IntPtr.Zero != hService)
{
NativeMethods.CloseServiceHandle(hService);
}
if (IntPtr.Zero != hSCManager)
{
NativeMethods.CloseServiceHandle(hSCManager);
}
}
}
public static bool IsInstalled(string svcName)
{
IntPtr sc_handle = NativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL_ACCESS);
if (sc_handle == IntPtr.Zero)
{
throw new Exception($"IsInstalled: Cannot open service manager, {Marshal.GetLastWin32Error()}");
}
bool bResult = false;
IntPtr sv_handle = NativeMethods.OpenService(sc_handle, svcName, NativeMethods.SERVICE_QUERY_CONFIG);
if (sv_handle.ToInt64() != 0)
{
bResult = true;
NativeMethods.CloseServiceHandle(sv_handle);
}
NativeMethods.CloseServiceHandle(sc_handle);
return bResult;
}
private static void WaitForStatus(IntPtr hService, NativeMethods.SERVICE_STATE desiredStatus, TimeSpan timeout)
{
Stopwatch swLoop = new Stopwatch();
swLoop.Start();
NativeMethods.SERVICE_STATUS serviceStatus = new NativeMethods.SERVICE_STATUS();
do
{
Thread.Sleep(500);
if (!NativeMethods.QueryServiceStatus(hService, ref serviceStatus))
{
throw new Exception($"WaitForStatus: Unable to query status of service, {Marshal.GetLastWin32Error()}");
}
}
while (serviceStatus.dwCurrentState != (int)desiredStatus && (swLoop.ElapsedMilliseconds <= timeout.TotalMilliseconds));
if (serviceStatus.dwCurrentState != (int)desiredStatus)
{
throw new Exception($"WaitForStatus: Service failed to reach desired state: {desiredStatus}, current state: {serviceStatus.dwCurrentState}");
}
}
}
}

View File

@@ -0,0 +1,66 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Linq;
using System.Windows.Automation;
using MS.Internal.Mita.Foundation;
using MS.Internal.Mita.Foundation.Controls;
using MS.Internal.Mita.Foundation.Waiters;
using WEX.Logging.Interop;
namespace Calculator.UIAutomationLibrary
{
public static class UIObjectExtensions
{
private const string NamePropertyName = "Name";
private static UICondition CoreWindowCondition = UICondition.CreateFromClassName("Windows.UI.Core.CoreWindow");
public static Window GetParentCoreWindow(this UIObject uiObject)
{
if (uiObject.Matches(CoreWindowCondition))
{
return new Window(uiObject);
}
return new Window(uiObject.Ancestors.Find(CoreWindowCondition));
}
public static Window GetTopLevelWindow(this Window window)
{
var node = window;
while (node != null && node.Parent != null && node.Parent.ControlType == ControlType.Window)
{
node = new Window(node.Parent);
}
return node;
}
public static void VerifyParentTreeStructure(this UIObject uiObject)
{
var node = uiObject;
while (node != null && node.Parent != null)
{
if (!node.Parent.Children.Contains(node))
{
Log.Comment($"- [VerifyingTree] {node} specifies {node.Parent} as parent but is not part of its children.");
}
if (!node.Parent.Descendants.Contains(node))
{
Log.Comment($"- [VerifyingTree] {node} specifies {node.Parent} as parent but is not part of its descendants.");
}
node = node.Parent;
}
}
public static bool DoesDescendantExist(this UIObject uiObject, string automationId)
{
UIObject temp;
return uiObject.Descendants.TryFind(automationId, out temp);
}
public static PropertyChangedEventWaiter GetNameChangedWaiter(this TextBlock textBlock)
{
return new PropertyChangedEventWaiter(textBlock, UIProperty.Get(NamePropertyName));
}
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
using System.IO;
using WEX.Logging.Interop;
namespace Calculator.UIAutomationLibrary
{
public class Utilities
{
public static void KillExistingCalculatorProcesses()
{
Log.Comment("Killing any existing Calculator processes");
foreach (var process in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(Constants.ProcessName)))
{
try
{
process.Kill();
Log.Comment($"Killed {process.ProcessName}, Id: {process.Id}");
}
catch (Exception) when (process.HasExited)
{
Log.Comment($"{process.ProcessName}, Id: {process.Id} already exited.");
}
}
}
}
}

View File

@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using MS.Internal.Mita.Foundation.Controls;
using WEX.Logging.Interop;
namespace Calculator.UIAutomationLibrary
{
public class WindowHelper
{
public static void SetAsForeground(Window window)
{
Log.Comment($"Set window {window.NativeWindowHandle} as the foreground window.");
NativeMethods.SetForegroundWindow(window.NativeWindowHandle);
}
}
}