/scripts/vbox/QtSilentInstall/Program.cs

https://gitlab.com/frank-van-westerop/rapcad · C# · 299 lines · 264 code · 35 blank · 0 comment · 47 complexity · 3388e7c8d2c31cee9edc4d4b620508d9 MD5 · raw file

  1. using System;
  2. using System.Diagnostics;
  3. using Accessibility;
  4. using System.Runtime.InteropServices;
  5. using System.Collections.Generic;
  6. using System.Threading;
  7. using System.Windows.Forms;
  8. namespace QtSilentInstall
  9. {
  10. internal class Accessible
  11. {
  12. IAccessible mElement;
  13. int mID;
  14. Accessible(IAccessible a, int i)
  15. {
  16. mElement = a;
  17. mID = i;
  18. }
  19. [DllImport("oleacc.dll")]
  20. internal static extern int AccessibleObjectFromWindow(
  21. IntPtr hwnd,
  22. uint id,
  23. ref Guid iid,
  24. [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject);
  25. [DllImport("oleacc.dll")]
  26. public static extern uint AccessibleChildren(
  27. IAccessible paccContainer,
  28. int iChildStart,
  29. int cChildren,
  30. [Out] object[] rgvarChildren,
  31. out int pcObtained);
  32. public static Accessible fromWindow(IntPtr hWnd)
  33. {
  34. const int OBJID_WINDOW = 0x00000000;
  35. Guid guid = new Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}");
  36. object obj = null;
  37. AccessibleObjectFromWindow(hWnd, OBJID_WINDOW, ref guid, ref obj);
  38. IAccessible acc = obj as IAccessible;
  39. if (acc != null)
  40. return new Accessible(acc, OBJID_WINDOW);
  41. return null;
  42. }
  43. public bool hasChildren
  44. {
  45. get
  46. {
  47. if (mID != 0) return false;
  48. return mElement.accChildCount > 0;
  49. }
  50. }
  51. public ICollection<Accessible> Children
  52. {
  53. get
  54. {
  55. List<Accessible> list = new List<Accessible>();
  56. int count = mElement.accChildCount;
  57. object[] children = new object[count];
  58. int j;
  59. AccessibleChildren(mElement, 0, count, children, out j);
  60. foreach (object o in children)
  61. {
  62. Accessible a = ElementFromObject(o);
  63. if (a != null)
  64. list.Add(a);
  65. }
  66. return list;
  67. }
  68. }
  69. public Accessible ElementFromObject(object o)
  70. {
  71. if (o is int)
  72. return new Accessible(mElement, (int)o);
  73. IAccessible acc = o as IAccessible;
  74. if (acc != null)
  75. return new Accessible(acc, 0);
  76. return null;
  77. }
  78. public string Name
  79. {
  80. get
  81. {
  82. try
  83. {
  84. return mElement.get_accName(mID);
  85. }
  86. catch
  87. {
  88. return string.Empty;
  89. }
  90. }
  91. }
  92. public void DoAction()
  93. {
  94. mElement.accDoDefaultAction(mID);
  95. }
  96. public AccessibleRole Role
  97. {
  98. get
  99. {
  100. return (AccessibleRole)mElement.get_accRole(mID);
  101. }
  102. }
  103. public bool Invisible
  104. {
  105. get
  106. {
  107. return (State & (int)AccessibleStates.Invisible) != 0;
  108. }
  109. }
  110. public int State
  111. {
  112. get
  113. {
  114. return (int)mElement.get_accState(mID);
  115. }
  116. }
  117. public bool Checked
  118. {
  119. get
  120. {
  121. return (State & (int)AccessibleStates.Checked) != 0;
  122. }
  123. }
  124. public Accessible Find(Predicate<Accessible> match)
  125. {
  126. return Descend(this.Children, match);
  127. }
  128. private static Accessible Descend(ICollection<Accessible> c, Predicate<Accessible> match)
  129. {
  130. foreach (Accessible a in c)
  131. {
  132. if (match(a))
  133. return a;
  134. if (a.hasChildren)
  135. {
  136. Accessible r = Descend(a.Children, match);
  137. if (r != null)
  138. return r;
  139. }
  140. }
  141. return null;
  142. }
  143. }
  144. internal class Name
  145. {
  146. private static string mName;
  147. public static Predicate<Accessible> StartsWith(string name)
  148. {
  149. mName = name;
  150. return new Predicate<Accessible>(IsMatch);
  151. }
  152. static bool IsMatch(Accessible a)
  153. {
  154. if (a == null || a.Name == null)
  155. return false;
  156. if (a.Invisible == false)
  157. return a.Name.StartsWith(mName);
  158. return false;
  159. }
  160. }
  161. internal class LicenseRadio
  162. {
  163. public static Predicate<Accessible> Match
  164. {
  165. get
  166. {
  167. return new Predicate<Accessible>(IsMatch);
  168. }
  169. }
  170. static bool IsMatch(Accessible a)
  171. {
  172. if (a == null)
  173. return false;
  174. if (a.Name == null && a.Role == AccessibleRole.RadioButton && a.Checked == false)
  175. return true;
  176. return false;
  177. }
  178. }
  179. internal class LaunchCheckBox
  180. {
  181. public static Predicate<Accessible> Match
  182. {
  183. get
  184. {
  185. return new Predicate<Accessible>(IsMatch);
  186. }
  187. }
  188. static bool IsMatch(Accessible a)
  189. {
  190. if (a == null)
  191. return false;
  192. if (a.Name == "Launch Qt Creator" && a.Role == AccessibleRole.CheckButton && a.Checked == true)
  193. return true;
  194. return false;
  195. }
  196. }
  197. internal class Program
  198. {
  199. public delegate bool EnumWindowsProc(IntPtr hwnd, int lParam);
  200. [DllImport("user32.dll")]
  201. [return: MarshalAs(UnmanagedType.Bool)]
  202. static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
  203. [DllImport("user32.dll", SetLastError = true)]
  204. static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
  205. static IntPtr gHWND;
  206. static bool FindWindow(IntPtr hwnd, int lParam)
  207. {
  208. uint lpdwProcessId;
  209. GetWindowThreadProcessId(hwnd, out lpdwProcessId);
  210. if (lpdwProcessId == lParam)
  211. {
  212. gHWND = hwnd;
  213. return false;
  214. }
  215. return true;
  216. }
  217. static EnumWindowsProc ptr;
  218. static Accessible WaitFor(Process p, Predicate<Accessible> match)
  219. {
  220. return WaitFor(p, match, 100);
  221. }
  222. static Accessible WaitFor(Process p, Predicate<Accessible> match, int pause)
  223. {
  224. Accessible a;
  225. do
  226. {
  227. Thread.Sleep(pause);
  228. ptr = new EnumWindowsProc(FindWindow);
  229. EnumWindows(ptr, new IntPtr(p.Id));
  230. a = Accessible.fromWindow(gHWND);
  231. } while (a == null);
  232. Accessible b;
  233. do
  234. {
  235. Thread.Sleep(pause);
  236. b = a.Find(match);
  237. } while (b == null);
  238. return b;
  239. }
  240. static int Main(string[] args)
  241. {
  242. if (args.Length != 1)
  243. return 1639;
  244. if (args[0] == null)
  245. return 160;
  246. Process p = Process.Start(args[0]);
  247. WaitFor(p, Name.StartsWith("Next")).DoAction();
  248. WaitFor(p, Name.StartsWith("Skip")).DoAction();
  249. WaitFor(p, Name.StartsWith("Next")).DoAction();
  250. WaitFor(p, Name.StartsWith("Next")).DoAction();
  251. WaitFor(p, Name.StartsWith("Next")).DoAction();
  252. WaitFor(p, LicenseRadio.Match).DoAction();
  253. WaitFor(p, Name.StartsWith("Next")).DoAction();
  254. WaitFor(p, Name.StartsWith("Next")).DoAction();
  255. WaitFor(p, Name.StartsWith("Install")).DoAction();
  256. WaitFor(p, Name.StartsWith("Finish"), 5000);
  257. WaitFor(p, LaunchCheckBox.Match).DoAction();
  258. WaitFor(p, Name.StartsWith("Finish")).DoAction();
  259. p.WaitForExit();
  260. Console.WriteLine("Success!");
  261. return p.ExitCode;
  262. }
  263. }
  264. }