Support merging plugins into winsw.exe executable

* Decouple Core components into WinSWCore projects.
* Use ILMerge to merge everything (inc. Plugins) into a single executable

TODO: API Should be refactored before the publishing
TODO: check signing procedure

Signed-off-by: Oleg Nenashev <o.v.nenashev@gmail.com>

Conflicts:
	src/Core/ServiceWrapper/winsw.csproj

Conflicts:
	src/Core/ServiceWrapper/Main.cs
	src/winsw.sln
pull/74/head
Oleg Nenashev 2015-02-01 01:41:22 +03:00
parent 2546168ed3
commit 3af1f72658
30 changed files with 188 additions and 151 deletions

2
.gitignore vendored
View File

@ -5,3 +5,5 @@ obj
/winsw.csproj.user
/winsw_cert.pfx
*.user
/src/packages/NUnit.2.6.4
/src/packages/ILMerge.MSBuild.Tasks.1.0.0.3

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ILMerge.MSBuild.Tasks" version="1.0.0.3" />
</packages>

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace winsw.util
{
public interface IEventWriter
{
void LogEvent(String message);
void LogEvent(String message, EventLogEntryType type);
}
}

View File

@ -18,6 +18,7 @@ using winsw.Extensions;
using winsw.Util;
using WMI;
using ServiceType = WMI.ServiceType;
using winsw.Native;
using System.Reflection;
namespace winsw

View File

@ -1,15 +0,0 @@
using System;
namespace winsw.Util
{
public class WinSWException : Exception
{
public WinSWException(String message)
: base(message)
{ }
public WinSWException(String message, Exception innerException)
: base(message, innerException)
{ }
}
}

View File

@ -1,73 +0,0 @@
using System;
using System.IO;
using System.Xml;
namespace winsw.Util
{
public class XmlHelper
{
/// <summary>
/// Retrieves a single string element
/// </summary>
/// <param name="node">Parent node</param>
/// <param name="tagName">Element name</param>
/// <param name="optional">If otional, don't throw an exception if the elemen is missing</param>
/// <returns>String value or null</returns>
/// <exception cref="InvalidDataException">The required element is missing</exception>
public static string SingleElement(XmlNode node, string tagName, Boolean optional)
{
var n = node.SelectSingleNode(tagName);
if (n == null && !optional) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
return n == null ? null : Environment.ExpandEnvironmentVariables(n.InnerText);
}
/// <summary>
/// Retrieves a single node
/// </summary>
/// <param name="node">Parent node</param>
/// <param name="tagName">Element name</param>
/// <param name="optional">If otional, don't throw an exception if the elemen is missing</param>
/// <returns>String value or null</returns>
/// <exception cref="InvalidDataException">The required element is missing</exception>
public static XmlNode SingleNode(XmlNode node, string tagName, Boolean optional)
{
var n = node.SelectSingleNode(tagName);
if (n == null && !optional) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
return n;
}
/// <summary>
/// Retrieves a single mandatory attribute
/// </summary>
/// <param name="node">Parent node</param>
/// <param name="attributeName">Attribute name</param>
/// <returns>Attribute value</returns>
/// <exception cref="InvalidDataException">The required attribute is missing</exception>
public static TAttributeType SingleAttribute <TAttributeType> (XmlElement node, string attributeName)
{
if (!node.HasAttribute(attributeName))
{
throw new InvalidDataException("Attribute <" + attributeName + "> is missing in configuration XML");
}
return SingleAttribute(node, attributeName, default(TAttributeType));
}
/// <summary>
/// Retrieves a single optional attribute
/// </summary>
/// <param name="node">Parent node</param>
/// <param name="attributeName">Attribute name</param>
/// <param name="defaultValue">Default value</param>
/// <returns>Attribute value (or default)</returns>
public static TAttributeType SingleAttribute<TAttributeType>(XmlElement node, string attributeName, TAttributeType defaultValue)
{
if (!node.HasAttribute(attributeName)) return defaultValue;
string rawValue = node.GetAttribute(attributeName);
string substitutedValue = Environment.ExpandEnvironmentVariables(rawValue);
var value = (TAttributeType)Convert.ChangeType(substitutedValue, typeof(TAttributeType));
return value;
}
}
}

View File

@ -9,7 +9,7 @@
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>winsw</RootNamespace>
<AssemblyName>winsw</AssemblyName>
<AssemblyName>WindowsService</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<StartupObject>
@ -62,9 +62,6 @@
</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net">
<HintPath>..\..\packages\log4net.2.0.3\lib\net20-full\log4net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
@ -74,28 +71,11 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Advapi32.cs" />
<Compile Include="Download.cs" />
<Compile Include="DynamicProxy.cs" />
<Compile Include="Extensions\AbstractWinSWExtension.cs" />
<Compile Include="Extensions\ExtensionException.cs" />
<Compile Include="Extensions\IWinSWExtension.cs" />
<Compile Include="Extensions\WinSWExtensionDescriptor.cs" />
<Compile Include="Extensions\WinSWExtensionManager.cs" />
<Compile Include="Kernel32.cs" />
<Compile Include="LogAppenders.cs" />
<Compile Include="Main.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="PeriodicRollingCalendar.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceDescriptor.cs" />
<Compile Include="SigIntHelper.cs" />
<Compile Include="Util\IEventWriter.cs" />
<Compile Include="Util\WinSWException.cs" />
<Compile Include="Util\XmlHelper.cs" />
<Compile Include="Wmi.cs" />
<Compile Include="WmiSchema.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="manifest.xml" />
@ -108,7 +88,6 @@
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\winsw_cert.pfx" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
@ -122,6 +101,16 @@
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj">
<Project>{ca5c71db-c5a8-4c27-bf83-8e6daed9d6b5}</Project>
<Name>SharedDirectoryMapper</Name>
</ProjectReference>
<ProjectReference Include="..\WinSWCore\WinSWCore.csproj">
<Project>{9d0c63e2-b6ff-4a85-bd36-b3e5d7f27d06}</Project>
<Name>WinSWCore</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@ -142,4 +131,18 @@
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- Merge plugins into winsw.exe -->
<UsingTask TaskName="ILMerge.MSBuild.Tasks.ILMerge" AssemblyFile="$(SolutionDir)\packages\ILMerge.MSBuild.Tasks.1.0.0.3\tools\ILMerge.MSBuild.Tasks.dll" />
<Target Name="AfterBuild">
<ItemGroup>
<MergeAsm Include="$(OutputPath)$(TargetFileName)" />
<MergeAsm Include="$(OutputPath)WinSWCore.dll" />
<MergeAsm Include="$(OutputPath)SharedDirectoryMapper.dll" />
</ItemGroup>
<PropertyGroup>
<MergedAssembly>$(ProjectDir)$(OutDir)winsw.exe</MergedAssembly>
</PropertyGroup>
<Message Text="ILMerge @(MergeAsm) -&gt; $(MergedAssembly)" Importance="high" />
<ILMerge InputAssemblies="@(MergeAsm)" OutputFile="$(MergedAssembly)" TargetKind="SameAsPrimaryAssembly" />
</Target>
</Project>

View File

@ -1,5 +1,4 @@
using System;
using winsw.Util;
namespace winsw.Extensions
{

View File

@ -6,9 +6,9 @@ using System.Text;
// ReSharper disable InconsistentNaming
namespace winsw
namespace winsw.Native
{
class ServiceManager : IDisposable
public class ServiceManager : IDisposable
{
private IntPtr _handle;
@ -39,7 +39,7 @@ namespace winsw
}
}
class Service : IDisposable
public class Service : IDisposable
{
internal IntPtr Handle;
@ -87,7 +87,7 @@ namespace winsw
}
}
static class LogonAsAService
public static class LogonAsAService
{
public static void AddLogonAsAServiceRight(string username)
{
@ -251,7 +251,7 @@ namespace winsw
/// Advapi32.dll wrapper for performing additional service related operations that are not
/// available in WMI.
/// </summary>
internal class Advapi32
public class Advapi32
{
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
@ -272,7 +272,7 @@ namespace winsw
internal static extern bool CloseServiceHandle(IntPtr hSCObject);
[DllImport("advapi32.DLL")]
internal static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus);
public static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus);
[DllImport("advapi32.dll", PreserveSig = true)]
internal static extern UInt32 LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, Int32 DesiredAccess,

View File

@ -1,18 +1,18 @@
using System;
using System.Runtime.InteropServices;
namespace winsw
namespace winsw.Native
{
/// <summary>
/// kernel32.dll P/Invoke wrappers
/// </summary>
internal class Kernel32
public class Kernel32
{
[DllImport("Kernel32.dll", SetLastError = true)]
internal static extern int SetStdHandle(int device, IntPtr handle);
public static extern int SetStdHandle(int device, IntPtr handle);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool CreateProcess(string lpApplicationName,
public static extern bool CreateProcess(string lpApplicationName,
string lpCommandLine, IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes, bool bInheritHandles,
uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
@ -20,11 +20,11 @@ namespace winsw
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll")]
internal static extern int GetLastError();
public static extern int GetLastError();
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
@ -33,7 +33,7 @@ namespace winsw
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct STARTUPINFO
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("WinSWCore")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WinSWCore")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8f845354-ba20-455d-82d1-9b6ec4e0e517")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -5,6 +5,7 @@ using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Xml;
using winsw.Native;
using winsw.Util;
using WMI;

View File

@ -4,9 +4,9 @@ using System.Text;
using System.Xml;
using System.IO;
namespace winsw.Utils
namespace winsw.Util
{
internal class XmlHelper
public class XmlHelper
{
/// <summary>
/// Retrieves a single string element

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>winsw</RootNamespace>
<AssemblyName>WinSWCore</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>..\..\..\winsw_cert.pfx</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Management" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Download.cs" />
<Compile Include="DynamicProxy.cs" />
<Compile Include="Extensions\AbstractWinSWExtension.cs" />
<Compile Include="Extensions\ExtensionException.cs" />
<Compile Include="Extensions\IWinSWExtension.cs" />
<Compile Include="Extensions\WinSWExtensionDescriptor.cs" />
<Compile Include="Extensions\WinSWExtensionManager.cs" />
<Compile Include="LogAppenders.cs" />
<Compile Include="Native\Advapi32.cs" />
<Compile Include="Native\Kernel32.cs" />
<Compile Include="PeriodicRollingCalendar.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceDescriptor.cs" />
<Compile Include="Util\IEventWriter.cs" />
<Compile Include="Util\XmlHelper.cs" />
<Compile Include="WinSWException.cs" />
<Compile Include="Wmi.cs" />
<Compile Include="WmiSchema.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\winsw_cert.pfx" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
namespace winsw.extensions
namespace winsw
{
public class WinSWException : Exception
{

View File

@ -41,9 +41,9 @@
<Compile Include="SharedDirectoryMapperHelper.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Core\ServiceWrapper\winsw.csproj">
<Project>{0de77f55-ade5-43c1-999a-0bc81153b039}</Project>
<Name>winsw</Name>
<ProjectReference Include="..\..\Core\WinSWCore\WinSWCore.csproj">
<Project>{9d0c63e2-b6ff-4a85-bd36-b3e5d7f27d06}</Project>
<Name>WinSWCore</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -7,7 +7,7 @@ namespace winsw.Plugins.SharedDirectoryMapper
/// <summary>
/// Stores configuration entries for SharedDirectoryMapper extension.
/// </summary>
internal class SharedDirectoryMapperConfig
public class SharedDirectoryMapperConfig
{
public bool EnableMapping { get; set; }
public String Label { get; set; }

View File

@ -64,6 +64,10 @@
<Project>{0DE77F55-ADE5-43C1-999A-0BC81153B039}</Project>
<Name>winsw</Name>
</ProjectReference>
<ProjectReference Include="..\..\Core\WinSWCore\WinSWCore.csproj">
<Project>{9d0c63e2-b6ff-4a85-bd36-b3e5d7f27d06}</Project>
<Name>WinSWCore</Name>
</ProjectReference>
<ProjectReference Include="..\..\Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj">
<Project>{ca5c71db-c5a8-4c27-bf83-8e6daed9d6b5}</Project>
<Name>SharedDirectoryMapper</Name>

View File

@ -1,4 +1,3 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
@ -6,15 +5,11 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winsw", "Core\ServiceWrapper\winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winswTests", "Test\winswTests\winswTests.csproj", "{93843402-842B-44B4-B303-AEE829BE0B43}"
ProjectSection(ProjectDependencies) = postProject
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5} = {CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{6BDF4025-D46C-4C69-BDB2-5CE434C857AA}"
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.Config = .nuget\NuGet.Config
.nuget\NuGet.exe = .nuget\NuGet.exe
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedDirectoryMapper", "Plugins\SharedDirectoryMapper\SharedDirectoryMapper.csproj", "{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}"
@ -23,6 +18,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{077C2CEC
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{BC4AD891-E87E-4F30-867C-FD8084A29E5D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5297623A-1A95-4F89-9AAE-DA634081EC86}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinSWCore", "Core\WinSWCore\WinSWCore.csproj", "{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -35,8 +34,8 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Mixed Platforms.ActiveCfg = Release|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Mixed Platforms.Build.0 = Release|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.ActiveCfg = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.Build.0 = Debug|Any CPU
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -69,12 +68,26 @@ Global
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.ActiveCfg = Release|Any CPU
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5}.Release|Win32.Build.0 = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.ActiveCfg = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Debug|Win32.Build.0 = Debug|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Any CPU.Build.0 = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.ActiveCfg = Release|Any CPU
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06}.Release|Win32.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0DE77F55-ADE5-43C1-999A-0BC81153B039} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
{93843402-842B-44B4-B303-AEE829BE0B43} = {077C2CEC-B687-4B53-86E9-C1A1BF5554E5}
{CA5C71DB-C5A8-4C27-BF83-8E6DAED9D6B5} = {BC4AD891-E87E-4F30-867C-FD8084A29E5D}
{9D0C63E2-B6FF-4A85-BD36-B3E5D7F27D06} = {5297623A-1A95-4F89-9AAE-DA634081EC86}
EndGlobalSection
EndGlobal