Browse Source

添加项目文件。

develop
H Vs 1 year ago
parent
commit
6c509e64cb
20 changed files with 670 additions and 0 deletions
  1. +9
    -0
      .gitignore
  2. +7
    -0
      HealthMonitor.Common/Class1.cs
  3. +22
    -0
      HealthMonitor.Common/Consts.cs
  4. +37
    -0
      HealthMonitor.Common/CustomizeStopWatch.cs
  5. +14
    -0
      HealthMonitor.Common/HealthMonitor.Common.csproj
  6. +129
    -0
      HealthMonitor.Common/helper/HttpHelper.cs
  7. +7
    -0
      HealthMonitor.Model/Class1.cs
  8. +23
    -0
      HealthMonitor.Model/Config/TDengineServiceConfig.cs
  9. +9
    -0
      HealthMonitor.Model/HealthMonitor.Model.csproj
  10. +148
    -0
      HealthMonitor.Service/Biz/db/TDengineService.cs
  11. +7
    -0
      HealthMonitor.Service/Class1.cs
  12. +19
    -0
      HealthMonitor.Service/HealthMonitor.Service.csproj
  13. +57
    -0
      HealthMonitor.WebApi/Controllers/WeatherForecastController.cs
  14. +19
    -0
      HealthMonitor.WebApi/HealthMonitor.WebApi.csproj
  15. +51
    -0
      HealthMonitor.WebApi/Program.cs
  16. +31
    -0
      HealthMonitor.WebApi/Properties/launchSettings.json
  17. +13
    -0
      HealthMonitor.WebApi/WeatherForecast.cs
  18. +16
    -0
      HealthMonitor.WebApi/appsettings.Development.json
  19. +9
    -0
      HealthMonitor.WebApi/appsettings.json
  20. +43
    -0
      HealthMonitor.sln

+ 9
- 0
.gitignore View File

@@ -0,0 +1,9 @@
*.user
*.suo
.vs/
*.log
obj/
bin/
.idea/
.vscode/
publish/

+ 7
- 0
HealthMonitor.Common/Class1.cs View File

@@ -0,0 +1,7 @@
namespace HealthMonitor.Common
{
public class Class1
{

}
}

+ 22
- 0
HealthMonitor.Common/Consts.cs View File

@@ -0,0 +1,22 @@
using System;

namespace HealthMonitor.Common
{
public class Consts
{
/// <summary>
/// HttpClient常用配置分组名称
/// </summary>
public const string DEFAULT_HTTPCLIENT_NAME = "DEFAULT_HTTP";

/// <summary>
/// 纪元时间(UTC时间戳起始计算时间)
/// </summary>
public static DateTime EraUtcTime = DateTime.Parse("1970/01/01");

/// <summary>
/// 有效定位的半径阈值(大于该值则为无效定位)
/// </summary>
public static int RadiusThreshold = 150;
}
}

+ 37
- 0
HealthMonitor.Common/CustomizeStopWatch.cs View File

@@ -0,0 +1,37 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HealthMonitor.Common
{
public class CustomizeStopWatch : IDisposable
{
private readonly Stopwatch _sw;
private readonly string _domain;
private readonly ILogger _logger;

public string Content { get; set; } = default!;

public CustomizeStopWatch(string domain, ILogger logger)
{
_domain = domain;
_logger = logger;

_sw = new Stopwatch();
_sw.Start();
}

public void Dispose()
{
if (_sw != null)
{
_logger.LogInformation($"统计时间[{_domain}],耗时 {_sw.Elapsed.TotalMilliseconds} 毫秒 {Content}");
_sw.Stop();
}
}
}
}

+ 14
- 0
HealthMonitor.Common/HealthMonitor.Common.csproj View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

</Project>

+ 129
- 0
HealthMonitor.Common/helper/HttpHelper.cs View File

@@ -0,0 +1,129 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace HealthMonitor.Common.helper
{

public class HttpHelper
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<HttpHelper> _logger;

public HttpHelper(IHttpClientFactory httpClientFactory, ILogger<HttpHelper> logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult!);
}


public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
}

public async Task<string?> HttpToGetAsync(string url)
{
return await HttpToGetAsync(url, new List<KeyValuePair<string, string>>());
}

public async Task<string?> HttpToGetAsync(string url, List<KeyValuePair<string, string>> headers)
{
var client = _httpClientFactory.CreateClient(Consts.DEFAULT_HTTPCLIENT_NAME);
if (headers != null && headers.Count > 0) //指定请求头
{
headers.ForEach(e =>
{
client.DefaultRequestHeaders.Add(e.Key, e.Value);
});
}

try
{
using (var response = await client.GetAsync(url).ConfigureAwait(false))
{
if (!response.IsSuccessStatusCode) return null;
else
{
var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return result;
}
}
}
catch (Exception ex)
{
_logger.LogError($"HttpToGetAsync发生异常, Msg:{ex.Message}\n{ex.StackTrace}");
return null;
}
}

public async Task<string?> HttpToPostAsync(string url, object data)
{
return await HttpToPostAsync(url, data, new List<KeyValuePair<string, string>>());
}

public async Task<string?> HttpToPostAsync(string url, object data, List<KeyValuePair<string, string>> headers)
{
if (data == null) return null;
var client = _httpClientFactory.CreateClient(Consts.DEFAULT_HTTPCLIENT_NAME);
if (headers != null && headers.Count > 0) //指定请求头
{
headers.ForEach(e =>
{
client.DefaultRequestHeaders.Add(e.Key, e.Value);
});

}

string? body;
if (data is string) body = data as string;
else body = JsonConvert.SerializeObject(data);

try
{
using (var content = new StringContent(body!))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var response = await client.PostAsync(url, content).ConfigureAwait(false))
{
if (!response.IsSuccessStatusCode) return null;
else
{
var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return result;
}
}
}
}
catch (Exception ex)
{
_logger.LogError($"HttpToPostAsync发生异常, Msg:{ex.Message}\n{ex.StackTrace}");
return null;
}
}
/// <summary>
/// Authorization 的 Base64 加密
/// </summary>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns></returns>
public string GetEncodedCredentials(string username, string password)
{
string mergedCredentials = string.Format("{0}:{1}", username, password);
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
return Convert.ToBase64String(byteCredentials);
}
}
}

+ 7
- 0
HealthMonitor.Model/Class1.cs View File

@@ -0,0 +1,7 @@
namespace HealthMonitor.Model
{
public class Class1
{

}
}

+ 23
- 0
HealthMonitor.Model/Config/TDengineServiceConfig.cs View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HealthMonitor.Model.Config
{
public class TDengineServiceConfig
{
public string Host { get; set; } = default!;

public string UserName { get; set; } = default!;

public string Password { get; set; } = default!;

public short Port { get; set; } = default!;

public string DB { get; set; } = default!;


}
}

+ 9
- 0
HealthMonitor.Model/HealthMonitor.Model.csproj View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>

+ 148
- 0
HealthMonitor.Service/Biz/db/TDengineService.cs View File

@@ -0,0 +1,148 @@
using HealthMonitor.Model.Config;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TDengineDriver;
using TDengineDriver.Impl;

namespace HealthMonitor.Service.Biz.db
{
public class TDengineService
{

private readonly ILogger<TDengineService> _logger;
private readonly TDengineServiceConfig _configTDengineService;
public TDengineService(ILogger<TDengineService> logger, IOptions<TDengineServiceConfig> configTDengineService)
{
_logger = logger;
_configTDengineService = configTDengineService.Value;
}
public IntPtr Connection()
{

string host = _configTDengineService.Host;
string user = _configTDengineService.UserName;
string db = _configTDengineService.DB;
short port = _configTDengineService.Port;
string password = _configTDengineService.Password;
IntPtr conn = TDengine.Connect(host, user, password, db, port);

//string host = "172.16.255.180";
//short port = 6030;
//string user = "root";
//string password = "taosdata";
//string db = "health_monitor";

//IntPtr conn = TDengine.Connect(host, user, password, db, port);
// Check if get connection success
if (conn == IntPtr.Zero)
{
Console.WriteLine("Connect to TDengine failed");
}
else
{
Console.WriteLine("Connect to TDengine success");
}
return conn;
}
public void ExecuteSQL(IntPtr conn, string sql)
{
IntPtr res = TDengine.Query(conn, sql);
// Check if query success
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql + " failure, ");
// Get error message while Res is a not null pointer.
if (res != IntPtr.Zero)
{
Console.Write("reason:" + TDengine.Error(res));
}
}
else
{
Console.Write(sql + " success, {0} rows affected", TDengine.AffectRows(res));
//... do something with res ...

// Important: need to free result to avoid memory leak.
TDengine.FreeResult(res);
}
}

public void ExecuteQuerySQL(IntPtr conn, string sql)
{
IntPtr res = TDengine.Query(conn, sql);
// Check if query success
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql + " failure, ");
// Get error message while Res is a not null pointer.
if (res != IntPtr.Zero)
{
Console.Write("reason:" + TDengine.Error(res));
}
}
else
{
Console.Write(sql + " success, {0} rows affected", TDengine.AffectRows(res));
//... do something with res ...

List<TDengineDriver.TDengineMeta> resMeta = LibTaos.GetMeta(res);
List<Object> resData = LibTaos.GetData(res);

foreach (var meta in resMeta)
{
Console.Write($"\t|{meta.name} {meta.TypeName()} ({meta.size})\t|");
}

for (int i = 0; i < resData.Count; i++)
{
Console.Write($"|{resData[i].ToString()} \t");
//Console.WriteLine("{0},{1},{2}", i, resMeta.Count, (i) % resMeta.Count);
if (((i + 1) % resMeta.Count == 0))
{
Console.WriteLine("");
}
}

// Important: need to free result to avoid memory leak.
TDengine.FreeResult(res);
}
}


public void CheckRes(IntPtr conn, IntPtr res, String errorMsg)
{
if (TDengine.ErrorNo(res) != 0)
{
throw new Exception($"{errorMsg} since: {TDengine.Error(res)}");
}
}


public void ExecuteInsertSQL(IntPtr conn, string sql)
{
try
{
//sql = "INSERT INTO d1001 USING meters TAGS('California.SanFrancisco', 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) " +
// "d1002 USING power.meters TAGS('California.SanFrancisco', 3) VALUES('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) " +
// "d1003 USING power.meters TAGS('California.LosAngeles', 2) VALUES('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000)('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000) " +
// "d1004 USING power.meters TAGS('California.LosAngeles', 3) VALUES('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000)('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)";
IntPtr res = TDengine.Query(conn, sql);
CheckRes(conn, res, "failed to insert data");
int affectedRows = TDengine.AffectRows(res);
Console.WriteLine("affectedRows " + affectedRows);
TDengine.FreeResult(res);
}
finally
{
TDengine.Close(conn);
}
}


}
}

+ 7
- 0
HealthMonitor.Service/Class1.cs View File

@@ -0,0 +1,7 @@
namespace HealthMonitor.Service
{
public class Class1
{

}
}

+ 19
- 0
HealthMonitor.Service/HealthMonitor.Service.csproj View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
<PackageReference Include="TDengine.Connector" Version="3.0.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\HealthMonitor.Model\HealthMonitor.Model.csproj" />
</ItemGroup>

</Project>

+ 57
- 0
HealthMonitor.WebApi/Controllers/WeatherForecastController.cs View File

@@ -0,0 +1,57 @@
using HealthMonitor.Service.Biz.db;
using Microsoft.AspNetCore.Mvc;

namespace HealthMonitor.WebApi.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

private readonly ILogger<WeatherForecastController> _logger;

private readonly TDengineService _serviceTDengine;

public WeatherForecastController(ILogger<WeatherForecastController> logger, TDengineService serviceDengine)
{
_logger = logger;
_serviceTDengine = serviceDengine;
}

//[HttpGet(Name = "GetWeatherForecast")]
//public IEnumerable<WeatherForecast> Get()
//{
// return Enumerable.Range(1, 5).Select(index => new WeatherForecast
// {
// Date = DateTime.Now.AddDays(index),
// TemperatureC = Random.Shared.Next(-20, 55),
// Summary = Summaries[Random.Shared.Next(Summaries.Length)]
// })
// .ToArray();
//}

[HttpGet(Name = "GetWeatherForecast")]
public async Task<IActionResult> Get()
{
IntPtr conn = _serviceTDengine.Connection();
var sql = "select * from gps_bloodpress";
//Task.Factory.StartNew(async () =>
//{
// await _serviceTDengine.ExecuteQuerySQL(conn, sql);
//});

_serviceTDengine.ExecuteQuerySQL(conn, sql);



//var res= await _serviceAliIot.QueryDeviceStatisticseAsync(nameof(Get));
//var online = res?.OnlineCount;
return Ok("aa");

}
}
}

+ 19
- 0
HealthMonitor.WebApi/HealthMonitor.WebApi.csproj View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\HealthMonitor.Common\HealthMonitor.Common.csproj" />
<ProjectReference Include="..\HealthMonitor.Model\HealthMonitor.Model.csproj" />
<ProjectReference Include="..\HealthMonitor.Service\HealthMonitor.Service.csproj" />
</ItemGroup>

</Project>

+ 51
- 0
HealthMonitor.WebApi/Program.cs View File

@@ -0,0 +1,51 @@
using HealthMonitor.Common;
using HealthMonitor.Common.helper;
using HealthMonitor.Model.Config;
using HealthMonitor.Service.Biz.db;

namespace HealthMonitor.WebApi
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddHttpClient(Consts.DEFAULT_HTTPCLIENT_NAME, c =>
{
c.Timeout = TimeSpan.FromSeconds(10); //³¬Ê±ÏÞÖÆ
c.DefaultRequestHeaders.Add("Accept", "application/json");
//c.DefaultRequestHeaders.Connection.Add("keep-alive");
});

builder.Services.Configure<TDengineServiceConfig>(builder.Configuration.GetSection("TDengineServiceConfig"));

builder.Services.AddSingleton<HttpHelper>();
builder.Services.AddSingleton<TDengineService>();

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();


app.MapControllers();

app.Run();
}
}
}

+ 31
- 0
HealthMonitor.WebApi/Properties/launchSettings.json View File

@@ -0,0 +1,31 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:44512",
"sslPort": 44381
}
},
"profiles": {
"HealthMonitor.WebApi": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7149;http://localhost:5083",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

+ 13
- 0
HealthMonitor.WebApi/WeatherForecast.cs View File

@@ -0,0 +1,13 @@
namespace HealthMonitor.WebApi
{
public class WeatherForecast
{
public DateTime Date { get; set; }

public int TemperatureC { get; set; }

public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

public string? Summary { get; set; }
}
}

+ 16
- 0
HealthMonitor.WebApi/appsettings.Development.json View File

@@ -0,0 +1,16 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"TDengineServiceConfig": {
"Host": "47.116.142.20",
"UserName": "root",
"Password": "taosdata",
"Port": 6030,
"DB": "health_monitor"
}

}

+ 9
- 0
HealthMonitor.WebApi/appsettings.json View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

+ 43
- 0
HealthMonitor.sln View File

@@ -0,0 +1,43 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthMonitor.WebApi", "HealthMonitor.WebApi\HealthMonitor.WebApi.csproj", "{9E002515-7C55-4B0E-A193-2991626539DF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthMonitor.Common", "HealthMonitor.Common\HealthMonitor.Common.csproj", "{BCEC4A3D-10B0-441D-B523-D7D5ECF5BBD8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthMonitor.Model", "HealthMonitor.Model\HealthMonitor.Model.csproj", "{D02C5E59-99CD-4842-A675-FA58124E0405}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HealthMonitor.Service", "HealthMonitor.Service\HealthMonitor.Service.csproj", "{52135FAB-BB8B-417B-8714-7B8521E8FF38}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9E002515-7C55-4B0E-A193-2991626539DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E002515-7C55-4B0E-A193-2991626539DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E002515-7C55-4B0E-A193-2991626539DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E002515-7C55-4B0E-A193-2991626539DF}.Release|Any CPU.Build.0 = Release|Any CPU
{BCEC4A3D-10B0-441D-B523-D7D5ECF5BBD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BCEC4A3D-10B0-441D-B523-D7D5ECF5BBD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BCEC4A3D-10B0-441D-B523-D7D5ECF5BBD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BCEC4A3D-10B0-441D-B523-D7D5ECF5BBD8}.Release|Any CPU.Build.0 = Release|Any CPU
{D02C5E59-99CD-4842-A675-FA58124E0405}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D02C5E59-99CD-4842-A675-FA58124E0405}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D02C5E59-99CD-4842-A675-FA58124E0405}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D02C5E59-99CD-4842-A675-FA58124E0405}.Release|Any CPU.Build.0 = Release|Any CPU
{52135FAB-BB8B-417B-8714-7B8521E8FF38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52135FAB-BB8B-417B-8714-7B8521E8FF38}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52135FAB-BB8B-417B-8714-7B8521E8FF38}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52135FAB-BB8B-417B-8714-7B8521E8FF38}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8BD2A1C6-360A-43B0-866E-D9EF81686192}
EndGlobalSection
EndGlobal

Loading…
Cancel
Save