summaryrefslogtreecommitdiff
path: root/src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs')
-rw-r--r--src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs b/src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs
new file mode 100644
index 00000000..35e53de6
--- /dev/null
+++ b/src/internal/WixBuildTools.TestSupport/MsbuildRunner.cs
@@ -0,0 +1,168 @@
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
3namespace WixBuildTools.TestSupport
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8
9 public class MsbuildRunner : ExternalExecutable
10 {
11 private static readonly string VswhereFindArguments = "-property installationPath";
12 private static readonly string Msbuild15RelativePath = @"MSBuild\15.0\Bin\MSBuild.exe";
13 private static readonly string Msbuild15RelativePath64 = @"MSBuild\15.0\Bin\amd64\MSBuild.exe";
14 private static readonly string MsbuildCurrentRelativePath = @"MSBuild\Current\Bin\MSBuild.exe";
15 private static readonly string MsbuildCurrentRelativePath64 = @"MSBuild\Current\Bin\amd64\MSBuild.exe";
16
17 private static readonly object InitLock = new object();
18
19 private static bool Initialized;
20 private static MsbuildRunner Msbuild15Runner;
21 private static MsbuildRunner Msbuild15Runner64;
22 private static MsbuildRunner MsbuildCurrentRunner;
23 private static MsbuildRunner MsbuildCurrentRunner64;
24
25 public static MsbuildRunnerResult Execute(string projectPath, string[] arguments = null, bool x64 = false) =>
26 InitAndExecute(String.Empty, projectPath, arguments, x64);
27
28 public static MsbuildRunnerResult ExecuteWithMsbuild15(string projectPath, string[] arguments = null, bool x64 = false) =>
29 InitAndExecute("15", projectPath, arguments, x64);
30
31 public static MsbuildRunnerResult ExecuteWithMsbuildCurrent(string projectPath, string[] arguments = null, bool x64 = false) =>
32 InitAndExecute("Current", projectPath, arguments, x64);
33
34 private static MsbuildRunnerResult InitAndExecute(string msbuildVersion, string projectPath, string[] arguments, bool x64)
35 {
36 lock (InitLock)
37 {
38 if (!Initialized)
39 {
40 Initialized = true;
41 var vswhereResult = VswhereRunner.Execute(VswhereFindArguments, true);
42 if (vswhereResult.ExitCode != 0)
43 {
44 throw new InvalidOperationException($"Failed to execute vswhere.exe, exit code: {vswhereResult.ExitCode}. Output:\r\n{String.Join("\r\n", vswhereResult.StandardOutput)}");
45 }
46
47 string msbuild15Path = null;
48 string msbuild15Path64 = null;
49 string msbuildCurrentPath = null;
50 string msbuildCurrentPath64 = null;
51
52 foreach (var installPath in vswhereResult.StandardOutput)
53 {
54 if (msbuildCurrentPath == null)
55 {
56 var path = Path.Combine(installPath, MsbuildCurrentRelativePath);
57 if (File.Exists(path))
58 {
59 msbuildCurrentPath = path;
60 }
61 }
62
63 if (msbuildCurrentPath64 == null)
64 {
65 var path = Path.Combine(installPath, MsbuildCurrentRelativePath64);
66 if (File.Exists(path))
67 {
68 msbuildCurrentPath64 = path;
69 }
70 }
71
72 if (msbuild15Path == null)
73 {
74 var path = Path.Combine(installPath, Msbuild15RelativePath);
75 if (File.Exists(path))
76 {
77 msbuild15Path = path;
78 }
79 }
80
81 if (msbuild15Path64 == null)
82 {
83 var path = Path.Combine(installPath, Msbuild15RelativePath64);
84 if (File.Exists(path))
85 {
86 msbuild15Path64 = path;
87 }
88 }
89 }
90
91 if (msbuildCurrentPath != null)
92 {
93 MsbuildCurrentRunner = new MsbuildRunner(msbuildCurrentPath);
94 }
95
96 if (msbuildCurrentPath64 != null)
97 {
98 MsbuildCurrentRunner64 = new MsbuildRunner(msbuildCurrentPath64);
99 }
100
101 if (msbuild15Path != null)
102 {
103 Msbuild15Runner = new MsbuildRunner(msbuild15Path);
104 }
105
106 if (msbuild15Path64 != null)
107 {
108 Msbuild15Runner64 = new MsbuildRunner(msbuild15Path64);
109 }
110 }
111 }
112
113 MsbuildRunner runner;
114 switch (msbuildVersion)
115 {
116 case "15":
117 {
118 runner = x64 ? Msbuild15Runner64 : Msbuild15Runner;
119 break;
120 }
121 case "Current":
122 {
123 runner = x64 ? MsbuildCurrentRunner64 : MsbuildCurrentRunner;
124 break;
125 }
126 default:
127 {
128 runner = x64 ? MsbuildCurrentRunner64 ?? Msbuild15Runner64
129 : MsbuildCurrentRunner ?? Msbuild15Runner;
130 break;
131 }
132 }
133
134 if (runner == null)
135 {
136 throw new InvalidOperationException($"Failed to find an installed{(x64 ? " 64-bit" : String.Empty)} MSBuild{msbuildVersion}");
137 }
138
139 return runner.ExecuteCore(projectPath, arguments);
140 }
141
142 private MsbuildRunner(string exePath) : base(exePath) { }
143
144 private MsbuildRunnerResult ExecuteCore(string projectPath, string[] arguments)
145 {
146 var total = new List<string>
147 {
148 projectPath,
149 };
150
151 if (arguments != null)
152 {
153 total.AddRange(arguments);
154 }
155
156 var args = CombineArguments(total);
157 var mergeErrorIntoOutput = true;
158 var workingFolder = Path.GetDirectoryName(projectPath);
159 var result = this.Run(args, mergeErrorIntoOutput, workingFolder);
160
161 return new MsbuildRunnerResult
162 {
163 ExitCode = result.ExitCode,
164 Output = result.StandardOutput,
165 };
166 }
167 }
168}