Cosmos/source2/Debug/Cosmos.Debug.VSDebugEngine/Host/VMWare.cs
BlueSkeye_cp 7372c8a9bd Bochs integration : alpha version
Limitations :

- Bochs must be installed on the system. This is not checked as a  prerequisite by the Builder.
- You will find a GuessForBochs Cosmos project under BlueSkeye user project folder that can be used to launch the Guess project under Bochs.
- You may have to fix manually the path for the following properties in Cosmos.bxrc file copied to the CosmosForBochs\Bin\Debug folder
  * romimage
  * vgaromimage
- The Cosmos project UI is not yet Bochs aware. If you do not use the GuessForBochs project you must manually edit your Cosmos project file to modify the following property in both the Debug and Release property group from the project file :

    <Launch>Bochs</Launch>

  You must also add the following properties in both the Debug and Release property group from the project file :

    <BochsConfig>Cosmos.bxrc</BochsConfig>
    <Bochs_Deployment>ISO</Bochs_Deployment>
    <Bochs_Launch>Bochs</Bochs_Launch>
    <Bochs_DebugEnabled>True</Bochs_DebugEnabled>
    <Bochs_DebugMode>Source</Bochs_DebugMode>
    <Bochs_IgnoreDebugStubAttribute />
    <Bochs_VMwareEdition>Player</Bochs_VMwareEdition>
    <Bochs_OutputPath>bin\Debug\</Bochs_OutputPath>
    <Bochs_Framework>MicrosoftNET</Bochs_Framework>
    <Bochs_UseInternalAssembler>False</Bochs_UseInternalAssembler>
    <Bochs_TraceAssemblies />
    <Bochs_EnableGDB>False</Bochs_EnableGDB>
    <Bochs_StartCosmosGDB>false</Bochs_StartCosmosGDB>
    <Bochs_Name>GuessForBochs</Bochs_Name>
    <Bochs_Description>Use Bochs emulator to deploy and debug.</Bochs_Description>
    <Bochs_VisualStudioDebugPort>Pipe: Cosmos\Serial</Bochs_VisualStudioDebugPort>
    <Bochs_PxeInterface>192.168.43.1</Bochs_PxeInterface>
    <Bochs_SlavePort>Serial: COM3</Bochs_SlavePort>
    <Bochs_ShowLaunchConsole>False</Bochs_ShowLaunchConsole>
2012-09-14 17:13:06 +00:00

197 lines
7.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using Vestris.VMWareLib;
using Cosmos.Build.Common;
using Cosmos.Debug.Common;
namespace Cosmos.Debug.VSDebugEngine.Host {
public class VMware : Base {
protected VMwareEdition mEdition;
protected string mDir;
protected string mVmxPath;
protected Process mProcess;
protected string mWorkstationPath;
protected string mPlayerPath;
public VMware(NameValueCollection aParams, bool aUseGDB) : base(aParams, aUseGDB) {
mDir = Path.Combine(CosmosPaths.Build, @"VMWare\Workstation\");
mVmxPath = Path.Combine(mDir, @"Debug.vmx");
mWorkstationPath = GetPathname("VMware Workstation", "vmware.exe");
mPlayerPath = GetPathname("VMware Player", "vmplayer.exe");
if (mWorkstationPath == null && mPlayerPath == null) {
throw new Exception("VMware not found.");
}
string xFlavor = aParams[BuildProperties.VMwareEditionString].ToUpper();
mEdition = VMwareEdition.Player;
if (xFlavor == "WORKSTATION") {
mEdition = VMwareEdition.Workstation;
}
// Try alternate if selected one is not installed
if (mEdition == VMwareEdition.Player && mPlayerPath == null) {
mEdition = VMwareEdition.Workstation;
} else if (mEdition == VMwareEdition.Workstation && mWorkstationPath == null) {
mEdition = VMwareEdition.Player;
}
}
protected void ConnectToVMWare(VMWareVirtualHost aHost) {
if (mEdition == VMwareEdition.Player) {
aHost.ConnectToVMWareWorkstation();
} else {
aHost.ConnectToVMWarePlayer();
}
}
protected string GetPathname(string aKey, string aEXE) {
using (var xRegKey = Registry.LocalMachine.OpenSubKey(@"Software\VMware, Inc.\" + aKey, false)) {
if (xRegKey != null) {
string xResult = Path.Combine(((string)xRegKey.GetValue("InstallPath")), aEXE);
if (File.Exists(xResult)) {
return xResult;
}
}
return null;
}
}
public override void Start() {
Cleanup();
CreateDebugVmx();
// Target exe or file
mProcess = new Process();
var xPSI = mProcess.StartInfo;
if (mEdition == VMwareEdition.Player) {
xPSI.FileName = mPlayerPath;
} else {
xPSI.FileName = mWorkstationPath;
}
var xArgSB = new StringBuilder();
string xVmxPath = "\"" + mVmxPath + "\"";
if (mEdition == VMwareEdition.Player) {
xPSI.Arguments = xVmxPath;
} else {
// -x: Auto power on VM. Must be small x, big X means something else.
// -q: Close VMWare when VM is powered off.
// Options must come beore the vmx, and cannot use shellexecute
xPSI.Arguments = "-x -q " + xVmxPath;
}
xPSI.RedirectStandardError = false;
xPSI.RedirectStandardOutput = false;
xPSI.UseShellExecute = false;
mProcess.EnableRaisingEvents = true;
mProcess.Exited += delegate(Object aSender, EventArgs e) {
if (OnShutDown != null) {
OnShutDown(aSender, e);
}
};
mProcess.Start();
}
public override void Stop() {
using (var xHost = new VMWareVirtualHost()) {
ConnectToVMWare(xHost);
using (var xMachine = xHost.Open(mVmxPath)) {
xMachine.PowerOff();
}
xHost.Close();
}
Cleanup();
}
protected void DeleteFiles(string aPath, string aPattern) {
var xFiles = Directory.GetFiles(aPath, aPattern);
foreach (var xFile in xFiles) {
File.Delete(xFile);
}
}
protected void Cleanup() {
try {
string xPath = Path.GetDirectoryName(mVmxPath);
// Delete old Debug.vmx and other files that might be left over from previous run.
// Especially important with newer versions of VMWare player which defaults to suspend
// when the close button is used.
File.Delete(mVmxPath);
File.Delete(Path.ChangeExtension(mVmxPath, ".nvram"));
// Delete the auto snapshots that latest vmware players create as default.
// It creates them with suffixes though, so we need to wild card find them.
DeleteFiles(xPath, "*.vmxf");
DeleteFiles(xPath, "*.vmss");
DeleteFiles(xPath, "*.vmsd");
DeleteFiles(xPath, "*.vmem");
// Delete log files so that logged data is only from last boot
File.Delete(Path.Combine(xPath, "vmware.log"));
File.Delete(Path.Combine(xPath, "vmware-0.log"));
File.Delete(Path.Combine(xPath, "vmware-1.log"));
File.Delete(Path.Combine(xPath, "vmware-2.log"));
} catch (Exception) {
// Ignore errors, users can stop VS while VMware is still running and files will be locked.
}
}
protected void CreateDebugVmx() {
// VMWare doesn't like to boot a read only VMX.
// We also need to make changes based on project / debug settings.
// Finally we do not want to create VCS checkins based on local user changes.
// Because of this we use Cosmos.vmx as a template and output a Debug.vmx on every run.
using (var xSrc = new StreamReader(Path.Combine(mDir, "Cosmos.vmx"))) {
try {
// Write out Debug.vmx
using (var xDest = new StreamWriter(mVmxPath)) {
string xLine;
while ((xLine = xSrc.ReadLine()) != null) {
var xParts = xLine.Split('=');
if (xParts.Length == 2) {
string xName = xParts[0].Trim();
string xValue = xParts[1].Trim();
if ((xName == "uuid.location") || (xName == "uuid.bios")) {
// We delete uuid entries so VMWare doesnt ask the user "Did you move or copy" the file
xValue = null;
} else if (xName == "ide1:0.fileName") {
// Set the ISO file for booting
xValue = "\"" + mParams["ISOFile"] + "\"";
} else if (xName == "nvram") {
// Point it to an initially non-existent nvram.
// This has the effect of disabling PXE so the boot is faster.
xValue = "\"Debug.nvram\"";
}
if (xValue != null) {
xDest.WriteLine(xName + " = " + xValue);
}
}
}
if (mUseGDB) {
xDest.WriteLine();
xDest.WriteLine("debugStub.listen.guest32 = \"TRUE\"");
xDest.WriteLine("debugStub.hideBreakpoints = \"TRUE\"");
xDest.WriteLine("monitor.debugOnStartGuest32 = \"TRUE\"");
xDest.WriteLine("debugStub.listen.guest32.remote = \"TRUE\"");
}
}
} catch (IOException ex) {
if (ex.Message.Contains(Path.GetFileName(mDir))) {
throw new Exception("The VMware image " + mDir + " is still in use. Please exit current Vmware session with Cosmos and try again.", ex);
}
throw ex;
}
}
}
}
}