From 82a816e40d683ad7e02959a2c033019b553cb9e0 Mon Sep 17 00:00:00 2001
From: xljiulang <366193849@qq.com>
Date: Sat, 24 Jul 2021 04:08:29 +0800
Subject: [PATCH] =?UTF-8?q?=E5=88=86=E7=A6=BB=E5=92=8C=E5=A4=8D=E7=94=A8Ht?=
=?UTF-8?q?tpClient?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../DomainResolver.cs | 4 +-
FastGithub.Http/FastGithub.Http.csproj | 14 ++++
FastGithub.Http/HttpClient.cs | 56 ++++++++++++++
FastGithub.Http/HttpClientFactory.cs | 35 +++++++++
.../HttpClientHandler.cs | 12 +--
.../HttpClientServiceCollectionExtensions.cs | 25 +++++++
FastGithub.Http/IDomainResolver.cs | 20 +++++
FastGithub.Http/IHttpClientFactory.cs | 15 ++++
.../RequestContext.cs | 2 +-
.../RequestContextExtensions.cs | 2 +-
.../FastGithub.ReverseProxy.csproj | 2 +-
FastGithub.ReverseProxy/HttpClientFactory.cs | 73 -------------------
.../ReverseProxyMiddleware.cs | 7 +-
...ReverseProxyServiceCollectionExtensions.cs | 3 +-
FastGithub.Upgrade/FastGithub.Upgrade.csproj | 1 +
FastGithub.Upgrade/GithubRequestMessage.cs | 17 +++++
FastGithub.Upgrade/ReverseProxyHttpHandler.cs | 46 ------------
FastGithub.Upgrade/UpgradeService.cs | 37 +++++++---
.../UpgradeServiceCollectionExtensions.cs | 1 +
FastGithub.sln | 6 ++
20 files changed, 232 insertions(+), 146 deletions(-)
rename {FastGithub.ReverseProxy => FastGithub.Http}/DomainResolver.cs (98%)
create mode 100644 FastGithub.Http/FastGithub.Http.csproj
create mode 100644 FastGithub.Http/HttpClient.cs
create mode 100644 FastGithub.Http/HttpClientFactory.cs
rename FastGithub.ReverseProxy/HttpClientHanlder.cs => FastGithub.Http/HttpClientHandler.cs (95%)
create mode 100644 FastGithub.Http/HttpClientServiceCollectionExtensions.cs
create mode 100644 FastGithub.Http/IDomainResolver.cs
create mode 100644 FastGithub.Http/IHttpClientFactory.cs
rename {FastGithub.ReverseProxy => FastGithub.Http}/RequestContext.cs (94%)
rename {FastGithub.ReverseProxy => FastGithub.Http}/RequestContextExtensions.cs (97%)
delete mode 100644 FastGithub.ReverseProxy/HttpClientFactory.cs
create mode 100644 FastGithub.Upgrade/GithubRequestMessage.cs
delete mode 100644 FastGithub.Upgrade/ReverseProxyHttpHandler.cs
diff --git a/FastGithub.ReverseProxy/DomainResolver.cs b/FastGithub.Http/DomainResolver.cs
similarity index 98%
rename from FastGithub.ReverseProxy/DomainResolver.cs
rename to FastGithub.Http/DomainResolver.cs
index 2b40391..98bb782 100644
--- a/FastGithub.ReverseProxy/DomainResolver.cs
+++ b/FastGithub.Http/DomainResolver.cs
@@ -8,12 +8,12 @@ using System.Net;
using System.Threading;
using System.Threading.Tasks;
-namespace FastGithub.ReverseProxy
+namespace FastGithub.Http
{
///
/// 域名解析器
///
- sealed class DomainResolver
+ sealed class DomainResolver : IDomainResolver
{
private readonly IMemoryCache memoryCache;
private readonly FastGithubConfig fastGithubConfig;
diff --git a/FastGithub.Http/FastGithub.Http.csproj b/FastGithub.Http/FastGithub.Http.csproj
new file mode 100644
index 0000000..e5cca58
--- /dev/null
+++ b/FastGithub.Http/FastGithub.Http.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net5.0
+
+
+
+
+
+
+
+
+
+
diff --git a/FastGithub.Http/HttpClient.cs b/FastGithub.Http/HttpClient.cs
new file mode 100644
index 0000000..8a8d4c5
--- /dev/null
+++ b/FastGithub.Http/HttpClient.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FastGithub.Http
+{
+ ///
+ /// 表示http客户端
+ ///
+ public class HttpClient : HttpMessageInvoker
+ {
+ private readonly DomainConfig domainConfig;
+
+ ///
+ /// http客户端
+ ///
+ ///
+ ///
+ public HttpClient(DomainConfig domainConfig, IDomainResolver domainResolver)
+ : this(domainConfig, new HttpClientHandler(domainResolver), disposeHandler: true)
+ {
+ this.domainConfig = domainConfig;
+ }
+
+ ///
+ /// http客户端
+ ///
+ ///
+ ///
+ ///
+ internal HttpClient(DomainConfig domainConfig, HttpClientHandler handler, bool disposeHandler)
+ : base(handler, disposeHandler)
+ {
+ this.domainConfig = domainConfig;
+ }
+
+ ///
+ /// 发送数据
+ ///
+ ///
+ ///
+ ///
+ public override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ request.SetRequestContext(new RequestContext
+ {
+ Host = request.RequestUri?.Host,
+ IsHttps = request.RequestUri?.Scheme == Uri.UriSchemeHttps,
+ TlsSniPattern = this.domainConfig.GetTlsSniPattern(),
+ TlsIgnoreNameMismatch = this.domainConfig.TlsIgnoreNameMismatch
+ });
+ return base.SendAsync(request, cancellationToken);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FastGithub.Http/HttpClientFactory.cs b/FastGithub.Http/HttpClientFactory.cs
new file mode 100644
index 0000000..387388e
--- /dev/null
+++ b/FastGithub.Http/HttpClientFactory.cs
@@ -0,0 +1,35 @@
+using Microsoft.Extensions.Options;
+
+namespace FastGithub.Http
+{
+ ///
+ /// HttpClient工厂
+ ///
+ sealed class HttpClientFactory : IHttpClientFactory
+ {
+ private HttpClientHandler httpClientHanlder;
+
+ ///
+ /// HttpClient工厂
+ ///
+ ///
+ ///
+ public HttpClientFactory(
+ IDomainResolver domainResolver,
+ IOptionsMonitor options)
+ {
+ this.httpClientHanlder = new HttpClientHandler(domainResolver);
+ options.OnChange(opt => this.httpClientHanlder = new HttpClientHandler(domainResolver));
+ }
+
+ ///
+ /// 创建httpClient
+ ///
+ ///
+ ///
+ public HttpClient CreateHttpClient(DomainConfig domainConfig)
+ {
+ return new HttpClient(domainConfig, this.httpClientHanlder, disposeHandler: false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/FastGithub.ReverseProxy/HttpClientHanlder.cs b/FastGithub.Http/HttpClientHandler.cs
similarity index 95%
rename from FastGithub.ReverseProxy/HttpClientHanlder.cs
rename to FastGithub.Http/HttpClientHandler.cs
index 9ece290..c493f8a 100644
--- a/FastGithub.ReverseProxy/HttpClientHanlder.cs
+++ b/FastGithub.Http/HttpClientHandler.cs
@@ -9,20 +9,20 @@ using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
-namespace FastGithub.ReverseProxy
+namespace FastGithub.Http
{
///
- /// YARP的HttpClientHandler
+ /// HttpClientHandler
///
- class HttpClientHanlder : DelegatingHandler
+ class HttpClientHandler : DelegatingHandler
{
- private readonly DomainResolver domainResolver;
+ private readonly IDomainResolver domainResolver;
///
- /// YARP的HttpClientHandler
+ /// HttpClientHandler
///
///
- public HttpClientHanlder(DomainResolver domainResolver)
+ public HttpClientHandler(IDomainResolver domainResolver)
{
this.domainResolver = domainResolver;
this.InnerHandler = CreateSocketsHttpHandler();
diff --git a/FastGithub.Http/HttpClientServiceCollectionExtensions.cs b/FastGithub.Http/HttpClientServiceCollectionExtensions.cs
new file mode 100644
index 0000000..6648b3b
--- /dev/null
+++ b/FastGithub.Http/HttpClientServiceCollectionExtensions.cs
@@ -0,0 +1,25 @@
+using FastGithub.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+
+namespace FastGithub
+{
+ ///
+ /// httpClient的服务注册扩展
+ ///
+ public static class HttpClientServiceCollectionExtensions
+ {
+ ///
+ /// 添加HttpClient相关服务
+ ///
+ ///
+ ///
+ public static IServiceCollection AddHttpClient(this IServiceCollection services)
+ {
+ services.AddMemoryCache();
+ services.TryAddSingleton();
+ services.TryAddSingleton();
+ return services;
+ }
+ }
+}
diff --git a/FastGithub.Http/IDomainResolver.cs b/FastGithub.Http/IDomainResolver.cs
new file mode 100644
index 0000000..760e6aa
--- /dev/null
+++ b/FastGithub.Http/IDomainResolver.cs
@@ -0,0 +1,20 @@
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FastGithub.Http
+{
+ ///
+ /// 域名解析器
+ ///
+ public interface IDomainResolver
+ {
+ ///
+ /// 解析域名
+ ///
+ ///
+ ///
+ ///
+ Task ResolveAsync(string domain, CancellationToken cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/FastGithub.Http/IHttpClientFactory.cs b/FastGithub.Http/IHttpClientFactory.cs
new file mode 100644
index 0000000..ce71e74
--- /dev/null
+++ b/FastGithub.Http/IHttpClientFactory.cs
@@ -0,0 +1,15 @@
+namespace FastGithub.Http
+{
+ ///
+ /// httpClient工厂
+ ///
+ public interface IHttpClientFactory
+ {
+ ///
+ /// 创建httpClient
+ ///
+ ///
+ ///
+ HttpClient CreateHttpClient(DomainConfig domainConfig);
+ }
+}
diff --git a/FastGithub.ReverseProxy/RequestContext.cs b/FastGithub.Http/RequestContext.cs
similarity index 94%
rename from FastGithub.ReverseProxy/RequestContext.cs
rename to FastGithub.Http/RequestContext.cs
index 509526a..83a0d41 100644
--- a/FastGithub.ReverseProxy/RequestContext.cs
+++ b/FastGithub.Http/RequestContext.cs
@@ -1,4 +1,4 @@
-namespace FastGithub.ReverseProxy
+namespace FastGithub.Http
{
///
/// 表示请求上下文
diff --git a/FastGithub.ReverseProxy/RequestContextExtensions.cs b/FastGithub.Http/RequestContextExtensions.cs
similarity index 97%
rename from FastGithub.ReverseProxy/RequestContextExtensions.cs
rename to FastGithub.Http/RequestContextExtensions.cs
index 68e6291..5388ca6 100644
--- a/FastGithub.ReverseProxy/RequestContextExtensions.cs
+++ b/FastGithub.Http/RequestContextExtensions.cs
@@ -1,7 +1,7 @@
using System;
using System.Net.Http;
-namespace FastGithub.ReverseProxy
+namespace FastGithub.Http
{
///
/// 请求上下文扩展
diff --git a/FastGithub.ReverseProxy/FastGithub.ReverseProxy.csproj b/FastGithub.ReverseProxy/FastGithub.ReverseProxy.csproj
index 57a0ed9..2a1696b 100644
--- a/FastGithub.ReverseProxy/FastGithub.ReverseProxy.csproj
+++ b/FastGithub.ReverseProxy/FastGithub.ReverseProxy.csproj
@@ -6,13 +6,13 @@
-
+
diff --git a/FastGithub.ReverseProxy/HttpClientFactory.cs b/FastGithub.ReverseProxy/HttpClientFactory.cs
deleted file mode 100644
index 57b66d7..0000000
--- a/FastGithub.ReverseProxy/HttpClientFactory.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using Microsoft.Extensions.Options;
-using System;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace FastGithub.ReverseProxy
-{
- ///
- /// HttpClient工厂
- ///
- sealed class HttpClientFactory
- {
- private HttpClientHanlder httpClientHanlder;
-
- ///
- /// HttpClient工厂
- ///
- ///
- ///
- public HttpClientFactory(
- DomainResolver domainResolver,
- IOptionsMonitor options)
- {
- this.httpClientHanlder = new HttpClientHanlder(domainResolver);
- options.OnChange(opt => this.httpClientHanlder = new HttpClientHanlder(domainResolver));
- }
-
- ///
- /// 创建httpClient
- ///
- ///
- ///
- public HttpMessageInvoker CreateHttpClient(DomainConfig domainConfig)
- {
- return new HttpClient(this.httpClientHanlder, domainConfig, disposeHandler: false);
- }
-
- ///
- /// http客户端
- ///
- private class HttpClient : HttpMessageInvoker
- {
- private readonly DomainConfig domainConfig;
-
- public HttpClient(
- HttpMessageHandler handler,
- DomainConfig domainConfig,
- bool disposeHandler = false) : base(handler, disposeHandler)
- {
- this.domainConfig = domainConfig;
- }
-
- ///
- /// 发送数据
- ///
- ///
- ///
- ///
- public override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
- {
- request.SetRequestContext(new RequestContext
- {
- Host = request.RequestUri?.Host,
- IsHttps = request.RequestUri?.Scheme == Uri.UriSchemeHttps,
- TlsSniPattern = this.domainConfig.GetTlsSniPattern(),
- TlsIgnoreNameMismatch = this.domainConfig.TlsIgnoreNameMismatch
- });
- return base.SendAsync(request, cancellationToken);
- }
- }
- }
-}
diff --git a/FastGithub.ReverseProxy/ReverseProxyMiddleware.cs b/FastGithub.ReverseProxy/ReverseProxyMiddleware.cs
index 7b28119..88008c0 100644
--- a/FastGithub.ReverseProxy/ReverseProxyMiddleware.cs
+++ b/FastGithub.ReverseProxy/ReverseProxyMiddleware.cs
@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Http;
+using FastGithub.Http;
+using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
@@ -12,13 +13,13 @@ namespace FastGithub.ReverseProxy
sealed class ReverseProxyMiddleware
{
private readonly IHttpForwarder httpForwarder;
- private readonly HttpClientFactory httpClientFactory;
+ private readonly IHttpClientFactory httpClientFactory;
private readonly FastGithubConfig fastGithubConfig;
private readonly ILogger logger;
public ReverseProxyMiddleware(
IHttpForwarder httpForwarder,
- HttpClientFactory httpClientFactory,
+ IHttpClientFactory httpClientFactory,
FastGithubConfig fastGithubConfig,
ILogger logger)
{
diff --git a/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs b/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs
index 3ec02e4..b027f57 100644
--- a/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs
+++ b/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs
@@ -18,8 +18,7 @@ namespace FastGithub
return services
.AddMemoryCache()
.AddHttpForwarder()
- .AddSingleton()
- .AddTransient()
+ .AddHttpClient()
.AddSingleton()
.AddSingleton();
}
diff --git a/FastGithub.Upgrade/FastGithub.Upgrade.csproj b/FastGithub.Upgrade/FastGithub.Upgrade.csproj
index a870eac..c3cc728 100644
--- a/FastGithub.Upgrade/FastGithub.Upgrade.csproj
+++ b/FastGithub.Upgrade/FastGithub.Upgrade.csproj
@@ -10,6 +10,7 @@
+
diff --git a/FastGithub.Upgrade/GithubRequestMessage.cs b/FastGithub.Upgrade/GithubRequestMessage.cs
new file mode 100644
index 0000000..8428d5b
--- /dev/null
+++ b/FastGithub.Upgrade/GithubRequestMessage.cs
@@ -0,0 +1,17 @@
+using System.Net.Http;
+using System.Net.Http.Headers;
+
+namespace FastGithub.Upgrade
+{
+ ///
+ /// github请求消息
+ ///
+ class GithubRequestMessage : HttpRequestMessage
+ {
+ public GithubRequestMessage()
+ {
+ this.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
+ this.Headers.UserAgent.Add(new ProductInfoHeaderValue(nameof(FastGithub), "1.0"));
+ }
+ }
+}
diff --git a/FastGithub.Upgrade/ReverseProxyHttpHandler.cs b/FastGithub.Upgrade/ReverseProxyHttpHandler.cs
deleted file mode 100644
index 60b0e5d..0000000
--- a/FastGithub.Upgrade/ReverseProxyHttpHandler.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace FastGithub.Upgrade
-{
- ///
- /// 本机反向代理的httpHandler
- ///
- sealed class ReverseProxyHttpHandler : DelegatingHandler
- {
- ///
- /// 本机反向代理的httpHandler
- ///
- public ReverseProxyHttpHandler()
- {
- this.InnerHandler = new HttpClientHandler
- {
- ServerCertificateCustomValidationCallback = delegate { return true; }
- };
- }
-
- ///
- /// 替换为Loopback
- ///
- ///
- ///
- ///
- protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
- {
- var uri = request.RequestUri;
- if (uri != null && uri.HostNameType == UriHostNameType.Dns)
- {
- var domain = uri.Host;
- var builder = new UriBuilder(uri) { Host = IPAddress.Loopback.ToString() };
-
- request.RequestUri = builder.Uri;
- request.Headers.Host = domain;
- }
-
- return await base.SendAsync(request, cancellationToken);
- }
- }
-}
diff --git a/FastGithub.Upgrade/UpgradeService.cs b/FastGithub.Upgrade/UpgradeService.cs
index 94c54b3..35813ff 100644
--- a/FastGithub.Upgrade/UpgradeService.cs
+++ b/FastGithub.Upgrade/UpgradeService.cs
@@ -1,8 +1,7 @@
-using Microsoft.Extensions.Logging;
+using FastGithub.Http;
+using Microsoft.Extensions.Logging;
using System;
using System.Linq;
-using System.Net.Http;
-using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Threading;
using System.Threading.Tasks;
@@ -14,15 +13,20 @@ namespace FastGithub.Upgrade
///
sealed class UpgradeService
{
+ private readonly IDomainResolver domainResolver;
private readonly ILogger logger;
- private const string ReleasesUri = "https://api.github.com/repos/xljiulang/fastgithub/releases";
+ private readonly Uri releasesUri = new("https://api.github.com/repos/xljiulang/fastgithub/releases");
///
/// 升级服务
///
+ ///
///
- public UpgradeService(ILogger logger)
+ public UpgradeService(
+ IDomainResolver domainResolver,
+ ILogger logger)
{
+ this.domainResolver = domainResolver;
this.logger = logger;
}
@@ -48,9 +52,13 @@ namespace FastGithub.Upgrade
var lastedVersion = lastRelease.GetProductionVersion();
if (lastedVersion.CompareTo(currentVersion) > 0)
{
- this.logger.LogInformation($"您正在使用{currentVersion}版本{Environment.NewLine}请前往{lastRelease.HtmlUrl}下载新版本");
+ this.logger.LogInformation($"当前版本{currentVersion}为老版本{Environment.NewLine}请前往{lastRelease.HtmlUrl}下载新版本");
this.logger.LogInformation(lastRelease.ToString());
}
+ else
+ {
+ this.logger.LogInformation($"当前版本{currentVersion}为最新版本");
+ }
}
///
@@ -59,14 +67,21 @@ namespace FastGithub.Upgrade
///
public async Task GetLastedReleaseAsync(CancellationToken cancellationToken)
{
- using var httpClient = new HttpClient(new ReverseProxyHttpHandler())
+ var domainConfig = new DomainConfig
{
- Timeout = TimeSpan.FromSeconds(30d),
+ TlsSni = false,
+ TlsIgnoreNameMismatch = true,
+ Timeout = TimeSpan.FromSeconds(30d)
};
- httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
- httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(nameof(FastGithub), "1.0"));
- var releases = await httpClient.GetFromJsonAsync(ReleasesUri, cancellationToken);
+ using var request = new GithubRequestMessage
+ {
+ RequestUri = this.releasesUri
+ };
+
+ using var httpClient = new HttpClient(domainConfig, this.domainResolver);
+ var response = await httpClient.SendAsync(request, cancellationToken);
+ var releases = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken);
return releases?.FirstOrDefault(item => item.Prerelease == false);
}
}
diff --git a/FastGithub.Upgrade/UpgradeServiceCollectionExtensions.cs b/FastGithub.Upgrade/UpgradeServiceCollectionExtensions.cs
index a3fd0ec..600fd9b 100644
--- a/FastGithub.Upgrade/UpgradeServiceCollectionExtensions.cs
+++ b/FastGithub.Upgrade/UpgradeServiceCollectionExtensions.cs
@@ -16,6 +16,7 @@ namespace FastGithub
public static IServiceCollection AddAppUpgrade(this IServiceCollection services)
{
return services
+ .AddHttpClient()
.AddSingleton()
.AddHostedService();
}
diff --git a/FastGithub.sln b/FastGithub.sln
index 3d702f8..24bdbd6 100644
--- a/FastGithub.sln
+++ b/FastGithub.sln
@@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGithub.ReverseProxy", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGithub.DnscryptProxy", "FastGithub.DnscryptProxy\FastGithub.DnscryptProxy.csproj", "{26BB826F-4117-4746-9BD0-C6D8043E2808}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGithub.Http", "FastGithub.Http\FastGithub.Http.csproj", "{B5DCB3E4-5094-4170-B844-6F395002CA42}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
{26BB826F-4117-4746-9BD0-C6D8043E2808}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26BB826F-4117-4746-9BD0-C6D8043E2808}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26BB826F-4117-4746-9BD0-C6D8043E2808}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B5DCB3E4-5094-4170-B844-6F395002CA42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B5DCB3E4-5094-4170-B844-6F395002CA42}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B5DCB3E4-5094-4170-B844-6F395002CA42}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B5DCB3E4-5094-4170-B844-6F395002CA42}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE