#include <string>
#include <vector>
+#include <map>
// For `HRESULT` definition
#ifdef FEATURE_PAL
virtual HRESULT Initialize() = 0;
virtual HRESULT Attach(int pid) = 0;
- virtual HRESULT Launch(std::string fileExec, std::vector<std::string> execArgs, bool stopAtEntry = false) = 0;
+ virtual HRESULT Launch(const std::string &fileExec, const std::vector<std::string> &execArgs, const std::map<std::string, std::string> &env,
+ const std::string &cwd, bool stopAtEntry = false) = 0;
virtual HRESULT ConfigurationDone() = 0;
virtual HRESULT Disconnect(DisconnectAction action = DisconnectDefault) = 0;
// Distributed under the MIT License.
// See the LICENSE file in the project root for more information.
-#include "manageddebugger.h"
-
#include <sstream>
#include <mutex>
#include <memory>
#include <chrono>
#include <stdexcept>
+#include <vector>
+#include <map>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "manageddebugger.h"
#include "valueprint.h"
#include "symbolreader.h"
#include "logger.h"
using std::string;
+using std::vector;
+using std::map;
// From dbgshim.h
struct dbgshim_t
return RunIfReady();
}
-HRESULT ManagedDebugger::Launch(string fileExec, std::vector<string> execArgs, bool stopAtEntry)
+HRESULT ManagedDebugger::Launch(const string &fileExec, const vector<string> &execArgs, const map<string, string> &env, const string &cwd, bool stopAtEntry)
{
LogFuncEntry();
m_execPath = fileExec;
m_execArgs = execArgs;
m_stopAtEntry = stopAtEntry;
+ m_cwd = cwd;
+ m_env = env;
m_breakpoints.SetStopAtEntry(m_stopAtEntry);
return RunIfReady();
}
return s;
}
+static bool IsDirExists(const char* const path)
+{
+ struct stat info;
+
+ if (stat(path, &info) != 0)
+ return false;
+
+ if (!(info.st_mode & S_IFDIR))
+ return false;
+
+ return true;
+}
+
HRESULT ManagedDebugger::RunProcess(string fileExec, std::vector<string> execArgs)
{
static const auto startupCallbackWaitTimeout = std::chrono::milliseconds(5000);
HANDLE resumeHandle; // Fake thread handle for the process resume
+ vector<char> outEnv;
+ if (!m_env.empty()) {
+ // We need to append the environ values with keeping the current process environment block.
+ // It works equal for any platrorms in coreclr CreateProcessW(), but not critical for Linux.
+ map<string, string> envMap;
+ if (GetSystemEnvironmentAsMap(envMap) != -1) {
+ auto it = m_env.begin();
+ auto end = m_env.end();
+ // Override the system value (PATHs appending needs a complex implementation)
+ while (it != end) {
+ envMap[it->first] = it->second;
+ ++it;
+ }
+ for (const auto &pair : envMap) {
+ outEnv.insert(outEnv.end(), pair.first.begin(), pair.first.end());
+ outEnv.push_back('=');
+ outEnv.insert(outEnv.end(), pair.second.begin(), pair.second.end());
+ outEnv.push_back('\0');
+ }
+ outEnv.push_back('\0');
+ }
+ }
+
+ // cwd in launch.json set working directory for debugger https://code.visualstudio.com/docs/python/debugging#_cwd
+ if (!m_cwd.empty())
+ if (!IsDirExists(m_cwd.c_str()) || !SetWorkDir(m_cwd))
+ m_cwd.clear();
+
IfFailRet(g_dbgshim.CreateProcessForLaunch(reinterpret_cast<LPWSTR>(const_cast<WCHAR*>(to_utf16(ss.str()).c_str())),
/* Suspend process */ TRUE,
- /* Current environment */ NULL,
- /* Current working directory */ NULL,
+ outEnv.empty() ? NULL : &outEnv[0],
+ m_cwd.empty() ? NULL : reinterpret_cast<LPCWSTR>(to_utf16(m_cwd).c_str()),
&m_processId, &resumeHandle));
IfFailRet(g_dbgshim.RegisterForRuntimeStartup(m_processId, ManagedDebugger::StartupCallback, this, &m_unregisterToken));
#include <unordered_map>
#include <unordered_set>
#include <vector>
+#include <map>
#include <condition_variable>
#include <future>
} m_startMethod;
std::string m_execPath;
std::vector<std::string> m_execArgs;
+ std::string m_cwd;
+ std::map<std::string, std::string> m_env;
bool m_stopAtEntry;
bool m_isConfigurationDone;
HRESULT Initialize() override;
HRESULT Attach(int pid) override;
- HRESULT Launch(std::string fileExec, std::vector<std::string> execArgs, bool stopAtEntry = false) override;
+ HRESULT Launch(const std::string &fileExec, const std::vector<std::string> &execArgs, const std::map<std::string, std::string> &env,
+ const std::string &cwd, bool stopAtEntry = false) override;
HRESULT ConfigurationDone() override;
HRESULT Disconnect(DisconnectAction action = DisconnectDefault) override;
{ "exec-run", [this](const std::vector<std::string> &args, std::string &output) -> HRESULT {
HRESULT Status;
m_debugger->Initialize();
- IfFailRet(m_debugger->Launch(m_fileExec, m_execArgs, true));
+ IfFailRet(m_debugger->Launch(m_fileExec, m_execArgs, {}, "", true));
Status = m_debugger->ConfigurationDone();
if (SUCCEEDED(Status))
output = "^running";
#include <fstream>
#include <thread>
#include <algorithm>
+#include <map>
#ifdef FEATURE_PAL
#include <dirent.h>
#include <winsock2.h>
#endif
+using std::string;
+using std::map;
+
unsigned long OSPageSize()
{
static unsigned long pageSize = 0;
return true;
}
+char** GetSystemEnvironment()
+{
+ char** sysEnviron;
+
+#if __APPLE__
+ sysEnviron = *(_NSGetEnviron());
+#else // __APPLE__
+ extern char** environ;
+ sysEnviron = environ;
+#endif // __APPLE__
+
+ return sysEnviron;
+}
+
+int GetSystemEnvironmentAsMap(map<string, string>& outMap) {
+ char*const*const pEnv = GetSystemEnvironment();
+
+ if (pEnv == nullptr)
+ return -1;
+
+ int counter = 0;
+ while (pEnv[counter] != nullptr) {
+ const string env = pEnv[counter];
+ size_t pos = env.find_first_of("=");
+ if (pos != string::npos && pos != 0) {
+ outMap.emplace(env.substr(0, pos), env.substr(pos+1));
+ }
+ ++counter;
+ }
+
+ return 0;
+}
IORedirectServer::operator bool() const
{
// See the LICENSE file in the project root for more information.
#pragma once
-#include <string>
#include <iostream>
#include <functional>
+#include <string>
+#include <map>
#include <palclr.h>
std::string GetTempFolder();
std::string GetBasename(const std::string &path);
bool IsFullPath(const std::string &path);
+char** GetSystemEnvironment();
+int GetSystemEnvironmentAsMap(std::map<std::string, std::string> &out);
class IORedirectServerHandles;
// Distributed under the MIT License.
// See the LICENSE file in the project root for more information.
-#include "vscodeprotocol.h"
-
#include <iostream>
+#include <string>
+#include <vector>
#include <unordered_map>
+#include <map>
+
+#include <exception>
#include <winerror.h>
+#include "vscodeprotocol.h"
+
#include "torelease.h"
#include "cputil.h"
#include "logger.h"
using std::string;
using std::vector;
+using std::map;
using std::min;
// for convenience
return S_OK;
} },
- { "launch", [this](const json &arguments, json &body){
- if (!m_fileExec.empty())
- {
- return m_debugger->Launch(m_fileExec, m_execArgs, arguments.value("stopAtEntry", false));
+ {"launch", [this](const json &arguments, json &body) {
+ const string cwd = arguments.at("cwd").get<string>();
+ map<string, string> env;
+ try {
+ env = arguments.at("env").get<map<string, string> >();
+ }
+ catch (std::exception &ex) {
+ Logger::levelLog(LOG_INFO, "'%s'", ex.what());
+ // If we catch inconsistent state on the interrupted reading
+ env.clear();
+ }
+ if (!m_fileExec.empty()) {
+ return m_debugger->Launch(m_fileExec, m_execArgs, env, cwd, arguments.value("stopAtEntry", false));
}
- std::vector<std::string> args = arguments.value("args", std::vector<std::string>());
+ vector<string> args = arguments.value("args", vector<string>());
args.insert(args.begin(), arguments.at("program").get<std::string>());
- return m_debugger->Launch("dotnet", args, arguments.value("stopAtEntry", false));
+ return m_debugger->Launch("dotnet", args, env, cwd, arguments.value("stopAtEntry", false));
} },
{ "threads", [this](const json &arguments, json &body){
HRESULT Status;
public string program;
public List<string> args;
public string cwd;
+ public Dictionary<string, string> env;
public string console;
public bool stopAtEntry;
public string internalConsoleOptions;
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
--- /dev/null
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+
+using NetcoreDbgTest;
+using NetcoreDbgTest.VSCode;
+using NetcoreDbgTest.Script;
+
+using Xunit;
+using Newtonsoft.Json;
+
+namespace NetcoreDbgTest.Script
+{
+ class Context
+ {
+ public static void PrepareStart()
+ {
+ InitializeRequest initializeRequest = new InitializeRequest();
+ initializeRequest.arguments.clientID = "vscode";
+ initializeRequest.arguments.clientName = "Visual Studio Code";
+ initializeRequest.arguments.adapterID = "coreclr";
+ initializeRequest.arguments.pathFormat = "path";
+ initializeRequest.arguments.linesStartAt1 = true;
+ initializeRequest.arguments.columnsStartAt1 = true;
+ initializeRequest.arguments.supportsVariableType = true;
+ initializeRequest.arguments.supportsVariablePaging = true;
+ initializeRequest.arguments.supportsRunInTerminalRequest = true;
+ initializeRequest.arguments.locale = "en-us";
+ Assert.True(VSCodeDebugger.Request(initializeRequest).Success);
+
+ LaunchRequest launchRequest = new LaunchRequest();
+ launchRequest.arguments.name = ".NET Core Launch (web)";
+ launchRequest.arguments.type = "coreclr";
+ launchRequest.arguments.preLaunchTask = "build";
+
+ launchRequest.arguments.program = Path.GetFileName(DebuggeeInfo.TargetAssemblyPath);
+ string targetAssemblyPath = Path.GetFileName(DebuggeeInfo.TargetAssemblyPath);
+ int subLength = DebuggeeInfo.TargetAssemblyPath.Length - targetAssemblyPath.Length;
+ string dllPath = DebuggeeInfo.TargetAssemblyPath.Substring(0, subLength);
+ launchRequest.arguments.cwd = dllPath;
+
+ launchRequest.arguments.env = new Dictionary<string, string>();
+ launchRequest.arguments.env.Add("ASPNETCORE_ENVIRONMENT", VALUE_A);
+ launchRequest.arguments.env.Add("ASPNETCORE_URLS", VALUE_B);
+ launchRequest.arguments.console = "internalConsole";
+ launchRequest.arguments.stopAtEntry = true;
+ launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
+ launchRequest.arguments.__sessionId = Guid.NewGuid().ToString();
+ Assert.True(VSCodeDebugger.Request(launchRequest).Success);
+ }
+
+ public static void PrepareEnd()
+ {
+ ConfigurationDoneRequest configurationDoneRequest = new ConfigurationDoneRequest();
+ Assert.True(VSCodeDebugger.Request(configurationDoneRequest).Success);
+ }
+
+ public static void WasExit()
+ {
+ bool wasExited = false;
+ int ?exitCode = null;
+ bool wasTerminated = false;
+
+ Func<string, bool> filter = (resJSON) => {
+ if (VSCodeDebugger.isResponseContainProperty(resJSON, "event", "exited")) {
+ wasExited = true;
+ ExitedEvent exitedEvent = JsonConvert.DeserializeObject<ExitedEvent>(resJSON);
+ exitCode = exitedEvent.body.exitCode;
+ }
+ if (VSCodeDebugger.isResponseContainProperty(resJSON, "event", "terminated")) {
+ wasTerminated = true;
+ }
+ if (wasExited && exitCode == 0 && wasTerminated)
+ return true;
+
+ return false;
+ };
+
+ if (!VSCodeDebugger.IsEventReceived(filter))
+ throw new NetcoreDbgTestCore.ResultNotSuccessException();
+ }
+
+ public static void DebuggerExit()
+ {
+ DisconnectRequest disconnectRequest = new DisconnectRequest();
+ disconnectRequest.arguments = new DisconnectArguments();
+ disconnectRequest.arguments.restart = false;
+ Assert.True(VSCodeDebugger.Request(disconnectRequest).Success);
+ }
+
+ public static void WasEntryPointHit()
+ {
+ Func<string, bool> filter = (resJSON) => {
+ if (VSCodeDebugger.isResponseContainProperty(resJSON, "event", "stopped")
+ && VSCodeDebugger.isResponseContainProperty(resJSON, "reason", "entry")) {
+ threadId = Convert.ToInt32(VSCodeDebugger.GetResponsePropertyValue(resJSON, "threadId"));
+ return true;
+ }
+ return false;
+ };
+
+ if (!VSCodeDebugger.IsEventReceived(filter))
+ throw new NetcoreDbgTestCore.ResultNotSuccessException();
+ }
+
+ public static void Continue()
+ {
+ ContinueRequest continueRequest = new ContinueRequest();
+ continueRequest.arguments.threadId = threadId;
+ Assert.True(VSCodeDebugger.Request(continueRequest).Success);
+ }
+
+ static VSCodeDebugger VSCodeDebugger = new VSCodeDebugger();
+ static int threadId = -1;
+
+ public const string VALUE_A = "Development";
+ public const string VALUE_B = "https://localhost:25001";
+ }
+}
+
+namespace VSCodeTestEnv
+{
+ class Program
+ {
+ public static void Main(string[] args)
+ {
+ Label.Checkpoint("init", "finish", () => {
+ Context.PrepareStart();
+ Context.PrepareEnd();
+ Context.WasEntryPointHit();
+ Context.Continue();
+ });
+
+ // Begin user code
+ user_code();
+ // End user code
+
+ Label.Checkpoint("finish", "", () => {
+ Context.WasExit();
+ Context.DebuggerExit();
+ });
+ }
+
+ public static void user_code()
+ {
+ var read_a = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
+ var read_b = Environment.GetEnvironmentVariable("ASPNETCORE_URLS");
+
+ // xunit Asserts() has a wrong behavior under Tizen devices
+ if (!String.Equals(Context.VALUE_A, read_a) || !String.Equals(Context.VALUE_B, read_b))
+ throw new NotImplementedException("TEST FAILED");
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">\r
+\r
+ <ItemGroup>\r
+ <ProjectReference Include="..\NetcoreDbgTest\NetcoreDbgTest.csproj" />\r
+ </ItemGroup>\r
+\r
+ <PropertyGroup>\r
+ <OutputType>Exe</OutputType>\r
+ <TargetFramework>netcoreapp2.1</TargetFramework>\r
+ </PropertyGroup>\r
+\r
+</Project>\r
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
launchRequest.arguments.type = "coreclr";
launchRequest.arguments.preLaunchTask = "build";
launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
- // NOTE this code works only with one source file
- launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+ launchRequest.arguments.cwd = "";
launchRequest.arguments.console = "internalConsole";
launchRequest.arguments.stopAtEntry = true;
launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
[InlineData("VSCodeTestVariables", "Program.cs")]
[InlineData("VSCodeTestEvaluate", "Program.cs")]
[InlineData("VSCodeTestStepping", "Program.cs")]
+ [InlineData("VSCodeTestEnv", "Program.cs")]
public void Run(string testCaseName, string testCourceList)
{
string testSuiteRoot = Path.GetFullPath(
<ProjectReference Include="..\VSCodeTestVariables\VSCodeTestVariables.csproj" />\r
<ProjectReference Include="..\VSCodeTestEvaluate\VSCodeTestEvaluate.csproj" />\r
<ProjectReference Include="..\VSCodeTestStepping\VSCodeTestStepping.csproj" />\r
+ <ProjectReference Include="..\VSCodeTestEnv\VSCodeTestEnv.csproj" />\r
</ItemGroup>\r
\r
</Project>\r
"VSCodeTestVariables"
"VSCodeTestEvaluate"
"VSCodeTestStepping"
+ "VSCodeTestEnv"
)
$TEST_NAMES = $args
"VSCodeTestVariables"
"VSCodeTestEvaluate"
"VSCodeTestStepping"
+ "VSCodeTestEnv"
)
TEST_NAMES="$@"
"VSCodeTestVariables"
"VSCodeTestEvaluate"
"VSCodeTestStepping"
+ "VSCodeTestEnv"
)
$TEST_NAMES = $args
--tcp localhost 4712 `
--proto $PROTO `
--test $TEST_NAME `
- --sources $SOURCE_FILES
+ --sources $SOURCE_FILES `
+ --assembly /tmp/$TEST_NAME.dll
} else {
$PROTO = "mi"
"VSCodeTestVariables"
"VSCodeTestEvaluate"
"VSCodeTestStepping"
+ "VSCodeTestEnv"
)
SDB=${SDB:-sdb}
--tcp localhost $PORT \
--proto $PROTO \
--test $TEST_NAME \
- --sources $SOURCE_FILES
+ --sources $SOURCE_FILES \
+ --assembly $REMOTETESTDIR/$TEST_NAME.dll
else
PROTO="mi"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MITestExceptionBreakpoint", "MITestExceptionBreakpoint\MITestExceptionBreakpoint.csproj", "{41431C99-59DF-4B7D-9647-BDF4258B048D}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSCodeTestEnv", "VSCodeTestEnv\VSCodeTestEnv.csproj", "{7555F581-C632-4490-A0E4-E4F1539E9209}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
{41431C99-59DF-4B7D-9647-BDF4258B048D}.Release|x64.Build.0 = Release|Any CPU
{41431C99-59DF-4B7D-9647-BDF4258B048D}.Release|x86.ActiveCfg = Release|Any CPU
{41431C99-59DF-4B7D-9647-BDF4258B048D}.Release|x86.Build.0 = Release|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|x64.Build.0 = Debug|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|x86.Build.0 = Debug|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|x64.ActiveCfg = Release|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|x64.Build.0 = Release|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|x86.ActiveCfg = Release|Any CPU
+ {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal