in vsintegration/src/FSharp.ProjectSystem.Base/Project/ProjectConfig.cs [980:1091]
private VsDebugTargetInfo GetDebugTargetInfo(uint grfLaunch, bool forLaunch)
{
VsDebugTargetInfo info = new VsDebugTargetInfo();
info.cbSize = (uint)Marshal.SizeOf(info);
info.dlo = Microsoft.VisualStudio.Shell.Interop.DEBUG_LAUNCH_OPERATION.DLO_CreateProcess;
// On first call, reset the cache, following calls will use the cached values
string property = GetConfigurationProperty("StartAction", true);
// Set the debug target
if (0 == System.String.Compare("Program", property, StringComparison.OrdinalIgnoreCase))
{
string startProgram = StartProgram;
if (!string.IsNullOrEmpty(startProgram))
info.bstrExe = startProgram;
}
else
// property is either null or "Project"
// we're ignoring "URL" for now
{
string outputType = project.GetProjectProperty(ProjectFileConstants.OutputType, false);
if (forLaunch && 0 == string.Compare("library", outputType, StringComparison.OrdinalIgnoreCase))
throw new ClassLibraryCannotBeStartedDirectlyException();
info.bstrExe = this.project.GetOutputAssembly(this.configCanonicalName);
}
property = GetConfigurationProperty("RemoteDebugMachine", false);
if (property != null && property.Length > 0)
{
info.bstrRemoteMachine = property;
}
bool isRemoteDebug = (info.bstrRemoteMachine != null);
property = GetConfigurationProperty("StartWorkingDirectory", false);
if (string.IsNullOrEmpty(property))
{
// 3273: aligning with C#
info.bstrCurDir = Path.GetDirectoryName(this.project.GetOutputAssembly(this.configCanonicalName));
}
else
{
if (isRemoteDebug)
{
info.bstrCurDir = property;
}
else
{
string fullPath;
if (Path.IsPathRooted(property))
{
fullPath = property;
}
else
{
// use project folder as a base part when computing full path from given relative
var currentDir = Path.GetDirectoryName(this.project.GetOutputAssembly(this.configCanonicalName));
fullPath = Path.Combine(currentDir, property);
}
if (!Directory.Exists(fullPath))
throw new WorkingDirectoryNotExistsException(fullPath);
info.bstrCurDir = fullPath;
}
}
property = GetConfigurationProperty("StartArguments", false);
if (!string.IsNullOrEmpty(property))
{
info.bstrArg = property;
}
info.fSendStdoutToOutputWindow = 0;
property = GetConfigurationProperty("EnableUnmanagedDebugging", false);
if (property != null && string.Compare(property, "true", StringComparison.OrdinalIgnoreCase) == 0)
{
//Set the unmanged debugger
//TODO change to vsconstant when it is available in VsConstants. It should be guidCOMPlusNativeEng
info.clsidCustom = new Guid("{92EF0900-2251-11D2-B72E-0000F87572EF}");
}
else
{
//Set the managed debugger
info.clsidCustom = VSConstants.CLSID_ComPlusOnlyDebugEngine;
}
info.grfLaunch = grfLaunch;
bool isConsoleApp = string.Compare("exe",
project.GetProjectProperty(ProjectFileConstants.OutputType, false),
StringComparison.OrdinalIgnoreCase) == 0;
bool noDebug = ((uint)(((__VSDBGLAUNCHFLAGS)info.grfLaunch) & __VSDBGLAUNCHFLAGS.DBGLAUNCH_NoDebug)) != 0;
// Do not use cmd.exe to get "Press any key to continue." when remote debugging
if (isConsoleApp && noDebug && !isRemoteDebug)
{
// VSWhidbey 573404: escape the characters ^<>& so that they are passed to the application rather than interpreted by cmd.exe.
System.Text.StringBuilder newArg = new System.Text.StringBuilder(info.bstrArg);
newArg.Replace("^", "^^")
.Replace("<", "^<")
.Replace(">", "^>")
.Replace("&", "^&");
newArg.Insert(0, "\" ");
newArg.Insert(0, info.bstrExe);
newArg.Insert(0, "/c \"\"");
newArg.Append(" & pause\"");
string newExe = Path.Combine(Environment.SystemDirectory, "cmd.exe");
info.bstrArg = newArg.ToString();
info.bstrExe = newExe;
}
return info;
}