aboutsummaryrefslogtreecommitdiff
path: root/src/TestExe
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-03-08 16:06:01 -0600
committerSean Hall <r.sean.hall@gmail.com>2021-03-08 16:11:57 -0600
commit99d7440134d0f33683d1150a770a2bc594be41de (patch)
tree9a38c1df21c0022516bdfeca0d30f235acd3b46a /src/TestExe
parent23e3978430ec3ae4f1ea808af0b590b71b2fec9a (diff)
downloadwix-99d7440134d0f33683d1150a770a2bc594be41de.tar.gz
wix-99d7440134d0f33683d1150a770a2bc594be41de.tar.bz2
wix-99d7440134d0f33683d1150a770a2bc594be41de.zip
Port dependency tests from old repo.
Diffstat (limited to 'src/TestExe')
-rw-r--r--src/TestExe/Program.cs74
-rw-r--r--src/TestExe/Task.cs471
-rw-r--r--src/TestExe/TestExe.csproj17
-rw-r--r--src/TestExe/app.config10
4 files changed, 572 insertions, 0 deletions
diff --git a/src/TestExe/Program.cs b/src/TestExe/Program.cs
new file mode 100644
index 00000000..e92c413b
--- /dev/null
+++ b/src/TestExe/Program.cs
@@ -0,0 +1,74 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3using System;
4using System.Collections.Generic;
5using System.Linq;
6using System.Text;
7
8namespace TestExe
9{
10 class Program
11 {
12 static List<Task> tasks;
13 static int exitCodeToReturn = 0;
14
15 static int Main(string[] args)
16 {
17 Usage();
18 tasks = TaskParser.ParseTasks(args);
19
20 foreach (Task t in tasks)
21 {
22 // special case for the ExitCodeTask
23 if (t.GetType() == typeof(ExitCodeTask))
24 {
25 exitCodeToReturn = int.Parse(t.data);
26 }
27 else
28 {
29 t.RunTask();
30 }
31 }
32
33 Console.WriteLine("Exiting with ExitCode = {0}", exitCodeToReturn);
34 return exitCodeToReturn;
35 }
36
37 static void Usage()
38 {
39 Console.WriteLine(@"TestExe.exe");
40 Console.WriteLine(@"");
41 Console.WriteLine(@"TestExe can be passed various switches to define how it will behave and what tasks it will perform.");
42 Console.WriteLine(@"All switches are optional.");
43 Console.WriteLine(@"Any # of switches can be combined in any order.");
44 Console.WriteLine(@"Switches can be specified multiple times.");
45 Console.WriteLine(@"The order of the switches listed is the order they will be processed.");
46 Console.WriteLine(@"Info is written to stdout to describe what tasks are being performed as they are executed.");
47 Console.WriteLine(@"");
48 Console.WriteLine(@"Usage: TestExe.exe [tasks...]");
49 Console.WriteLine(@"");
50 Console.WriteLine(@"");
51 Console.WriteLine(@"/ec # Exit code to return. Can only be specified once. If not specified, 0 will be returned. Example: “/ec 3010” would return 3010");
52 Console.WriteLine(@"/s # Milliseconds to sleep before continuing. Example: “/s 5000” would sleep 5 seconds.");
53 Console.WriteLine(@"/sr #-# Random range of Milliseconds to sleep before continuing. Example: “/sr 5000-10000” would sleep between 5-10 seconds.");
54 Console.WriteLine(@"/log filename Create a log file called filename. Contents of the log are static text. Example: “/log %temp%\test.log” would create a %temp%\test.log file.");
55 Console.WriteLine(@"/Pinfo filename Create an xml file containing information about the process: PID, start time, user running the process, etc.");
56 Console.WriteLine(@"/fe filename Wait for a file to exist before continuing. Example: “/fe %temp%\cache\file.msi” would wait until %temp%\cache\file.msi exists.");
57 Console.WriteLine(@"/regw regkey,name,type,value (Re)writes a registry key with the specified value");
58 Console.WriteLine(@"/regd regkey,[name] Deletes registry key name or key and all of its children (subkeys and values)");
59 Console.WriteLine(@"");
60 Console.WriteLine(@"Example: ");
61 Console.WriteLine(@"");
62 Console.WriteLine(@"TestExe.exe /ec 1603 /Pinfo %temp%\Pinfo1.xml /s 1000 /log %temp%\log1.log /sr 5000-10000 /log %temp%\log2.log");
63 Console.WriteLine(@"");
64 Console.WriteLine(@"This would result in the following execution:");
65 Console.WriteLine(@" - Create an xml file with the current process info in it.");
66 Console.WriteLine(@" - Sleep 1 seconds");
67 Console.WriteLine(@" - Create log1.log");
68 Console.WriteLine(@" - Sleep between 5-10 seconds");
69 Console.WriteLine(@" - Create log2.log");
70 Console.WriteLine(@" - Exit with 1603");
71 Console.WriteLine(@"");
72 }
73 }
74}
diff --git a/src/TestExe/Task.cs b/src/TestExe/Task.cs
new file mode 100644
index 00000000..577acbea
--- /dev/null
+++ b/src/TestExe/Task.cs
@@ -0,0 +1,471 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3using System;
4using System.Collections.Generic;
5using System.Diagnostics;
6using System.IO;
7using System.Linq;
8using System.Management;
9using System.Text;
10using Microsoft.Win32;
11
12namespace TestExe
13{
14 public abstract class Task
15 {
16 public string data;
17
18 public Task(string Data)
19 {
20 data = Data;
21 }
22
23 public abstract void RunTask();
24
25 }
26
27 public class ExitCodeTask : Task
28 {
29 public ExitCodeTask(string Data) : base(Data) { }
30
31 public override void RunTask()
32 {
33 // this task does nothing. Just stores data about what exit code to return.
34 }
35 }
36
37 public class SleepTask : Task
38 {
39 public SleepTask(string Data) : base(Data) { }
40
41 public override void RunTask()
42 {
43 int milliseconds = int.Parse(this.data);
44 Console.WriteLine("Starting to sleep for {0} milliseconds", milliseconds);
45 System.Threading.Thread.Sleep(milliseconds);
46 }
47 }
48
49 public class SleepRandomTask : Task
50 {
51 public SleepRandomTask(string Data) : base(Data) { }
52
53 public override void RunTask()
54 {
55 int low = int.Parse(data.Split(new string[] { ":" }, 2, StringSplitOptions.None)[0]);
56 int high = int.Parse(data.Split(new string[] { ":" }, 2, StringSplitOptions.None)[1]);
57
58 Random r = new Random();
59 int milliseconds = r.Next(high - low) + low;
60 Console.WriteLine("Starting to sleep for {0} milliseconds", milliseconds);
61 System.Threading.Thread.Sleep(milliseconds);
62 }
63 }
64
65 public class LogTask : Task
66 {
67 string[] argsUsed;
68 public LogTask(string Data, string[] args)
69 : base(Data)
70 {
71 argsUsed = args;
72 }
73
74 public override void RunTask()
75 {
76 string logFile = "";
77 string argsUsedString = "";
78
79 foreach (string a in argsUsed)
80 {
81 argsUsedString += a + " ";
82 }
83
84 try
85 {
86 logFile = System.Environment.ExpandEnvironmentVariables(data);
87 Console.WriteLine("creating log file: " + logFile);
88 StreamWriter textFile = File.CreateText(logFile);
89 textFile.WriteLine("This is a log file created by TestExe.exe");
90 textFile.WriteLine("Args used: " + argsUsedString);
91 textFile.Close();
92 }
93 catch
94 {
95 Console.WriteLine("creating a log file failed for: {0}", logFile);
96 }
97
98 }
99 }
100
101 public class ProcessInfoTask : Task
102 {
103 public ProcessInfoTask(string Data) : base(Data) { }
104
105 public override void RunTask()
106 {
107 try
108 {
109 string processInfoXml = "";
110
111 // Get information about the process and who is running it
112 Process thisProc = Process.GetCurrentProcess();
113 string username = thisProc.StartInfo.EnvironmentVariables["username"].ToString();
114
115 int parentProcId = GetParentProcess(thisProc.Id);
116 Process parentProc = Process.GetProcessById(parentProcId);
117 string parentUsername = parentProc.StartInfo.EnvironmentVariables["username"].ToString();
118
119 int grandparentProcId = GetParentProcess(parentProc.Id);
120 Process grandparentProc = Process.GetProcessById(grandparentProcId);
121 string grandparentUsername = grandparentProc.StartInfo.EnvironmentVariables["username"].ToString();
122
123 processInfoXml += "<ProcessInfo>";
124 processInfoXml += " <ProcessName>" + thisProc.ProcessName + "</ProcessName>";
125 processInfoXml += " <Id>" + thisProc.Id.ToString() + "</Id>";
126 processInfoXml += " <SessionId>" + thisProc.SessionId.ToString() + "</SessionId>";
127 processInfoXml += " <MachineName>" + thisProc.MachineName + "</MachineName>";
128 // this stuff isn't set since we didn't start the process and tell it what to use. So don't bother
129 //processInfoXml += " <StartInfo>";
130 //processInfoXml += " <FileName>" + thisProc.StartInfo.FileName + "</FileName>";
131 //processInfoXml += " <UserName>" + thisProc.StartInfo.UserName + "</UserName>";
132 //processInfoXml += " <WorkingDirectory>" + thisProc.StartInfo.WorkingDirectory + "</WorkingDirectory>";
133 //processInfoXml += " <Arguments>" + thisProc.StartInfo.Arguments + "</Arguments>";
134 //processInfoXml += " </StartInfo>";
135 processInfoXml += " <StartTime>" + thisProc.StartTime.ToString() + "</StartTime>";
136 processInfoXml += " <Username>" + username + "</Username>";
137 processInfoXml += " <ParentProcess>";
138 processInfoXml += " <ProcessName>" + parentProc.ProcessName + "</ProcessName>";
139 processInfoXml += " <Id>" + parentProc.Id.ToString() + "</Id>";
140 processInfoXml += " <StartTime>" + parentProc.StartTime.ToString() + "</StartTime>";
141 processInfoXml += " <Username>" + parentUsername + "</Username>";
142 processInfoXml += " </ParentProcess>";
143 processInfoXml += " <GrandparentProcess>";
144 processInfoXml += " <ProcessName>" + grandparentProc.ProcessName + "</ProcessName>";
145 processInfoXml += " <Id>" + grandparentProc.Id.ToString() + "</Id>";
146 processInfoXml += " <StartTime>" + grandparentProc.StartTime.ToString() + "</StartTime>";
147 processInfoXml += " <Username>" + grandparentUsername + "</Username>";
148 processInfoXml += " </GrandparentProcess>";
149 processInfoXml += "</ProcessInfo>";
150
151 string logFile = System.Environment.ExpandEnvironmentVariables(data);
152 Console.WriteLine("Creating Process Info data file: " + logFile);
153 StreamWriter textFile = File.CreateText(logFile);
154 textFile.WriteLine(processInfoXml);
155 textFile.Close();
156 }
157 catch (Exception eX)
158 {
159 Console.WriteLine("Creating Process Info data file failed");
160 Console.WriteLine(eX.Message);
161 }
162
163
164 }
165
166 private static int GetParentProcess(int Id)
167 {
168 int parentPid = 0;
169 using (ManagementObject mo = new ManagementObject("win32_process.handle='" + Id.ToString() + "'"))
170 {
171 mo.Get();
172 parentPid = Convert.ToInt32(mo["ParentProcessId"]);
173 }
174 return parentPid;
175 }
176 }
177
178 public class FileExistsTask : Task
179 {
180 public FileExistsTask(string Data) : base(Data) { }
181
182 public override void RunTask()
183 {
184 string fileToExist = System.Environment.ExpandEnvironmentVariables(data);
185
186 if (!String.IsNullOrEmpty(fileToExist))
187 {
188 Console.WriteLine("Waiting for this file to exist: \"" + fileToExist + "\"");
189 while (!System.IO.File.Exists(fileToExist))
190 {
191 System.Threading.Thread.Sleep(250);
192 }
193 Console.WriteLine("Found: \"" + fileToExist + "\"");
194 }
195
196 }
197 }
198
199 /// <summary>
200 /// Task class that will create a registry key and write a name and value in it
201 /// </summary>
202 public class RegistryWriterTask : Task
203 {
204 private string hive;
205 private string keyPath;
206 private string[] keyPathArray;
207 private string name;
208 private RegistryValueKind regValueKind;
209 private object value;
210
211 public RegistryWriterTask(string Data) : base(Data) { }
212
213 public override void RunTask()
214 {
215 if (parseRegKeyNameTypeValue(System.Environment.ExpandEnvironmentVariables(data)))
216 {
217 RegistryKey rk = Registry.LocalMachine;
218
219 if (hive == "HKCU") rk = Microsoft.Win32.Registry.CurrentUser;
220 if (hive == "HKCC") rk = Microsoft.Win32.Registry.CurrentConfig;
221 if (hive == "HKLM") rk = Microsoft.Win32.Registry.LocalMachine;
222
223 foreach (string key in keyPathArray)
224 {
225 rk = rk.CreateSubKey(key, RegistryKeyPermissionCheck.ReadWriteSubTree);
226 }
227
228 rk.SetValue(name, value, regValueKind);
229 Console.WriteLine("Created registry key: '{0}' name: '{1}' value: '{2}' of type: '{3}'",
230 hive + "\\" + keyPath,
231 name,
232 value.ToString(),
233 regValueKind.ToString());
234 }
235 else
236 {
237 Console.WriteLine("Unable to write registry key.");
238 }
239
240 }
241
242 private bool parseRegKeyNameTypeValue(string delimittedData)
243 {
244 string[] splitString = delimittedData.Split(new string[] { "," }, StringSplitOptions.None);
245 if (splitString.Length != 4)
246 {
247 Console.WriteLine("Invalid regkey. Unable to parse key,name,type,value from: \"" + delimittedData + "\"");
248 return false;
249 }
250 else
251 {
252 keyPath = splitString[0];
253 name = splitString[1];
254 string datatype = splitString[2];
255 if (datatype == "DWord")
256 {
257 value = UInt32.Parse(splitString[3]);
258 }
259 else if (datatype == "QWord")
260 {
261 value = UInt64.Parse(splitString[3]);
262 }
263 else
264 {
265 value = splitString[3];
266 }
267
268 if (keyPath.ToUpper().StartsWith("HKLM\\"))
269 {
270 hive = "HKLM";
271 keyPath = keyPath.Replace("HKLM\\", "");
272 }
273 else if (keyPath.ToUpper().StartsWith("HKCC\\"))
274 {
275 hive = "HKCC";
276 keyPath = keyPath.Replace("HKCC\\", "");
277 }
278 else if (keyPath.ToUpper().StartsWith("HKCU\\"))
279 {
280 hive = "HKCU";
281 keyPath = keyPath.Replace("HKCU\\", "");
282 }
283 else
284 {
285 Console.WriteLine("Invalid regkey. Unable to determin hive. regkey must start with either: [HKLM], [HKCU], or [HKCC]");
286 return false;
287 }
288 keyPathArray = keyPath.Split(new string[] { "\\" }, StringSplitOptions.None);
289
290 try
291 {
292 regValueKind = (RegistryValueKind)System.Enum.Parse(typeof(RegistryValueKind), datatype);
293 }
294 catch (Exception ex)
295 {
296 Console.WriteLine("Invalid datatype. It must be: String, DWord, or QWord (case sensitive)");
297 Console.WriteLine(ex.Message);
298 return false;
299 }
300 }
301 return true;
302 }
303 }
304
305 /// <summary>
306 /// Task class that will delete a registry key value or registry key and all of its children
307 /// </summary>
308 public class RegistryDeleterTask : Task
309 {
310 private string hive;
311 private string keyPath;
312 private string[] keyPathArray;
313 private string name;
314
315 public RegistryDeleterTask(string Data) : base(Data) { }
316
317 public override void RunTask()
318 {
319 if (parseRegKeyName(System.Environment.ExpandEnvironmentVariables(data)))
320 {
321 try
322 {
323 RegistryKey rk = Registry.LocalMachine;
324
325 if (hive == "HKCU") rk = Microsoft.Win32.Registry.CurrentUser;
326 if (hive == "HKCC") rk = Microsoft.Win32.Registry.CurrentConfig;
327 if (hive == "HKLM") rk = Microsoft.Win32.Registry.LocalMachine;
328
329 RegistryKey rkParent = null;
330 foreach (string key in keyPathArray)
331 {
332 rkParent = rk;
333 rk = rk.OpenSubKey(key, true);
334 }
335
336 if (String.IsNullOrEmpty(name))
337 {
338 // delete the key and all of its children
339 string subkeyToDelete = keyPathArray[keyPathArray.Length - 1];
340 rkParent.DeleteSubKeyTree(subkeyToDelete);
341 Console.WriteLine("Deleted registry key: '{0}'", hive + "\\" + keyPath);
342 }
343 else
344 {
345 // just delete this value
346 rk.DeleteValue(name);
347 Console.WriteLine("Deleted registry key: '{0}' name: '{1}'", hive + "\\" + keyPath, name);
348 }
349 }
350 catch (Exception ex)
351 {
352 Console.WriteLine("Unable to delete registry key: '{0}'", hive + "\\" + keyPath);
353 Console.WriteLine(ex.Message);
354 }
355 }
356 else
357 {
358 Console.WriteLine("Unable to delete registry key.");
359 }
360
361 }
362
363 private bool parseRegKeyName(string delimittedData)
364 {
365 string[] splitString = delimittedData.Split(new string[] { "," }, StringSplitOptions.None);
366
367 if (splitString.Length > 2)
368 {
369 Console.WriteLine("Unable to parse registry key and name.");
370 return false;
371 }
372
373 keyPath = splitString[0];
374 if (splitString.Length == 2)
375 {
376 name = splitString[1];
377 }
378
379 if (keyPath.ToUpper().StartsWith("HKLM\\"))
380 {
381 hive = "HKLM";
382 keyPath = keyPath.Replace("HKLM\\", "");
383 }
384 else if (keyPath.ToUpper().StartsWith("HKCC\\"))
385 {
386 hive = "HKCC";
387 keyPath = keyPath.Replace("HKCC\\", "");
388 }
389 else if (keyPath.ToUpper().StartsWith("HKCU\\"))
390 {
391 hive = "HKCU";
392 keyPath = keyPath.Replace("HKCU\\", "");
393 }
394 else
395 {
396 Console.WriteLine("Invalid regkey. Unable to determine hive. regkey must start with either: [HKLM], [HKCU], or [HKCC]");
397 return false;
398 }
399 keyPathArray = keyPath.Split(new string[] { "\\" }, StringSplitOptions.None);
400 return true;
401 }
402 }
403
404 public class TaskParser
405 {
406
407 public static List<Task> ParseTasks(string[] args)
408 {
409 List<Task> tasks = new List<Task>();
410
411 try
412 {
413 // for invalid args. return empty list
414 if (args.Length % 2 == 0)
415 {
416 Task t;
417
418 for (int i = 0; i < args.Length; i += 2)
419 {
420 switch (args[i].ToLower())
421 {
422 case "/ec":
423 t = new ExitCodeTask(args[i + 1]);
424 tasks.Add(t);
425 break;
426 case "/s":
427 t = new SleepTask(args[i + 1]);
428 tasks.Add(t);
429 break;
430 case "/sr":
431 t = new SleepRandomTask(args[i + 1]);
432 tasks.Add(t);
433 break;
434 case "/log":
435 t = new LogTask(args[i + 1], args);
436 tasks.Add(t);
437 break;
438 case "/pinfo":
439 t = new ProcessInfoTask(args[i + 1]);
440 tasks.Add(t);
441 break;
442 case "/fe":
443 t = new FileExistsTask(args[i + 1]);
444 tasks.Add(t);
445 break;
446 case "/regw":
447 t = new RegistryWriterTask(args[i + 1]);
448 tasks.Add(t);
449 break;
450 case "/regd":
451 t = new RegistryDeleterTask(args[i + 1]);
452 tasks.Add(t);
453 break;
454
455 default:
456 Console.WriteLine("Error: Invalid switch specified.");
457 return new List<Task>();
458 }
459 }
460 }
461 }
462 catch
463 {
464 Console.WriteLine("Error: Invalid switch data specified. Couldn't parse the data.");
465 return new List<Task>();
466 }
467
468 return tasks;
469 }
470 }
471}
diff --git a/src/TestExe/TestExe.csproj b/src/TestExe/TestExe.csproj
new file mode 100644
index 00000000..933fa932
--- /dev/null
+++ b/src/TestExe/TestExe.csproj
@@ -0,0 +1,17 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFrameworks>net35</TargetFrameworks>
7 <AssemblyName>TestExe</AssemblyName>
8 <RootNamespace>TestExe</RootNamespace>
9 <OutputType>Exe</OutputType>
10 <DebugType>embedded</DebugType>
11 <RuntimeIdentifier>win-x86</RuntimeIdentifier>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <Reference Include="System.Management" />
16 </ItemGroup>
17</Project> \ No newline at end of file
diff --git a/src/TestExe/app.config b/src/TestExe/app.config
new file mode 100644
index 00000000..f9811b74
--- /dev/null
+++ b/src/TestExe/app.config
@@ -0,0 +1,10 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4
5<configuration>
6 <startup>
7 <supportedRuntime version="v4.0" />
8 <supportedRuntime version="v2.0.50727" />
9 </startup>
10</configuration>