PageRenderTime 27ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/UIAVerify/UIATestLibrary/UIAutomation/Core/Library.cs

#
C# | 299 lines | 170 code | 50 blank | 79 comment | 29 complexity | b68c86985512754d7f33a2124bad30f1 MD5 | raw file
  1. // (c) Copyright Microsoft Corporation.
  2. // This source is subject to the Microsoft Permissive License.
  3. // See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  4. // All other rights reserved.
  5. using Microsoft.Test.UIAutomation.Core;
  6. //using Microsoft.Test.UIAutomation.Logging;
  7. // ------------------------------------------------------------------
  8. using System;
  9. using System.Globalization;
  10. using System.Runtime.InteropServices;
  11. using System.Windows.Automation;
  12. using System.Collections;
  13. using System.IO;
  14. using System.Reflection;
  15. using System.Xml;
  16. using System.CodeDom;
  17. using System.Text;
  18. using System.Resources;
  19. using System.Diagnostics;
  20. using System.Threading;
  21. using MS.Win32;
  22. // This suppresses warnings #'s not recognized by the compiler.
  23. #pragma warning disable 1634, 1691
  24. namespace Microsoft.Test.UIAutomation.Core
  25. {
  26. using InternalHelper.Enumerations;
  27. using InternalHelper.Tests;
  28. using Microsoft.Test.UIAutomation;
  29. using Microsoft.Test.UIAutomation.TestManager;
  30. using UIVerifyLogger = Microsoft.Test.UIAutomation.Logging.UIVerifyLogger;
  31. /// -----------------------------------------------------------------------
  32. /// <summary></summary>
  33. /// -----------------------------------------------------------------------
  34. public class Library
  35. {
  36. /// -------------------------------------------------------------------
  37. /// <summary>
  38. /// Time to wait for events to happen
  39. /// </summary>
  40. /// -------------------------------------------------------------------
  41. internal const int MAXTIME = 60000;
  42. /// -------------------------------------------------------------------
  43. /// <summary>
  44. /// Default waiting is 1/10th second between calls
  45. /// </summary>
  46. /// -------------------------------------------------------------------
  47. internal const int TIMEWAIT = 100;
  48. /// -------------------------------------------------------------------
  49. /// <summary>
  50. /// Helps out with formating of the output
  51. /// </summary>
  52. /// -------------------------------------------------------------------
  53. const string PREBUFFER = " ";
  54. /// -------------------------------------------------------------------
  55. /// <summary>
  56. /// Enumerations to define which ProxyTable to load
  57. /// </summary>
  58. /// -------------------------------------------------------------------
  59. public enum ProxyTable
  60. {
  61. /// ---------------------------------------------------------------
  62. /// <summary>Standard proxies that are shipped with WUI</summary>
  63. /// ---------------------------------------------------------------
  64. Default,
  65. /// ---------------------------------------------------------------
  66. /// <summary>Default fallback proxy</summary>
  67. /// ---------------------------------------------------------------
  68. Msaa,
  69. /// ---------------------------------------------------------------
  70. /// <summary>Standard Win32 and WinForms proxies</summary>
  71. /// ---------------------------------------------------------------
  72. Win32WinForms
  73. }
  74. /// -------------------------------------------------------------------
  75. /// <summary>Start application with ShellExecute with default timeout</summary>
  76. /// -------------------------------------------------------------------
  77. static public void StartApplicationShellExecute(string appPath, string caption, string arguments, out AutomationElement element)
  78. {
  79. StartApplicationShellExecute(appPath, caption, arguments, out element, MAXTIME);
  80. }
  81. /// -------------------------------------------------------------------
  82. /// <summary>Start application with ShellExecute</summary>
  83. /// -------------------------------------------------------------------
  84. static public void StartApplicationShellExecute(string appPath, string caption, string arguments, out AutomationElement element, int timeOutMilliSeconds)
  85. {
  86. Trace.WriteLine("Calling ShellExecute (" + appPath + ")");
  87. IntPtr hInstance = UnsafeNativeMethods.ShellExecute(IntPtr.Zero, null, appPath, arguments, null, 1 /*SW_SHOWNORMAL */);
  88. // hINstance really doesn't do you anything except tell you that it has failed if <= 32
  89. if (hInstance.ToInt64() <= 32)
  90. {
  91. Trace.WriteLine("Error stating application: " + hInstance);
  92. throw new Exception("UnsafeNativeMethods.ShellExecute() returned " + hInstance);
  93. }
  94. IntPtr hwnd = IntPtr.Zero;
  95. DateTime end = DateTime.Now + TimeSpan.FromMilliseconds(timeOutMilliSeconds);
  96. // Need to hunt for the window when you use ShellExecute unfortunately, but this is required
  97. // call for security reasons. StartProcess is not allowed.
  98. element = null;
  99. end = DateTime.Now + TimeSpan.FromMilliseconds(timeOutMilliSeconds);
  100. while (null == element)
  101. {
  102. if (DateTime.Now > end)
  103. throw new TimeoutException("Could not find " + appPath + " in " + timeOutMilliSeconds / 1000 + " seconds - Current time(" + DateTime.Now.Hour.ToString("00") + ":" + DateTime.Now.Minute.ToString("00") + ":" + DateTime.Now.Second.ToString("00") + ":" + DateTime.Now.Millisecond.ToString("00") + ")");
  104. Thread.Sleep(TIMEWAIT);
  105. element = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, caption));
  106. }
  107. }
  108. /// -------------------------------------------------------------------------
  109. /// <summary>
  110. /// Start the application and retrieve it's AutomationElement as a member variable.
  111. /// </summary>
  112. /// -------------------------------------------------------------------------
  113. static public void StartApplication(string appPath, string arguments, out IntPtr handle, out AutomationElement element, out Process process)
  114. {
  115. Library.ValidateArgumentNonNull(appPath, "appPath");
  116. element = null;
  117. appPath = appPath.ToUpper();
  118. ProcessStartInfo psi = new ProcessStartInfo();
  119. process = new Process();
  120. psi.FileName = appPath;
  121. if (arguments != null)
  122. {
  123. psi.Arguments = arguments;
  124. }
  125. UIVerifyLogger.LogComment("{0}Starting({1})", PREBUFFER, appPath);
  126. process.StartInfo = psi;
  127. #pragma warning suppress 6506 // We create a new one so don't need to validate it
  128. process.Start();
  129. UIVerifyLogger.MonitorProcess(process);
  130. UIVerifyLogger.LogComment("{0}Waiting for max of {1} seconds for application to start", PREBUFFER, MAXTIME / 1000);
  131. DateTime finishTime = DateTime.Now + TimeSpan.FromMilliseconds(MAXTIME);
  132. while (process.MainWindowHandle.Equals(IntPtr.Zero))
  133. {
  134. if (DateTime.Now > finishTime)
  135. throw new Exception("Could not find " + appPath + " in " + MAXTIME + " milliseconds");
  136. Thread.Sleep(TIMEWAIT);
  137. process.Refresh();
  138. }
  139. // Special case code for these to test applications that are really console windows that start
  140. // up another test application. Don't take the console window, but the test application that
  141. // it shells.
  142. string title = string.Empty;
  143. if (appPath.IndexOf("WIN32PATTERNTARGET.EXE") != -1)
  144. title = "Win32 Pattern Target";
  145. if (title == string.Empty & appPath.IndexOf("WIN32TREETARGET.EXE") != -1)
  146. title = "Win32 Tree Test";
  147. // If it is special case, then find the window by title
  148. if (title != string.Empty)
  149. {
  150. finishTime = DateTime.Now + TimeSpan.FromMilliseconds(MAXTIME);
  151. handle = IntPtr.Zero;
  152. while (handle == IntPtr.Zero)
  153. {
  154. if (DateTime.Now > finishTime)
  155. throw new ArgumentException("Could not find the " + title + " window in " + MAXTIME + " milliseconds");
  156. Thread.Sleep(TIMEWAIT);
  157. handle = SafeNativeMethods.FindWindow(null, title);
  158. }
  159. element = AutomationElement.FromHandle(handle);
  160. }
  161. else // assume normal application window
  162. {
  163. handle = process.MainWindowHandle;
  164. }
  165. UIVerifyLogger.LogComment("{0}{1} started", PREBUFFER, appPath);
  166. element = AutomationElement.FromHandle(handle);
  167. UIVerifyLogger.LogComment("{0}Obtained an AutomationElement for {1}", PREBUFFER, appPath);
  168. }
  169. // -------------------------------------------------------------------
  170. // Closes Process
  171. // -------------------------------------------------------------------
  172. static public void StopApplication(Process process, string processName, int sleepTime)
  173. {
  174. UIVerifyLogger.LogComment("{0}Closing {1}", PREBUFFER, processName);
  175. if (process == null)
  176. throw new NullReferenceException();
  177. try
  178. {
  179. process.Kill();
  180. UIVerifyLogger.LogComment("{0}{1} has been terminated", PREBUFFER, processName);
  181. }
  182. catch (InvalidOperationException)
  183. {
  184. UIVerifyLogger.LogComment("{0}{1} has already been terminated", PREBUFFER, processName);
  185. }
  186. }
  187. /// -------------------------------------------------------------------
  188. /// <summary>
  189. /// Returns a string that resembles output of UISpy tree
  190. /// </summary>
  191. /// -------------------------------------------------------------------
  192. static public string GetUISpyLook(AutomationElement le)
  193. {
  194. if (le == null)
  195. return "AutomationElement == null";
  196. string buffer = "";
  197. // Wrap calls since in the ExceptionNotFound tests, calling the properties throws an exception
  198. try
  199. {
  200. buffer += "\"" + le.Current.ControlType.ProgrammaticName.Replace("ControlType.", "") + "\" ";
  201. }
  202. catch (ElementNotAvailableException)
  203. {
  204. // For the ElementNotAvailableException tests, this might justifiably get thrown.
  205. buffer += "\"ElementNotAvailable\"";
  206. }
  207. try
  208. {
  209. buffer += "\"" + le.Current.Name + "\" ";
  210. }
  211. catch (ElementNotAvailableException)
  212. {
  213. // For the ElementNotAvailableException tests, this might justifiably get thrown.
  214. // Do something so that OARC does not complain
  215. buffer += "\"ElementNotAvailable\"";
  216. }
  217. try
  218. {
  219. buffer += "\"" + le.Current.AutomationId + "\" ";
  220. }
  221. catch (ElementNotAvailableException)
  222. {
  223. // For the ElementNotAvailableException tests, this might justifiably get thrown.
  224. // Do something so that OARC does not complain
  225. buffer += "\"ElementNotAvailable\"";
  226. }
  227. return buffer;
  228. }
  229. /// -------------------------------------------------------------------
  230. /// Check that specified argument is non-null, if so, throw exception
  231. /// -------------------------------------------------------------------
  232. static public void ValidateArgumentNonNull(object obj, string argName)
  233. {
  234. if (obj == null)
  235. {
  236. throw new ArgumentNullException(argName + "== null");
  237. }
  238. }
  239. /// -------------------------------------------------------------------
  240. /// <summary>
  241. /// Checks for critical nonrecoverable errors
  242. /// </summary>
  243. /// -------------------------------------------------------------------
  244. static public bool IsCriticalException(Exception exception)
  245. {
  246. return exception is SEHException || exception is NullReferenceException || exception is StackOverflowException || exception is OutOfMemoryException || exception is System.Threading.ThreadAbortException;
  247. }
  248. }
  249. }