summaryrefslogtreecommitdiff
path: root/src/test/burn/TestExe
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-04-22 17:12:34 -0700
committerRob Mensching <rob@firegiant.com>2021-05-05 11:18:35 -0700
commitd8e47230e094a506406a83eb78916abf2668b29c (patch)
tree2213ee3ed1a19fd5cd19a5914a23b7f7a57318ff /src/test/burn/TestExe
parent2cbe83832cc76aa379b29665de5523e82c543acf (diff)
downloadwix-d8e47230e094a506406a83eb78916abf2668b29c.tar.gz
wix-d8e47230e094a506406a83eb78916abf2668b29c.tar.bz2
wix-d8e47230e094a506406a83eb78916abf2668b29c.zip
Move Integration into test
Diffstat (limited to 'src/test/burn/TestExe')
-rw-r--r--src/test/burn/TestExe/NetfxTask.cs295
-rw-r--r--src/test/burn/TestExe/Program.cs74
-rw-r--r--src/test/burn/TestExe/Task.cs209
-rw-r--r--src/test/burn/TestExe/TestExe.csproj20
-rw-r--r--src/test/burn/TestExe/TestExe_x64.csproj17
-rw-r--r--src/test/burn/TestExe/app.config10
6 files changed, 625 insertions, 0 deletions
diff --git a/src/test/burn/TestExe/NetfxTask.cs b/src/test/burn/TestExe/NetfxTask.cs
new file mode 100644
index 00000000..35b1ea95
--- /dev/null
+++ b/src/test/burn/TestExe/NetfxTask.cs
@@ -0,0 +1,295 @@
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
3#if NET35
4using System;
5using System.Collections.Generic;
6using System.Diagnostics;
7using System.IO;
8using System.Management;
9using Microsoft.Win32;
10
11namespace TestExe
12{
13 public class ProcessInfoTask : Task
14 {
15 public ProcessInfoTask(string Data) : base(Data) { }
16
17 public override void RunTask()
18 {
19 try
20 {
21 string processInfoXml = "";
22
23 // Get information about the process and who is running it
24 Process thisProc = Process.GetCurrentProcess();
25 string username = thisProc.StartInfo.EnvironmentVariables["username"].ToString();
26
27 int parentProcId = GetParentProcess(thisProc.Id);
28 Process parentProc = Process.GetProcessById(parentProcId);
29 string parentUsername = parentProc.StartInfo.EnvironmentVariables["username"].ToString();
30
31 int grandparentProcId = GetParentProcess(parentProc.Id);
32 Process grandparentProc = Process.GetProcessById(grandparentProcId);
33 string grandparentUsername = grandparentProc.StartInfo.EnvironmentVariables["username"].ToString();
34
35 processInfoXml += "<ProcessInfo>";
36 processInfoXml += " <ProcessName>" + thisProc.ProcessName + "</ProcessName>";
37 processInfoXml += " <Id>" + thisProc.Id.ToString() + "</Id>";
38 processInfoXml += " <SessionId>" + thisProc.SessionId.ToString() + "</SessionId>";
39 processInfoXml += " <MachineName>" + thisProc.MachineName + "</MachineName>";
40 // this stuff isn't set since we didn't start the process and tell it what to use. So don't bother
41 //processInfoXml += " <StartInfo>";
42 //processInfoXml += " <FileName>" + thisProc.StartInfo.FileName + "</FileName>";
43 //processInfoXml += " <UserName>" + thisProc.StartInfo.UserName + "</UserName>";
44 //processInfoXml += " <WorkingDirectory>" + thisProc.StartInfo.WorkingDirectory + "</WorkingDirectory>";
45 //processInfoXml += " <Arguments>" + thisProc.StartInfo.Arguments + "</Arguments>";
46 //processInfoXml += " </StartInfo>";
47 processInfoXml += " <StartTime>" + thisProc.StartTime.ToString() + "</StartTime>";
48 processInfoXml += " <Username>" + username + "</Username>";
49 processInfoXml += " <ParentProcess>";
50 processInfoXml += " <ProcessName>" + parentProc.ProcessName + "</ProcessName>";
51 processInfoXml += " <Id>" + parentProc.Id.ToString() + "</Id>";
52 processInfoXml += " <StartTime>" + parentProc.StartTime.ToString() + "</StartTime>";
53 processInfoXml += " <Username>" + parentUsername + "</Username>";
54 processInfoXml += " </ParentProcess>";
55 processInfoXml += " <GrandparentProcess>";
56 processInfoXml += " <ProcessName>" + grandparentProc.ProcessName + "</ProcessName>";
57 processInfoXml += " <Id>" + grandparentProc.Id.ToString() + "</Id>";
58 processInfoXml += " <StartTime>" + grandparentProc.StartTime.ToString() + "</StartTime>";
59 processInfoXml += " <Username>" + grandparentUsername + "</Username>";
60 processInfoXml += " </GrandparentProcess>";
61 processInfoXml += "</ProcessInfo>";
62
63 string logFile = System.Environment.ExpandEnvironmentVariables(this.data);
64 Console.WriteLine("Creating Process Info data file: " + logFile);
65 StreamWriter textFile = File.CreateText(logFile);
66 textFile.WriteLine(processInfoXml);
67 textFile.Close();
68 }
69 catch (Exception eX)
70 {
71 Console.WriteLine("Creating Process Info data file failed");
72 Console.WriteLine(eX.Message);
73 }
74
75
76 }
77
78 private static int GetParentProcess(int Id)
79 {
80 int parentPid = 0;
81 using (ManagementObject mo = new ManagementObject("win32_process.handle='" + Id.ToString() + "'"))
82 {
83 mo.Get();
84 parentPid = Convert.ToInt32(mo["ParentProcessId"]);
85 }
86 return parentPid;
87 }
88 }
89
90 /// <summary>
91 /// Task class that will create a registry key and write a name and value in it
92 /// </summary>
93 public class RegistryWriterTask : Task
94 {
95 private string hive;
96 private string keyPath;
97 private string[] keyPathArray;
98 private string name;
99 private RegistryValueKind regValueKind;
100 private object value;
101
102 public RegistryWriterTask(string Data) : base(Data) { }
103
104 public override void RunTask()
105 {
106 if (this.parseRegKeyNameTypeValue(System.Environment.ExpandEnvironmentVariables(this.data)))
107 {
108 RegistryKey rk = Registry.LocalMachine;
109
110 if (this.hive == "HKCU") { rk = Microsoft.Win32.Registry.CurrentUser; }
111 if (this.hive == "HKCC") { rk = Microsoft.Win32.Registry.CurrentConfig; }
112 if (this.hive == "HKLM") { rk = Microsoft.Win32.Registry.LocalMachine; }
113
114 foreach (string key in this.keyPathArray)
115 {
116 rk = rk.CreateSubKey(key, RegistryKeyPermissionCheck.ReadWriteSubTree);
117 }
118
119 rk.SetValue(this.name, this.value, this.regValueKind);
120 Console.WriteLine("Created registry key: '{0}' name: '{1}' value: '{2}' of type: '{3}'",
121 this.hive + "\\" + this.keyPath,
122 this.name,
123 this.value.ToString(),
124 this.regValueKind.ToString());
125 }
126 else
127 {
128 Console.WriteLine("Unable to write registry key.");
129 }
130
131 }
132
133 private bool parseRegKeyNameTypeValue(string delimittedData)
134 {
135 string[] splitString = delimittedData.Split(new string[] { "," }, StringSplitOptions.None);
136 if (splitString.Length != 4)
137 {
138 Console.WriteLine("Invalid regkey. Unable to parse key,name,type,value from: \"" + delimittedData + "\"");
139 return false;
140 }
141 else
142 {
143 this.keyPath = splitString[0];
144 this.name = splitString[1];
145 string datatype = splitString[2];
146 if (datatype == "DWord")
147 {
148 this.value = UInt32.Parse(splitString[3]);
149 }
150 else if (datatype == "QWord")
151 {
152 this.value = UInt64.Parse(splitString[3]);
153 }
154 else
155 {
156 this.value = splitString[3];
157 }
158
159 if (this.keyPath.ToUpper().StartsWith("HKLM\\"))
160 {
161 this.hive = "HKLM";
162 this.keyPath = this.keyPath.Replace("HKLM\\", "");
163 }
164 else if (this.keyPath.ToUpper().StartsWith("HKCC\\"))
165 {
166 this.hive = "HKCC";
167 this.keyPath = this.keyPath.Replace("HKCC\\", "");
168 }
169 else if (this.keyPath.ToUpper().StartsWith("HKCU\\"))
170 {
171 this.hive = "HKCU";
172 this.keyPath = this.keyPath.Replace("HKCU\\", "");
173 }
174 else
175 {
176 Console.WriteLine("Invalid regkey. Unable to determin hive. regkey must start with either: [HKLM], [HKCU], or [HKCC]");
177 return false;
178 }
179 this.keyPathArray = this.keyPath.Split(new string[] { "\\" }, StringSplitOptions.None);
180
181 try
182 {
183 this.regValueKind = (RegistryValueKind)System.Enum.Parse(typeof(RegistryValueKind), datatype);
184 }
185 catch (Exception ex)
186 {
187 Console.WriteLine("Invalid datatype. It must be: String, DWord, or QWord (case sensitive)");
188 Console.WriteLine(ex.Message);
189 return false;
190 }
191 }
192 return true;
193 }
194 }
195
196 /// <summary>
197 /// Task class that will delete a registry key value or registry key and all of its children
198 /// </summary>
199 public class RegistryDeleterTask : Task
200 {
201 private string hive;
202 private string keyPath;
203 private string[] keyPathArray;
204 private string name;
205
206 public RegistryDeleterTask(string Data) : base(Data) { }
207
208 public override void RunTask()
209 {
210 if (this.parseRegKeyName(System.Environment.ExpandEnvironmentVariables(this.data)))
211 {
212 try
213 {
214 RegistryKey rk = Registry.LocalMachine;
215
216 if (this.hive == "HKCU") { rk = Microsoft.Win32.Registry.CurrentUser; }
217 if (this.hive == "HKCC") { rk = Microsoft.Win32.Registry.CurrentConfig; }
218 if (this.hive == "HKLM") { rk = Microsoft.Win32.Registry.LocalMachine; }
219
220 RegistryKey rkParent = null;
221 foreach (string key in this.keyPathArray)
222 {
223 rkParent = rk;
224 rk = rk.OpenSubKey(key, true);
225 }
226
227 if (String.IsNullOrEmpty(this.name))
228 {
229 // delete the key and all of its children
230 string subkeyToDelete = this.keyPathArray[this.keyPathArray.Length - 1];
231 rkParent.DeleteSubKeyTree(subkeyToDelete);
232 Console.WriteLine("Deleted registry key: '{0}'", this.hive + "\\" + this.keyPath);
233 }
234 else
235 {
236 // just delete this value
237 rk.DeleteValue(this.name);
238 Console.WriteLine("Deleted registry key: '{0}' name: '{1}'", this.hive + "\\" + this.keyPath, this.name);
239 }
240 }
241 catch (Exception ex)
242 {
243 Console.WriteLine("Unable to delete registry key: '{0}'", this.hive + "\\" + this.keyPath);
244 Console.WriteLine(ex.Message);
245 }
246 }
247 else
248 {
249 Console.WriteLine("Unable to delete registry key.");
250 }
251
252 }
253
254 private bool parseRegKeyName(string delimittedData)
255 {
256 string[] splitString = delimittedData.Split(new string[] { "," }, StringSplitOptions.None);
257
258 if (splitString.Length > 2)
259 {
260 Console.WriteLine("Unable to parse registry key and name.");
261 return false;
262 }
263
264 this.keyPath = splitString[0];
265 if (splitString.Length == 2)
266 {
267 this.name = splitString[1];
268 }
269
270 if (this.keyPath.ToUpper().StartsWith("HKLM\\"))
271 {
272 this.hive = "HKLM";
273 this.keyPath = this.keyPath.Replace("HKLM\\", "");
274 }
275 else if (this.keyPath.ToUpper().StartsWith("HKCC\\"))
276 {
277 this.hive = "HKCC";
278 this.keyPath = this.keyPath.Replace("HKCC\\", "");
279 }
280 else if (this.keyPath.ToUpper().StartsWith("HKCU\\"))
281 {
282 this.hive = "HKCU";
283 this.keyPath = this.keyPath.Replace("HKCU\\", "");
284 }
285 else
286 {
287 Console.WriteLine("Invalid regkey. Unable to determine hive. regkey must start with either: [HKLM], [HKCU], or [HKCC]");
288 return false;
289 }
290 this.keyPathArray = this.keyPath.Split(new string[] { "\\" }, StringSplitOptions.None);
291 return true;
292 }
293 }
294}
295#endif
diff --git a/src/test/burn/TestExe/Program.cs b/src/test/burn/TestExe/Program.cs
new file mode 100644
index 00000000..e92c413b
--- /dev/null
+++ b/src/test/burn/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/test/burn/TestExe/Task.cs b/src/test/burn/TestExe/Task.cs
new file mode 100644
index 00000000..7d39bfd9
--- /dev/null
+++ b/src/test/burn/TestExe/Task.cs
@@ -0,0 +1,209 @@
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 Microsoft.Win32;
8
9namespace TestExe
10{
11 public abstract class Task
12 {
13 public string data;
14
15 public Task(string Data)
16 {
17 this.data = Data;
18 }
19
20 public abstract void RunTask();
21
22 }
23
24 public class ExitCodeTask : Task
25 {
26 public ExitCodeTask(string Data) : base(Data) { }
27
28 public override void RunTask()
29 {
30 // this task does nothing. Just stores data about what exit code to return.
31 }
32 }
33
34 public class SleepTask : Task
35 {
36 public SleepTask(string Data) : base(Data) { }
37
38 public override void RunTask()
39 {
40 int milliseconds = int.Parse(this.data);
41 Console.WriteLine("Starting to sleep for {0} milliseconds", milliseconds);
42 System.Threading.Thread.Sleep(milliseconds);
43 }
44 }
45
46 public class SleepRandomTask : Task
47 {
48 public SleepRandomTask(string Data) : base(Data) { }
49
50 public override void RunTask()
51 {
52 int low = int.Parse(this.data.Split(new string[] { ":" }, 2, StringSplitOptions.None)[0]);
53 int high = int.Parse(this.data.Split(new string[] { ":" }, 2, StringSplitOptions.None)[1]);
54
55 Random r = new Random();
56 int milliseconds = r.Next(high - low) + low;
57 Console.WriteLine("Starting to sleep for {0} milliseconds", milliseconds);
58 System.Threading.Thread.Sleep(milliseconds);
59 }
60 }
61
62 public class LargeFileTask : Task
63 {
64 public LargeFileTask(string Data) : base(Data) { }
65
66 public override void RunTask()
67 {
68 string[] tokens = this.data.Split(new char[] { '|' }, 2);
69 string filePath = System.Environment.ExpandEnvironmentVariables(tokens[0]);
70 long size = long.Parse(tokens[1]);
71 using (var stream = File.Create(filePath))
72 {
73 stream.Seek(size - 1, SeekOrigin.Begin);
74 stream.WriteByte(1);
75 }
76 }
77 }
78
79 public class LogTask : Task
80 {
81 string[] argsUsed;
82 public LogTask(string Data, string[] args)
83 : base(Data)
84 {
85 this.argsUsed = args;
86 }
87
88 public override void RunTask()
89 {
90 string logFile = "";
91 string argsUsedString = "";
92
93 foreach (string a in this.argsUsed)
94 {
95 argsUsedString += a + " ";
96 }
97
98 try
99 {
100 logFile = System.Environment.ExpandEnvironmentVariables(this.data);
101 Console.WriteLine("creating log file: " + logFile);
102 StreamWriter textFile = File.CreateText(logFile);
103 textFile.WriteLine("This is a log file created by TestExe.exe");
104 textFile.WriteLine("Args used: " + argsUsedString);
105 textFile.Close();
106 }
107 catch
108 {
109 Console.WriteLine("creating a log file failed for: {0}", logFile);
110 }
111
112 }
113 }
114
115 public class FileExistsTask : Task
116 {
117 public FileExistsTask(string Data) : base(Data) { }
118
119 public override void RunTask()
120 {
121 string fileToExist = System.Environment.ExpandEnvironmentVariables(this.data);
122
123 if (!String.IsNullOrEmpty(fileToExist))
124 {
125 Console.WriteLine("Waiting for this file to exist: \"" + fileToExist + "\"");
126 while (!System.IO.File.Exists(fileToExist))
127 {
128 System.Threading.Thread.Sleep(250);
129 }
130 Console.WriteLine("Found: \"" + fileToExist + "\"");
131 }
132
133 }
134 }
135
136 public class TaskParser
137 {
138
139 public static List<Task> ParseTasks(string[] args)
140 {
141 List<Task> tasks = new List<Task>();
142
143 try
144 {
145 // for invalid args. return empty list
146 if (args.Length % 2 == 0)
147 {
148 Task t;
149
150 for (int i = 0; i < args.Length; i += 2)
151 {
152 switch (args[i].ToLower())
153 {
154 case "/ec":
155 t = new ExitCodeTask(args[i + 1]);
156 tasks.Add(t);
157 break;
158 case "/s":
159 t = new SleepTask(args[i + 1]);
160 tasks.Add(t);
161 break;
162 case "/sr":
163 t = new SleepRandomTask(args[i + 1]);
164 tasks.Add(t);
165 break;
166 case "/lf":
167 t = new LargeFileTask(args[i + 1]);
168 tasks.Add(t);
169 break;
170 case "/log":
171 t = new LogTask(args[i + 1], args);
172 tasks.Add(t);
173 break;
174 case "/fe":
175 t = new FileExistsTask(args[i + 1]);
176 tasks.Add(t);
177 break;
178#if NET35
179 case "/pinfo":
180 t = new ProcessInfoTask(args[i + 1]);
181 tasks.Add(t);
182 break;
183 case "/regw":
184 t = new RegistryWriterTask(args[i + 1]);
185 tasks.Add(t);
186 break;
187 case "/regd":
188 t = new RegistryDeleterTask(args[i + 1]);
189 tasks.Add(t);
190 break;
191#endif
192
193 default:
194 Console.WriteLine("Error: Invalid switch specified.");
195 return new List<Task>();
196 }
197 }
198 }
199 }
200 catch
201 {
202 Console.WriteLine("Error: Invalid switch data specified. Couldn't parse the data.");
203 return new List<Task>();
204 }
205
206 return tasks;
207 }
208 }
209}
diff --git a/src/test/burn/TestExe/TestExe.csproj b/src/test/burn/TestExe/TestExe.csproj
new file mode 100644
index 00000000..5a130422
--- /dev/null
+++ b/src/test/burn/TestExe/TestExe.csproj
@@ -0,0 +1,20 @@
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;netcoreapp3.1</TargetFrameworks>
7 <AssemblyName>TestExe</AssemblyName>
8 <RootNamespace>TestExe</RootNamespace>
9 <OutputType>Exe</OutputType>
10 <DebugType>embedded</DebugType>
11 <RuntimeIdentifier>win-x86</RuntimeIdentifier>
12 <SelfContained>false</SelfContained>
13 <UseAppHost>true</UseAppHost>
14 <RollForward>Major</RollForward>
15 </PropertyGroup>
16
17 <ItemGroup Condition="'$(TargetFramework)'=='net35'">
18 <Reference Include="System.Management" />
19 </ItemGroup>
20</Project> \ No newline at end of file
diff --git a/src/test/burn/TestExe/TestExe_x64.csproj b/src/test/burn/TestExe/TestExe_x64.csproj
new file mode 100644
index 00000000..1dd2d8e6
--- /dev/null
+++ b/src/test/burn/TestExe/TestExe_x64.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-x64</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/test/burn/TestExe/app.config b/src/test/burn/TestExe/app.config
new file mode 100644
index 00000000..f9811b74
--- /dev/null
+++ b/src/test/burn/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>