Skip to content

Commit 4e68f2b

Browse files
committed
VMware host upgrade
1 parent 4385190 commit 4e68f2b

1 file changed

Lines changed: 104 additions & 39 deletions

File tree

source/Cosmos.Debug.Hosts/VMware.cs

Lines changed: 104 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,48 @@
77

88
//using Vestris.VMWareLib;
99
using Cosmos.Build.Common;
10+
using System.Linq;
1011

11-
namespace Cosmos.Debug.Hosts {
12-
public class VMware : Host {
12+
namespace Cosmos.Debug.Hosts
13+
{
14+
public class VMware : Host
15+
{
1316
protected VMwareEdition mEdition;
1417
protected string mDir;
1518
protected string mVmxPath;
1619
protected Process mProcess;
20+
protected Process[] mProcessesBefore, mProcessesAfter, mProcesses;
1721
protected string mWorkstationPath;
1822
protected string mPlayerPath;
1923
protected string mHarddisk;
2024

21-
public VMware(Dictionary<string, string> aParams, bool aUseGDB,string harddisk = "Filesystem.vmdk") : base(aParams, aUseGDB) {
25+
public VMware(Dictionary<string, string> aParams, bool aUseGDB, string harddisk = "Filesystem.vmdk") : base(aParams, aUseGDB)
26+
{
2227
mHarddisk = harddisk;
2328
mDir = Path.Combine(CosmosPaths.Build, @"VMWare\Workstation\");
2429
mVmxPath = Path.Combine(mDir, @"Debug.vmx");
2530

2631
mWorkstationPath = GetPathname("VMware Workstation", "vmware.exe");
2732
mPlayerPath = GetPathname("VMware Player", "vmplayer.exe");
28-
if (mWorkstationPath == null && mPlayerPath == null) {
33+
if (mWorkstationPath == null && mPlayerPath == null)
34+
{
2935
throw new Exception("VMware not found.");
3036
}
3137

3238
string xFlavor = aParams[BuildPropertyNames.VMwareEditionString].ToUpper();
3339
mEdition = VMwareEdition.Player;
34-
if (xFlavor == "WORKSTATION") {
40+
if (xFlavor == "WORKSTATION")
41+
{
3542
mEdition = VMwareEdition.Workstation;
3643
}
3744

3845
// Try alternate if selected one is not installed
39-
if (mEdition == VMwareEdition.Player && mPlayerPath == null && mWorkstationPath != null) {
46+
if (mEdition == VMwareEdition.Player && mPlayerPath == null && mWorkstationPath != null)
47+
{
4048
mEdition = VMwareEdition.Workstation;
41-
} else if (mEdition == VMwareEdition.Workstation && mWorkstationPath == null) {
49+
}
50+
else if (mEdition == VMwareEdition.Workstation && mWorkstationPath == null)
51+
{
4252
mEdition = VMwareEdition.Player;
4353
}
4454
}
@@ -51,36 +61,47 @@ public VMware(Dictionary<string, string> aParams, bool aUseGDB,string harddisk =
5161
// }
5262
//}
5363

54-
protected string GetPathname(string aKey, string aEXE) {
55-
using (var xRegKey = Registry.LocalMachine.OpenSubKey(@"Software\WOW6432Node\VMware, Inc.\" + aKey, false)) {
56-
if (xRegKey != null) {
64+
protected string GetPathname(string aKey, string aEXE)
65+
{
66+
using (var xRegKey = Registry.LocalMachine.OpenSubKey(@"Software\WOW6432Node\VMware, Inc.\" + aKey, false))
67+
{
68+
if (xRegKey != null)
69+
{
5770
string xResult = Path.Combine(((string)xRegKey.GetValue("InstallPath")), aEXE);
58-
if (File.Exists(xResult)) {
71+
if (File.Exists(xResult))
72+
{
5973
return xResult;
6074
}
6175
}
6276
return null;
6377
}
6478
}
6579

66-
public override void Start() {
80+
public override void Start()
81+
{
6782
Cleanup();
6883
CreateDebugVmx();
6984

7085
// Target exe or file
7186
mProcess = new Process();
7287
var xPSI = mProcess.StartInfo;
73-
if (mEdition == VMwareEdition.Player) {
88+
if (mEdition == VMwareEdition.Player)
89+
{
7490
xPSI.FileName = mPlayerPath;
75-
} else {
91+
}
92+
else
93+
{
7694
xPSI.FileName = mWorkstationPath;
7795
}
7896
var xArgSB = new StringBuilder();
7997

8098
string xVmxPath = "\"" + mVmxPath + "\"";
81-
if (mEdition == VMwareEdition.Player) {
99+
if (mEdition == VMwareEdition.Player)
100+
{
82101
xPSI.Arguments = xVmxPath;
83-
} else {
102+
}
103+
else
104+
{
84105
// -x: Auto power on VM. Must be small x, big X means something else.
85106
// -q: Close VMWare when VM is powered off.
86107
// Options must come beore the vmx, and cannot use shellexecute
@@ -89,7 +110,27 @@ public override void Start() {
89110
xPSI.UseShellExecute = false; //must be true to allow elevate the process, sometimes needed if vmware only runs with admin rights
90111
mProcess.EnableRaisingEvents = true;
91112
mProcess.Exited += ExitCallback;
113+
114+
mProcessesBefore = Process.GetProcessesByName("vmware-vmx");
92115
mProcess.Start();
116+
117+
Stopwatch watch = Stopwatch.StartNew();
118+
119+
// Wait for the process to spawn
120+
mProcessesAfter = Process.GetProcessesByName("vmware-vmx");
121+
while (mProcessesAfter.Length == mProcessesBefore.Length)
122+
{
123+
if (watch.Elapsed.Seconds == 15)
124+
{
125+
watch.Stop();
126+
throw new TimeoutException("VMware Workstation took too long to launch!");
127+
}
128+
129+
mProcessesAfter = Process.GetProcessesByName("vmware-vmx");
130+
}
131+
132+
// Get the new processes
133+
mProcesses = mProcessesBefore.Concat(mProcessesAfter).Distinct().ToArray();
93134
}
94135

95136
private void ExitCallback(object sender, EventArgs e)
@@ -106,18 +147,19 @@ private void ExitCallback(object sender, EventArgs e)
106147
}
107148
}
108149

109-
public override void Stop() {
150+
public override void Stop()
151+
{
110152
if (null != mProcess)
111153
{
112154
try
113155
{
114156
//TODO: Close VMWare properly
115157

116-
//Force Kill VMWare
158+
// Kill the VMware GUI
117159
mProcess.Kill();
118160

119-
//kil vmware-vmx.exe
120-
foreach (var process in Process.GetProcessesByName("vmware-vmx"))
161+
// Kill the actual VM instance
162+
foreach (var process in mProcesses)
121163
{
122164
process.Kill();
123165
}
@@ -129,15 +171,19 @@ public override void Stop() {
129171
Cleanup();
130172
}
131173

132-
protected void DeleteFiles(string aPath, string aPattern) {
174+
protected void DeleteFiles(string aPath, string aPattern)
175+
{
133176
var xFiles = Directory.GetFiles(aPath, aPattern);
134-
foreach (var xFile in xFiles) {
177+
foreach (var xFile in xFiles)
178+
{
135179
File.Delete(xFile);
136180
}
137181
}
138182

139-
protected void Cleanup() {
140-
try {
183+
protected void Cleanup()
184+
{
185+
try
186+
{
141187
string xPath = Path.GetDirectoryName(mVmxPath);
142188
// Delete old Debug.vmx and other files that might be left over from previous run.
143189
// Especially important with newer versions of VMWare player which defaults to suspend
@@ -155,59 +201,78 @@ protected void Cleanup() {
155201
File.Delete(Path.Combine(xPath, "vmware-0.log"));
156202
File.Delete(Path.Combine(xPath, "vmware-1.log"));
157203
File.Delete(Path.Combine(xPath, "vmware-2.log"));
158-
} catch (Exception) {
204+
}
205+
catch (Exception)
206+
{
159207
// Ignore errors, users can stop VS while VMware is still running and files will be locked.
160208
}
161209
}
162210

163-
protected void CreateDebugVmx() {
211+
protected void CreateDebugVmx()
212+
{
164213
// VMWare doesn't like to boot a read only VMX.
165214
// We also need to make changes based on project / debug settings.
166215
// Finally we do not want to create VCS checkins based on local user changes.
167216
// Because of this we use Cosmos.vmx as a template and output a Debug.vmx on every run.
168-
using (var xSrc = new StreamReader(File.Open(Path.Combine(mDir, "Cosmos.vmx"), FileMode.OpenOrCreate))) {
169-
try {
217+
using (var xSrc = new StreamReader(File.Open(Path.Combine(mDir, "Cosmos.vmx"), FileMode.OpenOrCreate)))
218+
{
219+
try
220+
{
170221
// Write out Debug.vmx
171-
using (var xDest = new StreamWriter(File.Open(mVmxPath, FileMode.Create))) {
222+
using (var xDest = new StreamWriter(File.Open(mVmxPath, FileMode.Create)))
223+
{
172224
string xLine;
173-
while ((xLine = xSrc.ReadLine()) != null) {
225+
while ((xLine = xSrc.ReadLine()) != null)
226+
{
174227
var xParts = xLine.Split('=');
175-
if (xParts.Length == 2) {
228+
if (xParts.Length == 2)
229+
{
176230
string xName = xParts[0].Trim();
177231
string xValue = xParts[1].Trim();
178232

179-
if ((xName == "uuid.location") || (xName == "uuid.bios")) {
233+
if ((xName == "uuid.location") || (xName == "uuid.bios"))
234+
{
180235
// We delete uuid entries so VMWare doesnt ask the user "Did you move or copy" the file
181236
xValue = null;
182237

183-
} else if (xName == "ide1:0.fileName")
238+
}
239+
else if (xName == "ide1:0.fileName")
184240
{
185241
// Set the ISO file for booting
186242
xValue = "\"" + mParams["ISOFile"] + "\"";
187-
} else if (xName == "ide0:0.fileName") {
243+
}
244+
else if (xName == "ide0:0.fileName")
245+
{
188246
xValue = "\"" + mHarddisk + "\"";
189-
} else if (xName == "nvram") {
247+
}
248+
else if (xName == "nvram")
249+
{
190250
// Point it to an initially non-existent nvram.
191251
// This has the effect of disabling PXE so the boot is faster.
192252
xValue = "\"Debug.nvram\"";
193253
}
194254

195-
if (xValue != null) {
255+
if (xValue != null)
256+
{
196257
xDest.WriteLine(xName + " = " + xValue);
197258
}
198259
}
199260
}
200261

201-
if (mUseGDB) {
262+
if (mUseGDB)
263+
{
202264
xDest.WriteLine();
203265
xDest.WriteLine("debugStub.listen.guest32 = \"TRUE\"");
204266
xDest.WriteLine("debugStub.hideBreakpoints = \"TRUE\"");
205267
xDest.WriteLine("monitor.debugOnStartGuest32 = \"TRUE\"");
206268
xDest.WriteLine("debugStub.listen.guest32.remote = \"TRUE\"");
207269
}
208270
}
209-
} catch (IOException ex) {
210-
if (ex.Message.Contains(Path.GetFileName(mDir))) {
271+
}
272+
catch (IOException ex)
273+
{
274+
if (ex.Message.Contains(Path.GetFileName(mDir)))
275+
{
211276
throw new Exception("The VMware image " + mDir + " is still in use. Please exit current Vmware session with Cosmos and try again.", ex);
212277
}
213278
throw;

0 commit comments

Comments
 (0)