diff --git a/Source/ChocolateyGui.Common.Tests/ChocolateyGui.Common.Tests.csproj b/Source/ChocolateyGui.Common.Tests/ChocolateyGui.Common.Tests.csproj new file mode 100644 index 000000000..d1293eeda --- /dev/null +++ b/Source/ChocolateyGui.Common.Tests/ChocolateyGui.Common.Tests.csproj @@ -0,0 +1,32 @@ + + + + net48 + + false + + Debug;Release;ReleaseOfficial + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + diff --git a/Source/ChocolateyGui.Common.Tests/UnitTest1.cs b/Source/ChocolateyGui.Common.Tests/UnitTest1.cs new file mode 100644 index 000000000..7efec3805 --- /dev/null +++ b/Source/ChocolateyGui.Common.Tests/UnitTest1.cs @@ -0,0 +1,18 @@ +namespace ChocolateyGui.Common.Tests +{ + using NUnit.Framework; + + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void Test1() + { + Assert.Pass(); + } + } +} \ No newline at end of file diff --git a/Source/ChocolateyGui.Common.Windows.Tests/ChocolateyGui.Common.Windows.Tests.csproj b/Source/ChocolateyGui.Common.Windows.Tests/ChocolateyGui.Common.Windows.Tests.csproj new file mode 100644 index 000000000..58f7ebc9c --- /dev/null +++ b/Source/ChocolateyGui.Common.Windows.Tests/ChocolateyGui.Common.Windows.Tests.csproj @@ -0,0 +1,32 @@ + + + + net48 + + false + + Debug;Release;ReleaseOfficial + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + diff --git a/Source/ChocolateyGui.Common.Windows.Tests/ChocolateyTestSetup.cs b/Source/ChocolateyGui.Common.Windows.Tests/ChocolateyTestSetup.cs new file mode 100644 index 000000000..42e3d4402 --- /dev/null +++ b/Source/ChocolateyGui.Common.Windows.Tests/ChocolateyTestSetup.cs @@ -0,0 +1,20 @@ +using AutoMapper; +using ChocolateyGui.Common.Windows.Startup; +using NUnit.Framework; + +namespace ChocolateyGui.Common.Windows.Tests +{ + [SetUpFixture] + public class ChocolateyTestSetup + { + public static IMapper Mapper { get; private set; } + + [OneTimeSetUp] + public void SetupAutomapper() + { + var mapperConfiguration = ChocolateyGuiMapper.CreateConfiguration(); + + Mapper = mapperConfiguration.CreateMapper(); + } + } +} \ No newline at end of file diff --git a/Source/ChocolateyGui.Common.Windows.Tests/Utilities/GalleryUriBuilderTests.cs b/Source/ChocolateyGui.Common.Windows.Tests/Utilities/GalleryUriBuilderTests.cs new file mode 100644 index 000000000..1f20f927f --- /dev/null +++ b/Source/ChocolateyGui.Common.Windows.Tests/Utilities/GalleryUriBuilderTests.cs @@ -0,0 +1,90 @@ +using System.Collections; +using ChocolateyGui.Common.Windows.Utilities; +using FluentAssertions; +using NUnit.Framework; + +namespace ChocolateyGui.Common.Windows.Tests.Utilities +{ + [TestFixture] + [TestOf(typeof(GalleryUriBuilder))] + public class GalleryUriBuilderTests + { + public static IEnumerable EmptyValues => new[] + { + null, + string.Empty, + " " + }; + + [TestCaseSource(nameof(EmptyValues))] + public void BuildFromPackageAndSource_ReturnsNull_ForNullOrWhitespacePackageId(string packageId) + { + GalleryUriBuilder.BuildFromPackageAndSource(packageId, "https://community.chocolatey.org/").Should().BeNull(); + } + + [TestCaseSource(nameof(EmptyValues))] + public void BuildFromPackageAndSource_ReturnsNull_ForNullOrWhitespaceSource(string source) + { + GalleryUriBuilder.BuildFromPackageAndSource("some-package", source).Should().BeNull(); + } + + [Test] + public void BuildFromPackageAndSource_ReturnsValidUri_ForValidPackageIdAndSource() + { + var uri = GalleryUriBuilder.BuildFromPackageAndSource("some-package", "https://community.chocolatey.org/"); + uri.Should().NotBeNull(); + uri.ToString().Should().Be("https://community.chocolatey.org/packages/some-package"); + } + + [Test] + public void BuildFromPackageAndSource_ReturnsValidUri_WithUnknownSource() + { + var uri = GalleryUriBuilder.BuildFromPackageAndSource("some-package", "https://myget.org/F/chocolatey/api/v2/"); + uri.Should().NotBeNull(); + uri.ToString().Should().Be("https://myget.org/packages/some-package"); + } + + [Test] + public void BuildFromPackageAndSource_ReturnsValidUri_WithVersion() + { + var uri = GalleryUriBuilder.BuildFromPackageAndSource("some-package", "https://community.chocolatey.org/", new NuGet.Versioning.NuGetVersion(1, 2, 3)); + uri.Should().NotBeNull(); + uri.ToString().Should().Be("https://community.chocolatey.org/packages/some-package/1.2.3"); + } + + [Test] + public void BuildFromPackageSource_ReturnsValidUri_WithPreReleaseVersion() + { + var uri = GalleryUriBuilder.BuildFromPackageAndSource("some-package", "https://community.chocolatey.org/", new NuGet.Versioning.NuGetVersion(1, 2, 3, "beta")); + uri.Should().NotBeNull(); + uri.ToString().Should().Be("https://community.chocolatey.org/packages/some-package/1.2.3-beta"); + } + + [Test] + public void IsKnownSource_ReturnsFalse_ForInvalidUri() + { + GalleryUriBuilder.IsKnownSource("not a valid uri").Should().BeFalse(); + } + + [TestCaseSource(nameof(EmptyValues))] + public void IsKnownSource_ReturnsFalse_ForNullOrWhitespace(string source) + { + GalleryUriBuilder.IsKnownSource(source).Should().BeFalse(); + } + + [TestCase("https://blog.chocolatey.org/api/v2/")] + [TestCase("http://myget.org/F/chocolatey/api/v2/")] + public void IsKnownSource_ReturnsFalse_ForUnknownSources(string source) + { + GalleryUriBuilder.IsKnownSource(source).Should().BeFalse(); + } + + [TestCase("https://chocolatey.org/api/v2/")] + [TestCase("https://community.chocolatey.org/api/v2/")] + [TestCase("https://community-test.chocolatey.org/api/v2/")] + public void IsKnownSource_ReturnsTrue_ForKnownSources(string source) + { + GalleryUriBuilder.IsKnownSource(source).Should().BeTrue(); + } + } +} \ No newline at end of file diff --git a/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs b/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs index d3f6f16e4..9e5d3216a 100644 --- a/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs +++ b/Source/ChocolateyGui.Common.Windows/Services/ChocolateyService.cs @@ -23,6 +23,7 @@ using ChocolateyGui.Common.Properties; using ChocolateyGui.Common.Services; using ChocolateyGui.Common.Utilities; +using ChocolateyGui.Common.Windows.Utilities; using Microsoft.VisualStudio.Threading; using NuGet.Protocol.Core.Types; using NuGet.Versioning; @@ -716,6 +717,13 @@ private static Package GetMappedPackage(GetChocolatey choco, PackageResult packa mappedPackage.IsInstalled = !string.IsNullOrWhiteSpace(package.InstallLocation) || forceInstalled; mappedPackage.IsPrerelease = mappedPackage.Version.IsPrerelease; + + var sourceUrl = packageInfo.SourceInstalledFrom ?? package.Source; + + if (string.IsNullOrWhiteSpace(mappedPackage.GalleryDetailsUrl) && GalleryUriBuilder.IsKnownSource(sourceUrl)) + { + mappedPackage.GalleryDetailsUrl = GalleryUriBuilder.BuildFromPackageAndSource(package.Identity.Id, sourceUrl, package.Identity.Version)?.ToString(); + } } return mappedPackage; diff --git a/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiMapper.cs b/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiMapper.cs new file mode 100644 index 000000000..b4d79d168 --- /dev/null +++ b/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiMapper.cs @@ -0,0 +1,72 @@ +using AutoMapper; +using chocolatey.infrastructure.app.configuration; +using chocolatey.infrastructure.app.nuget; +using ChocolateyGui.Common.Models; +using ChocolateyGui.Common.ViewModels.Items; +using ChocolateyGui.Common.Windows.ViewModels; +using NuGet.Protocol.Core.Types; +using ChocolateySource = chocolatey.infrastructure.app.configuration.ChocolateySource; +using Environment = System.Environment; + +namespace ChocolateyGui.Common.Windows.Startup +{ + public static class ChocolateyGuiMapper + { + public static MapperConfiguration CreateConfiguration() + { + var mapperConfiguration = new MapperConfiguration(config => + { + config.ForAllMaps((_, mapping) => mapping.MaxDepth(64)); + + config.CreateMap() + .ForMember(vm => vm.IsInstalled, options => options.Ignore()); + + config.CreateMap() + .ForMember(dest => dest.Version, opt => opt.MapFrom(src => src.Identity.Version)) + .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Identity.Id)) + .ForMember(dest => dest.Authors, opt => opt.MapFrom(src => src.Authors.Split(','))) + .ForMember(dest => dest.Owners, opt => opt.MapFrom(src => src.Owners.Split(','))) + .ForMember(dest => dest.GalleryDetailsUrl, opt => opt.MapFrom(src => src.PackageDetailsUrl == null ? null : src.PackageDetailsUrl.AbsoluteUri)); + + config.CreateMap(); + config.CreateMap(); + config.CreateMap() + .ForMember(dest => dest.Password, opt => opt.MapFrom(src => NugetEncryptionUtility.DecryptString(src.Password))) + .ForMember(dest => dest.CertificatePassword, opt => opt.MapFrom(src => NugetEncryptionUtility.DecryptString(src.CertificatePassword))); + + config.CreateMap() + .ForMember(dest => dest.VisibleToAdminsOnly, opt => opt.MapFrom(src => src.VisibleToAdminOnly)); + + config.CreateMap() + .ForMember( + dest => dest.DownloadChecksum, + opt => opt.Condition(source => !source.IgnoreChecksums)) + .ForMember( + dest => dest.DownloadChecksumType, + opt => opt.Condition(source => + !source.IgnoreChecksums && !string.IsNullOrEmpty(source.DownloadChecksum))) + .ForMember( + dest => dest.DownloadChecksum64bit, + opt => opt.Condition(source => + Environment.Is64BitOperatingSystem + && !source.IgnoreChecksums + && !source.Forcex86)) + .ForMember( + dest => dest.DownloadChecksumType64bit, + opt => opt.Condition(source => + Environment.Is64BitOperatingSystem + && !source.IgnoreChecksums + && !source.Forcex86 + && !string.IsNullOrEmpty(source.DownloadChecksum64bit))) + .ForMember( + dest => dest.PackageParameters, + opt => opt.Condition(source => !source.SkipPowerShell)) + .ForMember( + dest => dest.InstallArguments, + opt => opt.Condition(source => !source.SkipPowerShell && !source.NotSilent)); + }); + + return mapperConfiguration; + } + } +} diff --git a/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs b/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs index dfa10e50a..12d01fb27 100644 --- a/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs +++ b/Source/ChocolateyGui.Common.Windows/Startup/ChocolateyGuiModule.cs @@ -13,13 +13,10 @@ using Caliburn.Micro; using chocolatey; using chocolatey.infrastructure.adapters; -using chocolatey.infrastructure.app.configuration; -using chocolatey.infrastructure.app.nuget; using chocolatey.infrastructure.app.services; using chocolatey.infrastructure.cryptography; using chocolatey.infrastructure.filesystem; using chocolatey.infrastructure.services; -using ChocolateyGui.Common.Models; using ChocolateyGui.Common.Properties; using ChocolateyGui.Common.Providers; using ChocolateyGui.Common.Services; @@ -29,9 +26,6 @@ using ChocolateyGui.Common.Windows.ViewModels; using ChocolateyGui.Common.Windows.Views; using LiteDB; -using NuGet.Protocol.Core.Types; -using ChocolateySource = chocolatey.infrastructure.app.configuration.ChocolateySource; -using Environment = System.Environment; using PackageViewModel = ChocolateyGui.Common.Windows.ViewModels.Items.PackageViewModel; namespace ChocolateyGui.Common.Windows.Startup @@ -89,56 +83,7 @@ protected override void Load(ContainerBuilder builder) builder.RegisterType().As().SingleInstance(); // Register Mapper - var mapperConfiguration = new MapperConfiguration(config => - { - config.ForAllMaps((_, mapping) => mapping.MaxDepth(64)); - - config.CreateMap() - .ForMember(vm => vm.IsInstalled, options => options.Ignore()); - - config.CreateMap() - .ForMember(dest => dest.Version, opt => opt.MapFrom(src => src.Identity.Version)) - .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Identity.Id)) - .ForMember(dest => dest.Authors, opt => opt.MapFrom(src => src.Authors.Split(','))) - .ForMember(dest => dest.Owners, opt => opt.MapFrom(src => src.Owners.Split(','))); - - config.CreateMap(); - config.CreateMap(); - config.CreateMap() - .ForMember(dest => dest.Password, opt => opt.MapFrom(src => NugetEncryptionUtility.DecryptString(src.Password))) - .ForMember(dest => dest.CertificatePassword, opt => opt.MapFrom(src => NugetEncryptionUtility.DecryptString(src.CertificatePassword))); - - config.CreateMap() - .ForMember(dest => dest.VisibleToAdminsOnly, opt => opt.MapFrom(src => src.VisibleToAdminOnly)); - - config.CreateMap() - .ForMember( - dest => dest.DownloadChecksum, - opt => opt.Condition(source => !source.IgnoreChecksums)) - .ForMember( - dest => dest.DownloadChecksumType, - opt => opt.Condition(source => - !source.IgnoreChecksums && !string.IsNullOrEmpty(source.DownloadChecksum))) - .ForMember( - dest => dest.DownloadChecksum64bit, - opt => opt.Condition(source => - Environment.Is64BitOperatingSystem - && !source.IgnoreChecksums - && !source.Forcex86)) - .ForMember( - dest => dest.DownloadChecksumType64bit, - opt => opt.Condition(source => - Environment.Is64BitOperatingSystem - && !source.IgnoreChecksums - && !source.Forcex86 - && !string.IsNullOrEmpty(source.DownloadChecksum64bit))) - .ForMember( - dest => dest.PackageParameters, - opt => opt.Condition(source => !source.SkipPowerShell)) - .ForMember( - dest => dest.InstallArguments, - opt => opt.Condition(source => !source.SkipPowerShell && !source.NotSilent)); - }); + var mapperConfiguration = ChocolateyGuiMapper.CreateConfiguration(); builder.RegisterType().As().SingleInstance(); builder.RegisterInstance(mapperConfiguration.CreateMapper()).As(); diff --git a/Source/ChocolateyGui.Common.Windows/Utilities/GalleryUriBuilder.cs b/Source/ChocolateyGui.Common.Windows/Utilities/GalleryUriBuilder.cs new file mode 100644 index 000000000..854e341fa --- /dev/null +++ b/Source/ChocolateyGui.Common.Windows/Utilities/GalleryUriBuilder.cs @@ -0,0 +1,48 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright 2017 - Present Chocolatey Software, LLC +// Copyright 2014 - 2017 Rob Reynolds, the maintainers of Chocolatey, and RealDimensions Software, LLC +// +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using chocolatey; +using NuGet.Versioning; + +namespace ChocolateyGui.Common.Windows.Utilities +{ + public static class GalleryUriBuilder + { + public static Uri BuildFromPackageAndSource(string packageId, string source, NuGetVersion version = null) + { + if (string.IsNullOrWhiteSpace(packageId) || string.IsNullOrWhiteSpace(source)) + { + return null; + } + + var uri = new UriBuilder(source) + { + Path = version == null ? $"packages/{packageId}" : $"packages/{packageId}/{version.OriginalVersion ?? version.ToFullStringChecked()}" + }; + + return uri.Uri; + } + + public static Uri BuildCommunityGalleryFromPackage(string packageId, NuGetVersion version = null) + { + return BuildFromPackageAndSource(packageId, "https://community.chocolatey.org/", version); + } + + public static bool IsKnownSource(string sourceUrl) + { + if (string.IsNullOrWhiteSpace(sourceUrl) || !Uri.TryCreate(sourceUrl, UriKind.Absolute, out var uri)) + { + return false; + } + + return uri.Host.Equals("chocolatey.org", StringComparison.OrdinalIgnoreCase) + || uri.Host.Equals("community.chocolatey.org", StringComparison.OrdinalIgnoreCase) + || uri.Host.Equals("community-test.chocolatey.org", StringComparison.OrdinalIgnoreCase); + } + } +} diff --git a/Source/ChocolateyGui.Tests/ChocolateyGui.Tests.csproj b/Source/ChocolateyGui.Tests/ChocolateyGui.Tests.csproj new file mode 100644 index 000000000..6e25eb40a --- /dev/null +++ b/Source/ChocolateyGui.Tests/ChocolateyGui.Tests.csproj @@ -0,0 +1,32 @@ + + + + net48 + + false + + Debug;Release;ReleaseOfficial + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + diff --git a/Source/ChocolateyGui.Tests/UnitTest1.cs b/Source/ChocolateyGui.Tests/UnitTest1.cs new file mode 100644 index 000000000..6a4625747 --- /dev/null +++ b/Source/ChocolateyGui.Tests/UnitTest1.cs @@ -0,0 +1,18 @@ +namespace ChocolateyGui.Tests +{ + using NUnit.Framework; + + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void Test1() + { + Assert.Pass(); + } + } +} \ No newline at end of file diff --git a/Source/ChocolateyGui.UITests/ChocolateyGui.UITests.csproj b/Source/ChocolateyGui.UITests/ChocolateyGui.UITests.csproj index 61131c60b..642916171 100644 --- a/Source/ChocolateyGui.UITests/ChocolateyGui.UITests.csproj +++ b/Source/ChocolateyGui.UITests/ChocolateyGui.UITests.csproj @@ -6,9 +6,14 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + diff --git a/Source/ChocolateyGui.sln b/Source/ChocolateyGui.sln index c4d57b92d..42c050a76 100644 --- a/Source/ChocolateyGui.sln +++ b/Source/ChocolateyGui.sln @@ -27,6 +27,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChocolateyGui.Common.Window EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChocolateyGui.UITests", "ChocolateyGui.UITests\ChocolateyGui.UITests.csproj", "{58AE187D-B19D-44D8-97EC-683FABD295A8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChocolateyGui.Tests", "ChocolateyGui.Tests\ChocolateyGui.Tests.csproj", "{1175337D-ED16-437E-B35E-72A5A7B152D2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChocolateyGui.Common.Tests", "ChocolateyGui.Common.Tests\ChocolateyGui.Common.Tests.csproj", "{085EA320-903D-4E45-8BC6-20CE39C14F00}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChocolateyGui.Common.Windows.Tests", "ChocolateyGui.Common.Windows.Tests\ChocolateyGui.Common.Windows.Tests.csproj", "{FB7E815C-E218-418D-A470-014CF938959F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{31C451A9-DE07-4786-BED7-59DCB40905AD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -122,10 +130,57 @@ Global {58AE187D-B19D-44D8-97EC-683FABD295A8}.ReleaseOfficial|x86.Build.0 = Release|Any CPU {58AE187D-B19D-44D8-97EC-683FABD295A8}.WIX|Any CPU.ActiveCfg = Debug|Any CPU {58AE187D-B19D-44D8-97EC-683FABD295A8}.WIX|x86.ActiveCfg = Debug|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.Debug|x86.ActiveCfg = Debug|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.Debug|x86.Build.0 = Debug|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.Release|Any CPU.Build.0 = Release|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.Release|x86.ActiveCfg = Release|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.Release|x86.Build.0 = Release|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.ReleaseOfficial|Any CPU.ActiveCfg = ReleaseOfficial|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.ReleaseOfficial|Any CPU.Build.0 = ReleaseOfficial|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.ReleaseOfficial|x86.ActiveCfg = Release|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.ReleaseOfficial|x86.Build.0 = Release|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.WIX|Any CPU.ActiveCfg = Debug|Any CPU + {1175337D-ED16-437E-B35E-72A5A7B152D2}.WIX|x86.ActiveCfg = Debug|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.Debug|x86.ActiveCfg = Debug|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.Debug|x86.Build.0 = Debug|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.Release|Any CPU.Build.0 = Release|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.Release|x86.ActiveCfg = Release|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.Release|x86.Build.0 = Release|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.ReleaseOfficial|Any CPU.ActiveCfg = ReleaseOfficial|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.ReleaseOfficial|Any CPU.Build.0 = ReleaseOfficial|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.ReleaseOfficial|x86.ActiveCfg = Release|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.ReleaseOfficial|x86.Build.0 = Release|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.WIX|Any CPU.ActiveCfg = Debug|Any CPU + {085EA320-903D-4E45-8BC6-20CE39C14F00}.WIX|x86.ActiveCfg = Debug|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.Debug|x86.ActiveCfg = Debug|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.Debug|x86.Build.0 = Debug|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.Release|Any CPU.Build.0 = Release|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.Release|x86.ActiveCfg = Release|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.Release|x86.Build.0 = Release|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.ReleaseOfficial|Any CPU.ActiveCfg = ReleaseOfficial|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.ReleaseOfficial|Any CPU.Build.0 = ReleaseOfficial|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.ReleaseOfficial|x86.ActiveCfg = Release|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.ReleaseOfficial|x86.Build.0 = Release|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.WIX|Any CPU.ActiveCfg = Debug|Any CPU + {FB7E815C-E218-418D-A470-014CF938959F}.WIX|x86.ActiveCfg = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1175337D-ED16-437E-B35E-72A5A7B152D2} = {31C451A9-DE07-4786-BED7-59DCB40905AD} + {085EA320-903D-4E45-8BC6-20CE39C14F00} = {31C451A9-DE07-4786-BED7-59DCB40905AD} + {FB7E815C-E218-418D-A470-014CF938959F} = {31C451A9-DE07-4786-BED7-59DCB40905AD} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0DAE54C5-B74A-4794-8331-7E144197DBD5} EndGlobalSection