mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-26 20:20:14 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a5f8db69f | ||
|
|
3d3d126c64 | ||
|
|
8e32b428bd | ||
|
|
8193c6267a | ||
|
|
c845601863 | ||
|
|
1309d63389 | ||
|
|
fff5c293c8 | ||
|
|
e9136e7245 | ||
|
|
66b47e9042 | ||
|
|
5144b1d1b0 | ||
|
|
8213f8a776 | ||
|
|
799185d870 | ||
|
|
4796bc0b71 | ||
|
|
a5c49c470b | ||
|
|
c3affdde7e | ||
|
|
066cfa66c5 | ||
|
|
b89430e4cf | ||
|
|
729c7373fd | ||
|
|
6f843c3939 | ||
|
|
64099cf274 | ||
|
|
a33acc16b6 | ||
|
|
90d0291640 | ||
|
|
fa45e92d2f | ||
|
|
7aedb5dcef | ||
|
|
5509004c64 | ||
|
|
40b46966dc | ||
|
|
f2a3d9cab1 | ||
|
|
b68e4e062e | ||
|
|
4f9e6591dc | ||
|
|
b9e03e7ed1 | ||
|
|
b7606b2ec0 | ||
|
|
de01020f8b | ||
|
|
b9742c0514 | ||
|
|
4e1830bd75 | ||
|
|
d6bbb1bd3d | ||
|
|
22dd40d43b | ||
|
|
1d09ed185d | ||
|
|
81467c0a4f | ||
|
|
79982d7ee9 | ||
|
|
c97171cebb | ||
|
|
db66950499 | ||
|
|
8bbfd1dbc3 | ||
|
|
c9ae6f4fdf | ||
|
|
157319b69e | ||
|
|
456f9c13f5 | ||
|
|
055fe2a4d7 | ||
|
|
15c6f575bc | ||
|
|
5b5e5b031a | ||
|
|
faa981eb87 | ||
|
|
648300328c | ||
|
|
57d1c62770 | ||
|
|
14b1e19246 | ||
|
|
5478e1a31e | ||
|
|
a81f1d54f1 | ||
|
|
f9542f87b7 | ||
|
|
a7ce44495a | ||
|
|
d5650f77df | ||
|
|
0041ea7c23 | ||
|
|
dab382441f | ||
|
|
28fc2ee466 | ||
|
|
fe056c8e27 | ||
|
|
cbd2575ad5 | ||
|
|
04c2276c73 | ||
|
|
ea9ee6bda3 | ||
|
|
a0c7d26ee7 | ||
|
|
9002127836 | ||
|
|
42457873ee | ||
|
|
884b2f7244 | ||
|
|
4bedc0f702 | ||
|
|
505ef59c23 | ||
|
|
b1c41f9421 | ||
|
|
07385d0040 | ||
|
|
c9000b1653 | ||
|
|
09bd0f6b5b | ||
|
|
6a90230dbb | ||
|
|
ec70128239 | ||
|
|
f2048bc3e5 | ||
|
|
9000c3bf2a | ||
|
|
3725f9b62f | ||
|
|
2c92e3e6f8 | ||
|
|
f78271c2f5 | ||
|
|
f2bdc19d74 | ||
|
|
0fde0eccba | ||
|
|
5c55fa97e7 | ||
|
|
323c7eb6c3 | ||
|
|
42dea46260 | ||
|
|
1bf65820c0 | ||
|
|
ba1c5b6c8b | ||
|
|
deb6c4eaa1 | ||
|
|
af337a8fbd | ||
|
|
80d14c6c24 | ||
|
|
07d82be4c7 | ||
|
|
1e261f1125 | ||
|
|
8a1bde0773 | ||
|
|
617b99c39d | ||
|
|
8b4680fcee | ||
|
|
e27ae2b202 | ||
|
|
5419530031 | ||
|
|
415fd30cc5 | ||
|
|
ef627692ef | ||
|
|
6f28ce0993 | ||
|
|
2dbb13db87 | ||
|
|
40d3c0e669 | ||
|
|
6be424dc5f | ||
|
|
6babd615cd | ||
|
|
d1f266465b | ||
|
|
fccd8da9f6 | ||
|
|
df2f84ff99 | ||
|
|
d0bfbdbc77 | ||
|
|
51e19bae95 | ||
|
|
5673bf2150 | ||
|
|
f5c66a353e | ||
|
|
09dd6fe47e | ||
|
|
96471ccf27 | ||
|
|
7b3f40da3b | ||
|
|
e369c6aa10 | ||
|
|
5b4fcc2b8b | ||
|
|
33c6f0d5f9 | ||
|
|
6abdb6dc11 | ||
|
|
a981d31ec4 | ||
|
|
8a0dd49e39 | ||
|
|
dc005a1a47 | ||
|
|
5d69679073 | ||
|
|
1030e15d8e | ||
|
|
48083a90d2 | ||
|
|
aab89668a9 | ||
|
|
a4a6f0e61d | ||
|
|
a103ec141b | ||
|
|
c23dc29e1c | ||
|
|
ddda4c0273 | ||
|
|
cd1c1b91d7 | ||
|
|
ce09385a52 | ||
|
|
8d6e83a42b | ||
|
|
b0a72ab23a | ||
|
|
b5f8910e2e | ||
|
|
881ff3fba9 | ||
|
|
8878d183a7 | ||
|
|
46f95574d1 |
@@ -8,10 +8,10 @@ assignees: ''
|
||||
---
|
||||
|
||||
<!--
|
||||
发布前请先尝试在 Issuse 内搜索一下你的问题是否已经被提出过,
|
||||
发布前请先尝试在 Issues 内搜索一下你的问题是否已经被提出过,
|
||||
详细地描述 bug,让大家都能理解,请一定确定你所要发布的内容是一个 Bug,如果不确定请发 Question
|
||||
别忘了填写标题,标题要简短的描述问题
|
||||
Before posting, please try searching in Issuse to see if your question has already been asked,
|
||||
Before posting, please try searching in Issues to see if your question has already been asked,
|
||||
Describe the bug in detail so that everyone can understand it
|
||||
Don't forget to fill in the title, which should briefly describe the problem
|
||||
-->
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET 6
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3.0.2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET 6
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3.0.2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
@@ -321,7 +321,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET 6
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3.0.2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET 6
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3.0.2
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
# xcode-version: '12.x' # set the latest available Xcode 12
|
||||
|
||||
- name: Setup Android NDK
|
||||
uses: nttld/setup-ndk@v1.0.6
|
||||
uses: nttld/setup-ndk@v1.2.0
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r21e
|
||||
|
||||
+86
-79
@@ -5,18 +5,18 @@
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.7" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.10" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) Or $(TargetFramework.StartsWith('netcoreapp3.1'))">
|
||||
<!-- Microsoft.Extensions.* & AspNetCore & EntityFrameworkCore(NETCOREAPP31) -->
|
||||
@@ -24,7 +24,7 @@
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="3.1.27" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="3.1.27" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.27" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.1.27" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="3.1.27" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.27" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="3.1.27" />
|
||||
@@ -40,12 +40,12 @@
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('net6.0')) ">
|
||||
<!-- Entity Framework Plus -->
|
||||
<!-- A FREE & Open Source library to enhance EF6 and EF Core -->
|
||||
<PackageVersion Include="Z.EntityFramework.Plus.EFCore" Version="6.14.3" />
|
||||
<PackageVersion Include="Z.EntityFramework.Plus.EFCore" Version="6.15.2" />
|
||||
|
||||
<!-- AspNetCore 6 OpenId/OAuth -->
|
||||
<PackageVersion Include="AspNet.Security.OpenId.Steam" Version="6.0.0" />
|
||||
<PackageVersion Include="AspNet.Security.OAuth.QQ" Version="6.0.6" />
|
||||
<PackageVersion Include="AspNet.Security.OAuth.Apple" Version="6.0.6" />
|
||||
<PackageVersion Include="AspNet.Security.OAuth.QQ" Version="6.0.12" />
|
||||
<PackageVersion Include="AspNet.Security.OAuth.Apple" Version="6.0.12" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
</ItemGroup>
|
||||
@@ -74,22 +74,23 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- Microsoft.* -->
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<!--<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="1.4.1" />-->
|
||||
<!--<PackageVersion Include="Microsoft.Windows.SDK.NET.Ref" Version="10.0.19041.22" />-->
|
||||
<!--<PackageVersion Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.1" />-->
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.1" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="6.0.0" />
|
||||
<PackageVersion Include="Microsoft.Net.Http.Headers" Version="2.2.255.255" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||
<!--<PackageVersion Include="CommunityToolkit.Mvvm" Version="7.1.2" />-->
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Net.Http.WinHttpHandler" Version="6.0.1" />
|
||||
|
||||
|
||||
<!-- AppCenter.* -->
|
||||
<PackageVersion Include="Microsoft.AppCenter" Version="4.5.3" />
|
||||
<PackageVersion Include="Microsoft.AppCenter.Analytics" Version="4.5.3" />
|
||||
<PackageVersion Include="Microsoft.AppCenter.Crashes" Version="4.5.3" />
|
||||
<PackageVersion Include="Microsoft.AppCenter" Version="5.0.1" />
|
||||
<PackageVersion Include="Microsoft.AppCenter.Analytics" Version="5.0.1" />
|
||||
<PackageVersion Include="Microsoft.AppCenter.Crashes" Version="5.0.1" />
|
||||
<PackageVersion Include="Aigio.Avalonia.AppCenter" Version="4.5.3" />
|
||||
<PackageVersion Include="Aigio.Avalonia.AppCenter.Analytics" Version="4.5.3" />
|
||||
<PackageVersion Include="Aigio.Avalonia.AppCenter.Crashes" Version="4.5.3" />
|
||||
@@ -107,43 +108,44 @@
|
||||
<PackageVersion Include="Xamarin.Forms" Version="5.0.0.2478" />
|
||||
<PackageVersion Include="Xamarin.Forms.Visual.Material" Version="5.0.0.2478" />
|
||||
<PackageVersion Include="Xam.Plugins.Forms.ImageCircle" Version="3.1.1.1-beta" />
|
||||
|
||||
|
||||
<!-- NUnit & NUnit.Xamarin & Moq -->
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.3.1" />
|
||||
<PackageVersion Include="nunit.xamarin" Version="3.6.1" />
|
||||
<PackageVersion Include="PCLStorage" Version="1.0.2" />
|
||||
<PackageVersion Include="Moq" Version="4.18.1" />
|
||||
<PackageVersion Include="Moq" Version="4.18.3" />
|
||||
|
||||
<!-- NLog -->
|
||||
<PackageVersion Include="NLog" Version="5.0.1" />
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.0.1" />
|
||||
<PackageVersion Include="NLog.Web.AspNetCore" Version="5.1.0" />
|
||||
<PackageVersion Include="NLog" Version="5.1.0" />
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.2.0" />
|
||||
<PackageVersion Include="NLog.Web.AspNetCore" Version="5.2.0" />
|
||||
<PackageVersion Include="AspNetCore2.NETStandard.NLog.Web.AspNetCore" Version="5.0.0" />
|
||||
|
||||
<!-- ReactiveUI -->
|
||||
<PackageVersion Include="System.Reactive" Version="5.0.0" />
|
||||
<PackageVersion Include="Splat" Version="14.4.1" />
|
||||
<PackageVersion Include="DynamicData" Version="7.9.7" />
|
||||
<PackageVersion Include="ReactiveUI" Version="18.3.1" />
|
||||
<PackageVersion Include="ReactiveUI.Fody" Version="18.3.1" />
|
||||
<PackageVersion Include="ReactiveUI.XamForms" Version="18.3.1" />
|
||||
<PackageVersion Include="ReactiveUI.AndroidX" Version="18.3.1" />
|
||||
<PackageVersion Include="ReactiveUI.Maui" Version="18.3.1" />
|
||||
<PackageVersion Include="Splat" Version="14.6.1" />
|
||||
<PackageVersion Include="DynamicData" Version="7.12.11" />
|
||||
<PackageVersion Include="ReactiveUI" Version="18.4.1" />
|
||||
<PackageVersion Include="ReactiveUI.Fody" Version="18.4.1" />
|
||||
<PackageVersion Include="ReactiveUI.XamForms" Version="18.4.1" />
|
||||
<PackageVersion Include="ReactiveUI.AndroidX" Version="18.4.1" />
|
||||
<PackageVersion Include="ReactiveUI.Maui" Version="18.4.1" />
|
||||
|
||||
<!-- SkiaSharp & HarfBuzzSharp -->
|
||||
<!-- https://github.com/AvaloniaUI/Avalonia/blob/master/build/HarfBuzzSharp.props -->
|
||||
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2.1-preview.91" />
|
||||
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2.1-preview.91" />
|
||||
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2.3" />
|
||||
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2.3" />
|
||||
<!-- https://github.com/AvaloniaUI/Avalonia/blob/master/build/SkiaSharp.props -->
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.1-preview.91" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.1-preview.91" />
|
||||
<PackageVersion Include="SkiaSharp" Version="2.88.3" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.3" />
|
||||
|
||||
<!-- AutoMapper -->
|
||||
<PackageVersion Include="AutoMapper" Version="11.0.1" />
|
||||
<PackageVersion Include="AutoMapper.Collection" Version="8.0.0" />
|
||||
<PackageVersion Include="AutoMapper" Version="12.0.0" />
|
||||
<PackageVersion Include="AutoMapper.Collection" Version="9.0.0" />
|
||||
<PackageVersion Include="AutoMapper.Collection.EntityFrameworkCore" Version="8.0.0" />
|
||||
<PackageVersion Include="AutoMapper.Extensions.ExpressionMapping" Version="5.1.0" />
|
||||
<PackageVersion Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
|
||||
<PackageVersion Include="AutoMapper.Extensions.ExpressionMapping" Version="6.0.2" />
|
||||
<PackageVersion Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
|
||||
|
||||
<!-- QRCode -->
|
||||
<!--<PackageVersion Include="QRCoder" Version="1.4.2" />-->
|
||||
@@ -157,14 +159,14 @@
|
||||
<!--<PackageVersion Include="GtkSharp" Version="3.24.24.38" />-->
|
||||
|
||||
<!-- Compression -->
|
||||
<PackageVersion Include="SharpZipLib" Version="1.3.3" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.1" />
|
||||
<PackageVersion Include="Squid-Box.SevenZipSharp.Lite" Version="1.5.0.366" />
|
||||
<PackageVersion Include="7-Zip.NativeAssets.Win32" Version="21.7.0-preview.1" />
|
||||
<PackageVersion Include="ZstdNet" Version="1.4.5" />
|
||||
|
||||
<!-- Algorithm -->
|
||||
<PackageVersion Include="Crc32.NET" Version="1.2.0" />
|
||||
<PackageVersion Include="gfoidl.Base64" Version="1.1.1" />
|
||||
<PackageVersion Include="gfoidl.Base64" Version="1.1.2" />
|
||||
|
||||
<!--Command Line Tools-->
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
@@ -189,31 +191,31 @@
|
||||
<!--<PackageVersion Include="AlipaySDKNet.Standard" Version="4.6.109" />-->
|
||||
|
||||
<!-- Excel -->
|
||||
<PackageVersion Include="NPOI" Version="2.5.6" />
|
||||
<PackageVersion Include="NPOI" Version="2.6.0" />
|
||||
|
||||
<!-- Github API -->
|
||||
<PackageVersion Include="Octokit" Version="1.0.0" />
|
||||
<PackageVersion Include="Octokit" Version="4.0.3" />
|
||||
|
||||
<!-- ORM -->
|
||||
<PackageVersion Include="sqlite-net-pcl" Version="1.8.116" />
|
||||
<PackageVersion Include="SQLitePCLRaw.bundle_green" Version="2.1.0" />
|
||||
<PackageVersion Include="SQLitePCLRaw.bundle_green" Version="2.1.3" />
|
||||
|
||||
<!-- MonoMac(NETSTANDARD) -->
|
||||
<PackageVersion Include="MonoMac.NetStandard" Version="0.0.4" />
|
||||
|
||||
<!-- .NET Compat -->
|
||||
<PackageVersion Include="OperatingSystem2" Version="2.0.0" />
|
||||
<PackageVersion Include="JustArchiNET.Madness" Version="3.7.0" />
|
||||
<PackageVersion Include="JustArchiNET.Madness" Version="3.9.0" />
|
||||
|
||||
<!-- Serialize -->
|
||||
<PackageVersion Include="MessagePack" Version="2.4.35" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageVersion Include="MessagePack" Version="2.4.59" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
|
||||
<!-- Html Parser -->
|
||||
<PackageVersion Include="HtmlAgilityPack" Version="1.11.43" />
|
||||
<PackageVersion Include="HtmlAgilityPack" Version="1.11.46" />
|
||||
|
||||
<!-- Clipboard -->
|
||||
<PackageVersion Include="TextCopy" Version="6.1.0" />
|
||||
<PackageVersion Include="TextCopy" Version="6.2.0" />
|
||||
|
||||
<!-- Nito.* -->
|
||||
<PackageVersion Include="Nito.Comparers" Version="6.2.2" />
|
||||
@@ -228,7 +230,9 @@
|
||||
<PackageVersion Include="Fleck" Version="1.2.0" />
|
||||
|
||||
<!-- DNS -->
|
||||
<PackageVersion Include="DnsClient" Version="1.6.1" />
|
||||
<PackageVersion Include="Ae.DNS.Client" Version="0.0.16" />
|
||||
<!--<PackageVersion Include="Ae.Dns.Protocol" Version="0.0.16" />-->
|
||||
<PackageVersion Include="DnsClient" Version="1.7.0" />
|
||||
<PackageVersion Include="DNS" Version="7.0.0" />
|
||||
|
||||
<!-- Cryptographic Algorithms & Protocols -->
|
||||
@@ -238,34 +242,34 @@
|
||||
<PackageVersion Include="Polly" Version="7.2.3" />
|
||||
|
||||
<!--Avalonia Start-->
|
||||
<PackageVersion Include="Avalonia" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.Skia" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Skia" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="0.10.18" />
|
||||
<!--<PackageVersion Include="Avalonia.Direct2D1" Version="0.10.16" />-->
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.Xaml.Behaviors" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Xaml.Behaviors" Version="0.10.18" />
|
||||
<!--<PackageVersion Include="Avalonia.AvaloniaEdit" Version="0.10.12.2" />-->
|
||||
<!--<PackageVersion Include="CefNet.Avalonia" Version="93.1.21240.857" />-->
|
||||
<!--<PackageVersion Include="LibVLCSharp.Avalonia" Version="3.5.1" />-->
|
||||
<!--<PackageVersion Include="FluentAvaloniaUI" Version="1.4.1" />-->
|
||||
<PackageVersion Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-beta.330" />
|
||||
<!--<PackageVersion Include="FluentAvaloniaUI" Version="1.4.4" />-->
|
||||
<PackageVersion Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-beta.603" />
|
||||
<PackageVersion Include="JumpLists.Win32.Avalonia" Version="1.0.0" />
|
||||
<PackageVersion Include="Avalonia.Native" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.Win32" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.X11" Version="0.10.17" />
|
||||
<PackageVersion Include="Avalonia.Native" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.Win32" Version="0.10.18" />
|
||||
<PackageVersion Include="Avalonia.X11" Version="0.10.18" />
|
||||
<!--<PackageVersion Include="Avalonia.HtmlRenderer" Version="0.10.0" />-->
|
||||
<PackageVersion Include="WebView2.Avalonia" Version="1.0.1264.42-preview.220713.10" />
|
||||
<!--Avalonia End-->
|
||||
|
||||
<!-- Xamarin.Android -->
|
||||
<PackageVersion Include="Xamarin.Build.Download" Version="0.11.2" />
|
||||
<PackageVersion Include="Xamarin.Build.Download" Version="0.11.4" />
|
||||
<PackageVersion Include="Xamarin.Google.Dagger" Version="2.40.5" />
|
||||
<PackageVersion Include="Xamarin.Google.MLKit.BarcodeScanning" Version="116.1.2.5" />
|
||||
<PackageVersion Include="Plugin.CurrentActivity" Version="2.1.0.4" />
|
||||
<PackageVersion Include="de.hdodenhof.circleimageview" Version="3.1.0.4" />
|
||||
<PackageVersion Include="Square.OkHttp3" Version="4.9.3" />
|
||||
<PackageVersion Include="Square.OkHttp3" Version="4.9.3.2" />
|
||||
<PackageVersion Include="Square.Picasso" Version="2.71828.0" />
|
||||
<!--<PackageVersion Include="LeakCanaryBinding" Version="1.5.1.1" />-->
|
||||
<!--<PackageVersion Include="TencentOpenApiSDK.Android" Version="3.5.4.11" />-->
|
||||
@@ -274,29 +278,29 @@
|
||||
<!-- V2Ray -->
|
||||
<PackageVersion Include="XAB.AndroidLibV2rayLite" Version="1.0.0.1" />
|
||||
<!--<PackageVersion Include="Karamunting.KotlinX.Coroutines.Core" Version="1.4.2" />-->
|
||||
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Core" Version="1.6.2.1" />
|
||||
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Android" Version="1.6.2.1" />
|
||||
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Core" Version="1.6.4" />
|
||||
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Android" Version="1.6.4" />
|
||||
<PackageVersion Include="Xamarin.Android.ReactiveX.RxJava3.RxJava" Version="3.1.5.1" />
|
||||
|
||||
<!-- Xamarin.AndroidX -->
|
||||
<PackageVersion Include="Xamarin.AndroidX.Migration" Version="1.0.10" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.4.2.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Emoji.AppCompat" Version="1.1.0.9" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.4.1.2" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.5.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.RecyclerView" Version="1.2.1.7" />
|
||||
<PackageVersion Include="Xamarin.Google.Android.Material" Version="1.6.1.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.SwipeRefreshLayout" Version="1.1.0.9" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.ConstraintLayout" Version="2.1.4.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Navigation.UI" Version="2.4.2.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.4.2.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Navigation.UI" Version="2.5.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.5.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.ViewPager2" Version="1.0.0.16" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Activity" Version="1.4.0.4" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Activity" Version="1.5.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Biometric" Version="1.1.0.10" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.ExifInterface" Version="1.3.3.6" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Legacy.Support.Core.UI" Version="1.0.0.15" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.4.1.2" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Camera.Camera2" Version="1.1.0-beta02" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.1.0-beta02" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.5.1" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Camera.Camera2" Version="1.1.0" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.1.0" />
|
||||
<PackageVersion Include="Xamarin.AndroidX.Camera.View" Version="1.1.0-beta02" />
|
||||
<!--<PackageVersion Include="Xamarin.AndroidX.Window" Version="1.0.0.9" />-->
|
||||
<PackageVersion Include="Xamarin.AndroidX.WebKit" Version="1.4.0.8" />
|
||||
@@ -305,14 +309,14 @@
|
||||
<PackageVersion Include="Toast.iOS" Version="1.2.0" />
|
||||
|
||||
<!-- UWP -->
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.1.3" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.2.221116.1" />
|
||||
|
||||
<!-- Code Style -->
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.435" />
|
||||
|
||||
<!-- Quartz -->
|
||||
<PackageVersion Include="Quartz.AspNetCore" Version="3.4.0" />
|
||||
<PackageVersion Include="Quartz.AspNetCore" Version="3.5.0" />
|
||||
|
||||
<!-- Yet Another Reverse Proxy -->
|
||||
<PackageVersion Include="Yarp.ReverseProxy" Version="1.1.1" />
|
||||
@@ -322,5 +326,8 @@
|
||||
|
||||
<!-- ArchiSteamFarm -->
|
||||
<PackageVersion Include="ArchiSteamFarm.Library" Version="5.2.6.3-preview.220608" />
|
||||
|
||||
<!-- DBreeze(key value store embedded) -->
|
||||
<PackageVersion Include="DBreeze" Version="1.107.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="LocalNuGetPackages" value="./references/NuGetPackages" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -24,13 +24,9 @@
|
||||
"src\\Common.PinyinLib\\Common.PinyinLib.csproj",
|
||||
"src\\Common.PinyinLib.CFStringTransform\\Common.PinyinLib.CFStringTransform.csproj",
|
||||
"src\\Repositories.sqlite-net-pcl\\Repositories.sqlite-net-pcl.csproj",
|
||||
"src\\ST.Client.Android\\ST.Client.Android.csproj",
|
||||
"src\\ST.Client.Desktop.Mac\\ST.Client.Mac.csproj",
|
||||
"src\\ST.Client.Mobile.Droid.App\\ST.Client.Android.App.csproj",
|
||||
"src\\ST.Client.XamarinForms\\ST.Client.XamarinForms.csproj",
|
||||
"src\\ST.Client.Desktop.Avalonia\\ST.Client.Avalonia.csproj",
|
||||
"src\\ST.Client.Desktop.Avalonia.App\\ST.Client.Avalonia.App.csproj",
|
||||
"src\\ST.Client.iOS\\ST.Client.iOS.csproj",
|
||||
"src\\ST.Client\\ST.Client.csproj",
|
||||
"src\\ST.Services.CloudService.Models\\ST.Services.CloudService.Models.csproj",
|
||||
"src\\ST.Services.CloudService.ViewModels\\ST.Services.CloudService.ViewModels.csproj",
|
||||
@@ -42,11 +38,7 @@
|
||||
"src\\ST.Tools.Translate\\ST.Tools.Translate.csproj",
|
||||
"src\\ST\\ST.csproj",
|
||||
"src\\ST.Client.ResSecrets\\ST.Client.ResSecrets.csproj",
|
||||
"src\\ST.Client.iOS.ResSecrets\\ST.Client.iOS.ResSecrets.csproj",
|
||||
"src\\ST.Client.Android.ResSecrets\\ST.Client.Android.ResSecrets.csproj",
|
||||
"src\\ST.Client.Mac.ResSecrets\\ST.Client.Mac.ResSecrets.csproj",
|
||||
"tests\\Common.UnitTest.Droid.App\\ST.Client.UnitTest.Droid.App.csproj",
|
||||
"tests\\Common.UnitTest.Droid\\ST.Client.UnitTest.Droid.csproj",
|
||||
"tests\\Common.UnitTest\\Common.UnitTest.csproj",
|
||||
"tests\\ST.Client.Desktop.UnitTest\\ST.Client.Desktop.UnitTest.csproj",
|
||||
"tests\\ST.Client.UnitTest\\ST.Client.UnitTest.csproj"
|
||||
|
||||
+2
-415
@@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Root", "_Root", "{66839CD8
|
||||
download-guide.md = download-guide.md
|
||||
global.json = global.json
|
||||
packaging\Info.plist = packaging\Info.plist
|
||||
NuGet.Config = NuGet.Config
|
||||
packaging\package.net472.ps1 = packaging\package.net472.ps1
|
||||
README.en.md = README.en.md
|
||||
README.md = README.md
|
||||
@@ -114,14 +115,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI Framework", "UI Framewor
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web API", "Web API", "{4E7DF449-F136-4B90-82CE-D1418CD5123C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android", "src\ST.Client.Android\ST.Client.Android.csproj", "{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.iOS", "src\ST.Client.iOS\ST.Client.iOS.csproj", "{7EE23547-B2AC-409D-991C-1FDAE122657C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.XamarinForms", "src\ST.Client.XamarinForms\ST.Client.XamarinForms.csproj", "{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ST.Client.Android.App", "src\ST.Client.Mobile.Droid.App\ST.Client.Android.App.csproj", "{B355E372-27D2-4217-A129-D3355573681F}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Avalonia.Ref", "Avalonia.Ref", "{910D6A0F-42AB-4B65-B532-852E864EC006}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Native", "src\Avalonia.Native\Avalonia.Native.csproj", "{17FBD44D-D9AA-48C2-9A06-214E8405CF88}"
|
||||
@@ -153,10 +146,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Github", "_Github", "{B114
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.ClientLib.iOS", "src\Common.ClientLib.iOS\Common.ClientLib.iOS.csproj", "{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.UnitTest.Droid", "tests\Common.UnitTest.Droid\ST.Client.UnitTest.Droid.csproj", "{80E6762E-AB43-41E2-BDB4-7A3E24713977}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ST.Client.UnitTest.Droid.App", "tests\Common.UnitTest.Droid.App\ST.Client.UnitTest.Droid.App.csproj", "{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.UnitTest", "tests\ST.Client.Desktop.UnitTest\ST.Client.Desktop.UnitTest.csproj", "{5D9E0EAA-2419-426B-BAB4-EA496C1FF7E9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.UnitTest.Resources", "tests\ST.Client.UnitTest.Resources\ST.Client.UnitTest.Resources.csproj", "{FB2CA9B4-71F1-48E8-B9AE-FF4375F4FE43}"
|
||||
@@ -167,14 +156,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.Internals", "
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bindings", "Bindings", "{80EBD601-28AC-4840-B9B8-E6064816A443}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.V2Ray", "src\ST.Client.Android.V2Ray\ST.Client.Android.V2Ray.csproj", "{4A79264D-5BF5-4F89-8066-44E154BF557F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gameloop.Vdf", "references\Gameloop.Vdf\Gameloop.Vdf\Gameloop.Vdf.csproj", "{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.Shadowsocks", "src\ST.Client.Android.Shadowsocks\ST.Client.Android.Shadowsocks.csproj", "{920EF29F-406F-43A9-B002-29DD6B0B4FBF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.App.Modern", "src\ST.Client.Android.App.Modern\ST.Client.Android.App.Modern.csproj", "{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ResSecrets", "ResSecrets", "{17667B53-1A09-45A6-855A-0F07F9AE044F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.ResSecrets", "src\ST.Client.Android.ResSecrets\ST.Client.Android.ResSecrets.csproj", "{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}"
|
||||
@@ -189,16 +172,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Windows.ResSecret
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Desktop", "src\Avalonia.Desktop\Avalonia.Desktop.csproj", "{FA9F0E89-E410-400A-86F3-C603E51E62A8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Avalonia.App.MsixPackage", "src\ST.Client.Desktop.Avalonia.App.Bridge2\ST.Client.Avalonia.App.MsixPackage.csproj", "{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FDELauncher", "src\FDELauncher\FDELauncher.csproj", "{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Http.Headers", "src\Microsoft.Net.Http.Headers\Microsoft.Net.Http.Headers.csproj", "{C7F109B9-EA88-4B7E-ADB5-D6407686ADE0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Maui.App", "src\ST.Client.Maui.App\ST.Client.Maui.App.csproj", "{73A9AB65-AF95-4F27-98E2-B3296F9BC198}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Maui", "src\ST.Client.Maui\ST.Client.Maui.csproj", "{48417EE3-BACB-4E04-B48D-B3781862AD81}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.Essentials", "src\Common.Essentials\Common.Essentials.csproj", "{41434AB5-48C3-47D4-8721-D118D87F472B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.Essentials.Xamarin", "src\Common.Essentials.Xamarin\Common.Essentials.Xamarin.csproj", "{07C9AC06-5D84-41AB-A3C9-5C5B1A27F526}"
|
||||
@@ -1321,132 +1298,6 @@ Global
|
||||
{D30203AC-97AB-4A51-BFA5-826251C9A28E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D30203AC-97AB-4A51-BFA5-826251C9A28E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D30203AC-97AB-4A51-BFA5-826251C9A28E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|ARM.Deploy.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|ARM64.Deploy.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|iPhone.Deploy.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|x64.Deploy.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Debug|x86.Deploy.0 = Debug|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|ARM.Deploy.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|ARM64.Deploy.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|iPhone.Deploy.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|x64.Deploy.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B355E372-27D2-4217-A129-D3355573681F}.Release|x86.Deploy.0 = Release|Any CPU
|
||||
{17FBD44D-D9AA-48C2-9A06-214E8405CF88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{17FBD44D-D9AA-48C2-9A06-214E8405CF88}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{17FBD44D-D9AA-48C2-9A06-214E8405CF88}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
@@ -1671,76 +1522,6 @@ Global
|
||||
{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|x64.Build.0 = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|ARM.Deploy.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|ARM64.Deploy.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|iPhone.Deploy.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|x64.Deploy.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|x86.Deploy.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|ARM.Deploy.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|ARM64.Deploy.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|iPhone.Deploy.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|x64.Deploy.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|x86.Deploy.0 = Release|Any CPU
|
||||
{5D9E0EAA-2419-426B-BAB4-EA496C1FF7E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5D9E0EAA-2419-426B-BAB4-EA496C1FF7E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5D9E0EAA-2419-426B-BAB4-EA496C1FF7E9}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
@@ -1853,34 +1634,6 @@ Global
|
||||
{47C151DA-D2B1-43F4-A04E-B454E2134852}.Release|x64.Build.0 = Release|Any CPU
|
||||
{47C151DA-D2B1-43F4-A04E-B454E2134852}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{47C151DA-D2B1-43F4-A04E-B454E2134852}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
@@ -1909,64 +1662,6 @@ Global
|
||||
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x86.Build.0 = Release|Any CPU
|
||||
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
@@ -2135,36 +1830,6 @@ Global
|
||||
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM64.ActiveCfg = Debug|arm64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM64.Build.0 = Debug|arm64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.Build.0 = Debug|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x86.Build.0 = Debug|x86
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|Any CPU.Build.0 = Release|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM64.ActiveCfg = Release|arm64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM64.Build.0 = Release|arm64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.ActiveCfg = Release|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.Build.0 = Release|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.Deploy.0 = Release|x64
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x86.ActiveCfg = Release|x86
|
||||
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x86.Build.0 = Release|x86
|
||||
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
@@ -2221,76 +1886,6 @@ Global
|
||||
{C7F109B9-EA88-4B7E-ADB5-D6407686ADE0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C7F109B9-EA88-4B7E-ADB5-D6407686ADE0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C7F109B9-EA88-4B7E-ADB5-D6407686ADE0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|ARM.Deploy.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|ARM64.Deploy.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|iPhone.Deploy.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|x64.Deploy.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Debug|x86.Deploy.0 = Debug|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|ARM.Deploy.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|ARM64.Deploy.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|iPhone.Deploy.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|x64.Build.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|x64.Deploy.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|x86.Build.0 = Release|Any CPU
|
||||
{73A9AB65-AF95-4F27-98E2-B3296F9BC198}.Release|x86.Deploy.0 = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|iPhone.Build.0 = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|x64.Build.0 = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81}.Release|x86.Build.0 = Release|Any CPU
|
||||
{41434AB5-48C3-47D4-8721-D118D87F472B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{41434AB5-48C3-47D4-8721-D118D87F472B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{41434AB5-48C3-47D4-8721-D118D87F472B}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
@@ -2700,9 +2295,6 @@ Global
|
||||
{E50441E8-75F3-406E-9921-30BFC211B5CE} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
|
||||
{8E38AAF2-8C7D-4B0D-AB25-AB37EECB4029} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
|
||||
{4E7DF449-F136-4B90-82CE-D1418CD5123C} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
|
||||
{DEF239E4-AC40-4BD8-8D36-5AA6B36AB86B} = {E50441E8-75F3-406E-9921-30BFC211B5CE}
|
||||
{7EE23547-B2AC-409D-991C-1FDAE122657C} = {E50441E8-75F3-406E-9921-30BFC211B5CE}
|
||||
{3763D6C4-82B7-4C13-9BB8-886FC1BD83B6} = {8E38AAF2-8C7D-4B0D-AB25-AB37EECB4029}
|
||||
{910D6A0F-42AB-4B65-B532-852E864EC006} = {E50441E8-75F3-406E-9921-30BFC211B5CE}
|
||||
{17FBD44D-D9AA-48C2-9A06-214E8405CF88} = {910D6A0F-42AB-4B65-B532-852E864EC006}
|
||||
{650572DD-E958-4E42-9B46-1510BA15E571} = {910D6A0F-42AB-4B65-B532-852E864EC006}
|
||||
@@ -2712,16 +2304,12 @@ Global
|
||||
{21C392C5-AE41-421A-A127-1A03C4ACA2AD} = {673FF8CD-9E85-4FA1-ABFC-D1149675E138}
|
||||
{29DE5086-0690-4AE7-9BA9-840F54B249DC} = {E448F863-4C9D-47A4-BC4A-4A1381B54DA4}
|
||||
{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
|
||||
{80E6762E-AB43-41E2-BDB4-7A3E24713977} = {CC46B486-00D7-49E6-ABA3-FDF8F4868D2B}
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA} = {CC46B486-00D7-49E6-ABA3-FDF8F4868D2B}
|
||||
{5D9E0EAA-2419-426B-BAB4-EA496C1FF7E9} = {CC46B486-00D7-49E6-ABA3-FDF8F4868D2B}
|
||||
{FB2CA9B4-71F1-48E8-B9AE-FF4375F4FE43} = {CC46B486-00D7-49E6-ABA3-FDF8F4868D2B}
|
||||
{E84FF7BC-FC2A-424E-8780-7DA9B487E23F} = {910D6A0F-42AB-4B65-B532-852E864EC006}
|
||||
{47C151DA-D2B1-43F4-A04E-B454E2134852} = {910D6A0F-42AB-4B65-B532-852E864EC006}
|
||||
{80EBD601-28AC-4840-B9B8-E6064816A443} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
|
||||
{4A79264D-5BF5-4F89-8066-44E154BF557F} = {80EBD601-28AC-4840-B9B8-E6064816A443}
|
||||
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE} = {673FF8CD-9E85-4FA1-ABFC-D1149675E138}
|
||||
{920EF29F-406F-43A9-B002-29DD6B0B4FBF} = {80EBD601-28AC-4840-B9B8-E6064816A443}
|
||||
{17667B53-1A09-45A6-855A-0F07F9AE044F} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
|
||||
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277} = {17667B53-1A09-45A6-855A-0F07F9AE044F}
|
||||
{089D4418-975B-455D-9AE1-B9DEC20FF4B1} = {17667B53-1A09-45A6-855A-0F07F9AE044F}
|
||||
@@ -2730,7 +2318,6 @@ Global
|
||||
{058F9955-8EFE-4BF3-A8F9-44C57B1F812E} = {17667B53-1A09-45A6-855A-0F07F9AE044F}
|
||||
{FA9F0E89-E410-400A-86F3-C603E51E62A8} = {910D6A0F-42AB-4B65-B532-852E864EC006}
|
||||
{C7F109B9-EA88-4B7E-ADB5-D6407686ADE0} = {673FF8CD-9E85-4FA1-ABFC-D1149675E138}
|
||||
{48417EE3-BACB-4E04-B48D-B3781862AD81} = {8E38AAF2-8C7D-4B0D-AB25-AB37EECB4029}
|
||||
{41434AB5-48C3-47D4-8721-D118D87F472B} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
|
||||
{07C9AC06-5D84-41AB-A3C9-5C5B1A27F526} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
|
||||
{5C440EC2-9251-4DB5-A14E-68FF37814F12} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
|
||||
@@ -2746,7 +2333,7 @@ Global
|
||||
{8C996C50-B29F-4CB6-90A7-77C9CD3B0B70} = {910D6A0F-42AB-4B65-B532-852E864EC006}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
RESX_NeutralResourcesLanguage = zh-Hans
|
||||
SolutionGuid = {9313F2B4-10DA-43AA-A481-CAA7571C740C}
|
||||
RESX_NeutralResourcesLanguage = zh-Hans
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>net.steampp.app</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.8.2</string>
|
||||
<string>2.8.3</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.8.2.0</string>
|
||||
<string>2.8.3.0</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
|
||||
Submodule references/ArchiSteamFarm updated: c0f13bf7fd...a427f628e1
Submodule references/FluentAvalonia updated: 8098c1c22a...50c719a4b9
Binary file not shown.
Binary file not shown.
Submodule references/SteamAchievementManager updated: b39839a962...99ce54cac5
+43
-38
@@ -1,28 +1,33 @@
|
||||
### 公告
|
||||
1. 非简中语言将默认隐藏加速和脚本功能,仅能通过切换语言并重启程序的方式还原被隐藏的功能
|
||||
2. 因经济状况原因,现已停止短信服务节约开销,后续会推出邮箱注册登录,对于仅使用手机号登录的用户请绑定第三方快速登录,否则注销后将无法再次登录,需要等待至邮箱服务推出后支持会暂时在开放短信服务提供换绑邮箱。
|
||||
3. 自动更新目前仅 Windows 端可用,且由于下载渠道限速可能导致无法更新成功,推荐在官网链接的网盘或群文件中下载压缩包解压覆盖更新(应用商店版由商店更新不受此影响)
|
||||
4. 在 Android 上因系统限制,目前的加速功能无法正常使用,所以此功能已放弃继续开发,如仍想使用需要自行导入证书到系统目录,使用 adb 工具或 Magisk 之类的软件操作,未来会使用不需要证书的加速功能替换此功能
|
||||
5. fde 版本需要安装 [ASP.NET Core 运行时 6.0.7 (x64) 与 .NET Core 运行时 6.0.7 (x64)](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0)
|
||||
6. Windows x86 与 x64 版本令牌本机加密互不兼容,使用两者版本时注意令牌加密后的文件不能共用。
|
||||
7. 由于新版本加速功能重构,调整了部分加速项目,这会影响旧版本程序使用加速功能
|
||||
8. 为了能继续维持开发,从此版本开始将会添加程序内广告,赞助用户可以在设置中关闭所有广告
|
||||
这是一个修复目前累积问题的版本,也是最后一个.NET 6 的版本,
|
||||
之后桌面端程序将使用.NET 7 + Avalonia 11.0 重构发布新版本。
|
||||
届时也会放弃继续对 Win7/8.1 系统的支持,所以这也意味着这是最后一个支持 Win7/8.1 的版本。
|
||||
也请各位敬请期待之后的 3.0 版本吧~
|
||||
|
||||
<!--
|
||||
### 版本亮点
|
||||
1. 修复与改进一些已知问题
|
||||
1. .NET 运行时升级至 6.0.12,使用 fde 版本需要升级运行时
|
||||
2. ASF 升级至 V5.3.2.4
|
||||
-->
|
||||
|
||||
### 修复问题
|
||||
1. 修复 Windows FDE 版在 Windows 8.1/10 上错误识别成 Windows 8
|
||||
2. 修复 网络加速 DNS 设置无效
|
||||
3. 修复 网络加速 PAC 代理模式不能正常工作
|
||||
4. 修复 Windows 7 上的一些兼容性问题导致加速失效
|
||||
5. 改进 Windows Desktop Bridge 版本中不再弹出防火墙规则授权弹窗
|
||||
6. 修复 Windows Desktop Bridge 版本开机自启静默失效
|
||||
7. 改进 DNS 驱动拦截模式停止后不再占用 sys 文件
|
||||
8. 改进 通知 UI 列表项中仅显示两行文字
|
||||
9. 修复 第三方快速登录失败
|
||||
10. 改进 关闭代理时仅根据当前代理模式进行清理
|
||||
|
||||
1. 改进 Mac 安装证书的提示,显示执行命令
|
||||
2. 修复 Steam 启动参数在一些场景下无效
|
||||
3. 修复 网络加速 关闭 http 重定向到 https 依然监听 80 端口错误
|
||||
4. 修复 网络加速 仅启用脚本功能 导致代理网站无法访问的错误
|
||||
5. 修复 网络加速 开启系统代理和 PAC 代理后,非代理网站无法正常访问的错误
|
||||
6. 修改 证书安装路径 为本地计算机 而不在是 当前用户 以支持跨用户访问,这项改动可能导致大家需要重新安装一次证书
|
||||
7. 修复 库存游戏 因 Steam 客户端更新导致的加载游戏数据失败问题
|
||||
8. 修复 捐助列表金额显示错位问题
|
||||
9. 修复 Twitch 聊天连接失败问题
|
||||
10. 修复 discord.gg 无法访问导致无法加入频道分享链接问题
|
||||
11. 修复 Steam 没有正确识别 Steam 国服提示问题
|
||||
12. ASF 升级至 V5.3.2.4
|
||||
12. .NET 运行时升级至 6.0.12,使用 fde 版本需要升级运行时
|
||||
13. 新增 Steam 设置可设置 模拟蒸汽平台启动参数
|
||||
14. 修复 Steam Beta 版库存游戏加载不出游戏详情和名称
|
||||
15. 修复 成就管理、云存档管理 无法打开
|
||||
16. 修复 库存游戏 首次加载后,游戏加载失败提示文本依然存在
|
||||
<!--
|
||||
|
||||
### 已知问题
|
||||
@@ -58,7 +63,7 @@
|
||||
|
||||
|
||||
[](https://steampp.net)
|
||||
[]()
|
||||
[]()
|
||||
|
||||
|
||||
##### [不知道该下载哪个文件?](./download-guide.md)
|
||||
@@ -67,28 +72,28 @@
|
||||
### 文件校验
|
||||
| File | Checksum (SHA256) |
|
||||
| ---- | ---- |
|
||||
| Steam++_win_x64_v2.8.2.7z | SHA256 |
|
||||
| Steam++_win_x64_fde_v2.8.2.7z | SHA256 |
|
||||
| Steam++_win_x64_v2.8.5.7z | SHA256 |
|
||||
| Steam++_win_x64_fde_v2.8.5.7z | SHA256 |
|
||||
| | |
|
||||
| Steam++_win_x64_v2.8.2.exe | SHA256 |
|
||||
| Steam++_win_x64_fde_v2.8.2.exe | SHA256 |
|
||||
| Steam++_win_x64_v2.8.5.exe | SHA256 |
|
||||
| Steam++_win_x64_fde_v2.8.5.exe | SHA256 |
|
||||
| | |
|
||||
| Steam++_win_x86_v2.8.2.7z | SHA256 |
|
||||
| Steam++_win_x86_fde_v2.8.2.7z | SHA256 |
|
||||
| Steam++_win_x86_v2.8.5.7z | SHA256 |
|
||||
| Steam++_win_x86_fde_v2.8.5.7z | SHA256 |
|
||||
| | |
|
||||
| Steam++_win_x86_v2.8.2.exe | SHA256 |
|
||||
| Steam++_win_x86_fde_v2.8.2.exe | SHA256 |
|
||||
| Steam++_win_x86_v2.8.5.exe | SHA256 |
|
||||
| Steam++_win_x86_fde_v2.8.5.exe | SHA256 |
|
||||
| | |
|
||||
| Steam++_linux_x64_v2.8.2.7z | SHA256 |
|
||||
| Steam++_linux_arm64_v2.8.2.7z | SHA256 |
|
||||
| Steam++_linux_x64_v2.8.5.7z | SHA256 |
|
||||
| Steam++_linux_arm64_v2.8.5.7z | SHA256 |
|
||||
| | |
|
||||
| Steam++_linux_x64_v2.8.2.deb | SHA256 |
|
||||
| Steam++_linux_arm64_v2.8.2.deb | SHA256 |
|
||||
| Steam++_linux_x64_v2.8.5.deb | SHA256 |
|
||||
| Steam++_linux_arm64_v2.8.5.deb | SHA256 |
|
||||
| | |
|
||||
| Steam++_linux_x64_v2.8.2.rpm | SHA256 |
|
||||
| Steam++_linux_arm64_v2.8.2.rpm | SHA256 |
|
||||
| Steam++_linux_x64_v2.8.5.rpm | SHA256 |
|
||||
| Steam++_linux_arm64_v2.8.5.rpm | SHA256 |
|
||||
| | |
|
||||
| Steam++_macos_x64_v2.8.2.dmg | SHA256 |
|
||||
| Steam++_macos_arm64_v2.8.2.dmg | SHA256 |
|
||||
| Steam++_macos_x64_v2.8.5.dmg | SHA256 |
|
||||
| Steam++_macos_arm64_v2.8.5.dmg | SHA256 |
|
||||
| | |
|
||||
| Steam++_android_v2.8.2.apk | SHA256 |
|
||||
| Steam++_android_v2.8.5.apk | SHA256 |
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
// https://github.com/AvaloniaUI/Avalonia/blob/0.10.17/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Avalonia.Controls.ApplicationLifetimes
|
||||
{
|
||||
sealed class ClassicDesktopStyleApplicationLifetime2 : IClassicDesktopStyleApplicationLifetime, IDisposable
|
||||
{
|
||||
private int _exitCode;
|
||||
private CancellationTokenSource? _cts;
|
||||
private bool _isShuttingDown;
|
||||
private HashSet<Window> _windows = new();
|
||||
|
||||
private static ClassicDesktopStyleApplicationLifetime2? _activeLifetime;
|
||||
|
||||
static ClassicDesktopStyleApplicationLifetime2()
|
||||
{
|
||||
Window.WindowOpenedEvent.AddClassHandler(typeof(Window), OnWindowOpened);
|
||||
Window.WindowClosedEvent.AddClassHandler(typeof(Window), WindowClosedEvent);
|
||||
}
|
||||
|
||||
private static void WindowClosedEvent(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_activeLifetime?._windows.Remove((Window)sender);
|
||||
_activeLifetime?.HandleWindowClosed((Window)sender);
|
||||
}
|
||||
|
||||
private static void OnWindowOpened(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_activeLifetime?._windows.Add((Window)sender);
|
||||
}
|
||||
|
||||
public ClassicDesktopStyleApplicationLifetime2()
|
||||
{
|
||||
if (_activeLifetime != null)
|
||||
throw new InvalidOperationException(
|
||||
"Can not have multiple active ClassicDesktopStyleApplicationLifetime instances and the previously created one was not disposed");
|
||||
_activeLifetime = this;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<ControlledApplicationLifetimeStartupEventArgs>? Startup;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<ShutdownRequestedEventArgs>? ShutdownRequested;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<ControlledApplicationLifetimeExitEventArgs>? Exit;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments passed to the AppBuilder Start method.
|
||||
/// </summary>
|
||||
public string[]? Args { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ShutdownMode ShutdownMode { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Window? MainWindow { get; set; }
|
||||
|
||||
public IReadOnlyList<Window> Windows => _windows.ToList();
|
||||
|
||||
private void HandleWindowClosed(Window window)
|
||||
{
|
||||
if (window == null)
|
||||
return;
|
||||
|
||||
if (_isShuttingDown)
|
||||
return;
|
||||
|
||||
if (ShutdownMode == ShutdownMode.OnLastWindowClose && _windows.Count == 0)
|
||||
TryShutdown();
|
||||
else if (ShutdownMode == ShutdownMode.OnMainWindowClose && ReferenceEquals(window, MainWindow))
|
||||
TryShutdown();
|
||||
}
|
||||
|
||||
public void Shutdown(int exitCode = 0)
|
||||
{
|
||||
DoShutdown(new ShutdownRequestedEventArgs(), true, exitCode);
|
||||
}
|
||||
|
||||
public bool TryShutdown(int exitCode = 0)
|
||||
{
|
||||
return DoShutdown(new ShutdownRequestedEventArgs(), false, exitCode);
|
||||
}
|
||||
|
||||
public int Start(string[] args)
|
||||
{
|
||||
Startup?.Invoke(this, new ControlledApplicationLifetimeStartupEventArgs(args));
|
||||
|
||||
var options = AvaloniaLocator.Current.GetService<ClassicDesktopStyleApplicationLifetimeOptions>();
|
||||
|
||||
if (options != null && options.ProcessUrlActivationCommandLine && args.Length > 0)
|
||||
{
|
||||
if (Application.Current is IApplicationPlatformEvents events)
|
||||
{
|
||||
events.RaiseUrlsOpened(args);
|
||||
}
|
||||
}
|
||||
|
||||
var lifetimeEvents = AvaloniaLocator.Current.GetService<IPlatformLifetimeEventsImpl>();
|
||||
|
||||
if (lifetimeEvents != null)
|
||||
lifetimeEvents.ShutdownRequested += OnShutdownRequested;
|
||||
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
// Note due to a bug in the JIT we wrap this in a method, otherwise MainWindow
|
||||
// gets stuffed into a local var and can not be GCed until after the program stops.
|
||||
// this method never exits until program end.
|
||||
ShowMainWindow();
|
||||
|
||||
Dispatcher.UIThread.MainLoop(_cts.Token);
|
||||
Environment.ExitCode = _exitCode;
|
||||
return _exitCode;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void ShowMainWindow()
|
||||
{
|
||||
MainWindow?.Show();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_activeLifetime == this)
|
||||
_activeLifetime = null;
|
||||
}
|
||||
|
||||
private bool DoShutdown(ShutdownRequestedEventArgs e, bool force = false, int exitCode = 0)
|
||||
{
|
||||
if (!force)
|
||||
{
|
||||
ShutdownRequested?.Invoke(this, e);
|
||||
|
||||
if (e.Cancel)
|
||||
return false;
|
||||
|
||||
// https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/3780037517u/overview
|
||||
// ClassicDesktopStyleApplicationLifetime.DoShutdown (ShutdownRequestedEventArgs e, Boolean force, Int32 exitCode) /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs, line 147
|
||||
// System.InvalidOperationException: Application is already shutting down.
|
||||
// v2.8.2 | 73 users | 76 reports
|
||||
// Exception Stack:
|
||||
// System.InvalidOperationException: Application is already shutting down.
|
||||
// at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.DoShutdown(ShutdownRequestedEventArgs e, Boolean force, Int32 exitCode) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 147
|
||||
// at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.OnShutdownRequested(Object sender, ShutdownRequestedEventArgs e) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 186
|
||||
// at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam) in /_/src/Windows/Avalonia.Win32/Win32Platform.cs:line 283
|
||||
if (_isShuttingDown)
|
||||
// throw new InvalidOperationException("Application is already shutting down.");
|
||||
return true;
|
||||
}
|
||||
|
||||
_exitCode = exitCode;
|
||||
_isShuttingDown = true;
|
||||
|
||||
try
|
||||
{
|
||||
// When an OS shutdown request is received, try to close all non-owned windows. Windows can cancel
|
||||
// shutdown by setting e.Cancel = true in the Closing event. Owned windows will be shutdown by their
|
||||
// owners.
|
||||
foreach (var w in Windows)
|
||||
{
|
||||
if (w.Owner is null)
|
||||
{
|
||||
w.Close();
|
||||
}
|
||||
}
|
||||
|
||||
if (!force && Windows.Count > 0)
|
||||
{
|
||||
e.Cancel = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
var args = new ControlledApplicationLifetimeExitEventArgs(exitCode);
|
||||
Exit?.Invoke(this, args);
|
||||
_exitCode = args.ApplicationExitCode;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_cts?.Cancel();
|
||||
_cts = null;
|
||||
_isShuttingDown = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) => DoShutdown(e);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Avalonia
|
||||
{
|
||||
public static class ClassicDesktopStyleApplicationLifetimeExtensions
|
||||
{
|
||||
public static int StartWithClassicDesktopLifetime2<T>(
|
||||
this T builder, string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
|
||||
where T : AppBuilderBase<T>, new()
|
||||
{
|
||||
var lifetime = new ClassicDesktopStyleApplicationLifetime2()
|
||||
{
|
||||
Args = args,
|
||||
ShutdownMode = shutdownMode,
|
||||
};
|
||||
builder.SetupWithLifetime(lifetime);
|
||||
return lifetime.Start(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,22 @@ namespace System.Application;
|
||||
/// </summary>
|
||||
public static class MainThread2
|
||||
{
|
||||
static IMainThreadPlatformService? mInterface;
|
||||
|
||||
static IMainThreadPlatformService Interface
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mInterface == null) mInterface = IMainThreadPlatformService.Instance;
|
||||
return mInterface;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前是否为主线程。
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsMainThread() => IMainThreadPlatformService.Instance.PlatformIsMainThread;
|
||||
public static bool IsMainThread() => Interface.PlatformIsMainThread;
|
||||
|
||||
/// <summary>
|
||||
/// 调用应用程序主线程上的操作。
|
||||
@@ -33,7 +44,7 @@ public static class MainThread2
|
||||
{
|
||||
try
|
||||
{
|
||||
IMainThreadPlatformService.Instance.PlatformBeginInvokeOnMainThread(action, priority);
|
||||
Interface.PlatformBeginInvokeOnMainThread(action, priority);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
|
||||
+130
-5
@@ -1,6 +1,7 @@
|
||||
using SQLite;
|
||||
using System.Application.Entities;
|
||||
using System.Application.Repositories;
|
||||
using System.Application.Settings;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using SQLiteNotNull = SQLite.NotNullAttribute;
|
||||
@@ -8,8 +9,13 @@ using SQLiteTable = SQLite.TableAttribute;
|
||||
|
||||
namespace System.Application.Services.Implementation;
|
||||
|
||||
internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatformService
|
||||
#if DBREEZE
|
||||
partial class PreferencesPlatformServiceImplV2
|
||||
#else
|
||||
sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatformService
|
||||
#endif
|
||||
{
|
||||
#if !DBREEZE
|
||||
readonly SQLiteConnection conn;
|
||||
|
||||
public PreferencesPlatformServiceImpl()
|
||||
@@ -17,9 +23,9 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
|
||||
conn = Repository.GetDbConnectionSync<Entity>();
|
||||
}
|
||||
|
||||
static string GetId(string key) => $"{key}_K";
|
||||
internal static string GetId(string key) => $"{key}_K";
|
||||
|
||||
static string GetId(string key, string? sharedName)
|
||||
internal static string GetId(string key, string? sharedName)
|
||||
{
|
||||
if (sharedName == null) return GetId(key);
|
||||
return $"{key}_{sharedName}_S";
|
||||
@@ -75,12 +81,14 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const string TableName = "1984415E";
|
||||
const string ColumnName_Id = "0F5E4BAA";
|
||||
const string ColumnName_Value = "4FC331D7";
|
||||
const string ColumnName_SharedName = "F6A739AA";
|
||||
|
||||
#if !DBREEZE
|
||||
const string Sql_Delete_Where_SharedName_Equals =
|
||||
$"DELETE FROM \"{TableName}\" WHERE \"{ColumnName_SharedName}\" = ?";
|
||||
|
||||
@@ -101,12 +109,12 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
|
||||
|
||||
//const string Sql_Select_Value_Where_Key_Equals_And_SharedName_Equals =
|
||||
// $"SELECT \"{ColumnName_Value}\" FROM \"{TableName}\" WHERE \"{ColumnName_Id}\" = ? AND \"{ColumnName_SharedName}\" = ?";
|
||||
#endif
|
||||
|
||||
[SQLiteTable(TableName)]
|
||||
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
|
||||
public sealed class Entity : IEntity<string>
|
||||
{
|
||||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
[Column(ColumnName_Id)]
|
||||
[PrimaryKey]
|
||||
[SQLiteNotNull]
|
||||
@@ -115,7 +123,6 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
|
||||
[Column(ColumnName_Value)]
|
||||
[SQLiteNotNull]
|
||||
public string Value { get; set; } = string.Empty;
|
||||
#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
|
||||
[Column(ColumnName_SharedName)]
|
||||
[SQLiteNotNull]
|
||||
@@ -124,3 +131,121 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
|
||||
string DebuggerDisplay() => SharedName == string.Empty ? $"{Id}, {Value}" : $"{Id}, {Value}, {SharedName}";
|
||||
}
|
||||
}
|
||||
|
||||
#if DBREEZE
|
||||
public sealed partial class PreferencesPlatformServiceImplV2 : IPreferencesGenericPlatformService
|
||||
{
|
||||
static string GetTableName(string? sharedName) => $"Preferences.{sharedName}";
|
||||
|
||||
public void PlatformSet<T>(string key, T? value, string? sharedName) where T : notnull, IConvertible
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
PlatformRemove(key, sharedName);
|
||||
}
|
||||
else
|
||||
{
|
||||
using var t = SettingsProviderV3.Provider.GetTransaction();
|
||||
t.Insert(GetTableName(sharedName), key, value.ToString(CultureInfo.InvariantCulture));
|
||||
t.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
public void PlatformClear(string? sharedName)
|
||||
{
|
||||
using var t = SettingsProviderV3.Provider.GetTransaction();
|
||||
t.RemoveAllKeys(GetTableName(sharedName), true);
|
||||
t.Commit();
|
||||
}
|
||||
|
||||
public bool PlatformContainsKey(string key, string? sharedName)
|
||||
{
|
||||
using var t = SettingsProviderV3.Provider.GetTransaction();
|
||||
var row = t.Select<string, string>(GetTableName(sharedName), key);
|
||||
if (row == null) return false;
|
||||
return row.Exists;
|
||||
}
|
||||
|
||||
public T? PlatformGet<T>(string key, T? defaultValue, string? sharedName) where T : notnull, IConvertible
|
||||
{
|
||||
using var t = SettingsProviderV3.Provider.GetTransaction();
|
||||
var row = t.Select<string, string>(GetTableName(sharedName), key);
|
||||
if (row == null || !row.Exists) return defaultValue;
|
||||
var value = ConvertibleHelper.Convert<T>(row.Value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void PlatformRemove(string key, string? sharedName)
|
||||
{
|
||||
using var t = SettingsProviderV3.Provider.GetTransaction();
|
||||
t.RemoveKey(GetTableName(sharedName), key);
|
||||
t.Commit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从
|
||||
/// <para>使用 SQLiteConnection 的 PreferencesPlatformServiceImpl</para>
|
||||
/// <para>迁移到</para>
|
||||
/// <para>使用 DBreeze 的 PreferencesPlatformServiceImplV2</para>
|
||||
/// </summary>
|
||||
public static void Migrate()
|
||||
{
|
||||
var dbPath = Repository.DataBaseDirectory;
|
||||
bool isOK = false;
|
||||
bool exists = false;
|
||||
try
|
||||
{
|
||||
var dbFilePath = Path.Combine(dbPath, "application2.dbf");
|
||||
try
|
||||
{
|
||||
exists = File.Exists(dbFilePath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
if (!exists) return;
|
||||
var conn = new SQLiteConnection(dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache);
|
||||
var items = conn.Table<Entity>().ToArray();
|
||||
if (items.Any())
|
||||
{
|
||||
var itemGroups = items.GroupBy(x => x.SharedName).ToArray();
|
||||
foreach (var itemGroup in itemGroups)
|
||||
{
|
||||
using var t = SettingsProviderV3.Provider.GetTransaction();
|
||||
foreach (var item in itemGroup)
|
||||
{
|
||||
if (item.Value != null)
|
||||
{
|
||||
string key;
|
||||
if (string.IsNullOrEmpty(item.SharedName)) key = item.Id.TrimEnd("_K");
|
||||
else key = item.Id.TrimEnd($"_{item.SharedName}_S");
|
||||
var tableName = GetTableName(item.SharedName);
|
||||
t.Insert(tableName, key, item.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
t.Commit();
|
||||
}
|
||||
}
|
||||
conn.Close();
|
||||
conn.Dispose();
|
||||
isOK = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isOK)
|
||||
{
|
||||
var files = Directory.GetFiles(dbPath, "application2*");
|
||||
foreach (var item in files)
|
||||
{
|
||||
IOPath.FileTryDelete(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -62,7 +62,11 @@ public static class ServiceCollectionExtensions
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddRepositoryPreferences(this IServiceCollection services)
|
||||
{
|
||||
#if DBREEZE
|
||||
services.AddSingleton<IPreferencesPlatformService, PreferencesPlatformServiceImplV2>();
|
||||
#else
|
||||
services.AddSingleton<IPreferencesPlatformService, PreferencesPlatformServiceImpl>();
|
||||
#endif
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !DBREEZE
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace System.Application.Settings;
|
||||
@@ -60,7 +61,7 @@ public sealed class FileSettingsProvider : ISerializationProvider
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
using var stream = new FileStream(_path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete);
|
||||
using var stream = OpenReadWrite(_path);
|
||||
if (stream.Position > 0)
|
||||
{
|
||||
stream.Position = 0;
|
||||
@@ -71,6 +72,28 @@ public sealed class FileSettingsProvider : ISerializationProvider
|
||||
}
|
||||
}
|
||||
|
||||
static FileStream OpenReadWrite(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return OpenReadWrite();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
if (IOPath.FileTryDelete(path))
|
||||
{
|
||||
// 直接打开文件流失败,尝试删除后再打开一次
|
||||
return OpenReadWrite();
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
FileStream OpenReadWrite() => new(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete);
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
if (File.Exists(_path))
|
||||
@@ -82,7 +105,7 @@ public sealed class FileSettingsProvider : ISerializationProvider
|
||||
{
|
||||
stream.Position = 0;
|
||||
}
|
||||
var source = Serializable.DMP<IDictionary<string, object?>>(stream);
|
||||
var source = stream.Length == 0 ? null : Serializable.DMP<IDictionary<string, object?>>(stream);
|
||||
//var source = XamlServices.Load(stream) as IDictionary<string, object>;
|
||||
_settings = source == null
|
||||
? new SortedDictionary<string, object?>()
|
||||
@@ -107,4 +130,5 @@ public sealed class FileSettingsProvider : ISerializationProvider
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !DBREEZE
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace System.Application.Settings;
|
||||
@@ -22,4 +23,5 @@ public interface ISerializationProvider
|
||||
bool RemoveValue(string key);
|
||||
|
||||
string ToJsonString();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !DBREEZE
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -194,4 +195,5 @@ public class SerializableProperty<T> : INotifyPropertyChanged
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !DBREEZE
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System.Application.Settings;
|
||||
@@ -43,23 +44,96 @@ public static class SettingsHost
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(SettingsHost), "Config Save", ex);
|
||||
Log.Error(nameof(SettingsHost), ex, "Config Save");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试备份配置
|
||||
/// </summary>
|
||||
/// <param name="bakLocalFilePath"></param>
|
||||
static void TryBackup(string bakLocalFilePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var localFilePath = SettingsHostBase.LocalFilePath;
|
||||
if (File.Exists(localFilePath))
|
||||
{
|
||||
File.Copy(localFilePath, bakLocalFilePath, true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(SettingsHost), ex, "Config TryBackUp");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试还原备份配置,返回是否有备份文件
|
||||
/// </summary>
|
||||
/// <param name="bakLocalFilePath"></param>
|
||||
/// <returns></returns>
|
||||
static bool TryRestoreBackup(string bakLocalFilePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var exists = File.Exists(bakLocalFilePath);
|
||||
if (exists)
|
||||
{
|
||||
var localFilePath = SettingsHostBase.LocalFilePath;
|
||||
File.Copy(bakLocalFilePath, localFilePath, true);
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(SettingsHost), ex, "Config TryRestoreBackup");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试删除配置
|
||||
/// </summary>
|
||||
static void TryDelete()
|
||||
{
|
||||
try
|
||||
{
|
||||
var localFilePath = SettingsHostBase.LocalFilePath;
|
||||
if (File.Exists(localFilePath))
|
||||
{
|
||||
File.Delete(localFilePath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(SettingsHost), ex, "Config TryDelete");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
var isLoad = false;
|
||||
var bakLocalFilePath = $"{SettingsHostBase.LocalFilePath}.bak";
|
||||
try
|
||||
{
|
||||
SettingsHostBase.Local.Load();
|
||||
isLoad = true;
|
||||
|
||||
TryBackup(bakLocalFilePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(SettingsHost), "Config Load", ex);
|
||||
if (!TryRestoreBackup(bakLocalFilePath))
|
||||
{
|
||||
// 还原备份文件失败,删除当前配置
|
||||
TryDelete();
|
||||
}
|
||||
|
||||
File.Delete(SettingsHostBase.LocalFilePath);
|
||||
SettingsHostBase.Local.Load();
|
||||
Log.Error(nameof(SettingsHost), ex, $"Config Load, isLoad: {isLoad}");
|
||||
|
||||
if (!isLoad) SettingsHostBase.Local.Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,5 +159,6 @@ public abstract class SettingsHost2<TSettings> : SettingsHostBase where TSetting
|
||||
|
||||
static string GetKey(string propertyName) => $"{CategoryName}.{propertyName}";
|
||||
|
||||
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave, [CallerMemberName] string propertyName = "") => GetProperty(GetKey, Local, defaultValue, autoSave, propertyName);
|
||||
}
|
||||
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave = true, [CallerMemberName] string propertyName = "") => GetProperty(GetKey, Local, defaultValue, autoSave, propertyName);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,168 @@
|
||||
#if DBREEZE
|
||||
using DBreeze;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using static System.Application.Settings.ISerializableProperty;
|
||||
|
||||
namespace System.Application.Settings;
|
||||
|
||||
public interface ISerializableProperty : INotifyPropertyChanged
|
||||
{
|
||||
public const string tableName = "SerializableProperty";
|
||||
}
|
||||
|
||||
[DebuggerDisplay("Value={Value}, Key={Key}, Default={Default}")]
|
||||
public sealed class SerializableProperty<T> : ISerializableProperty, INotifyPropertyChanged
|
||||
{
|
||||
T? _value;
|
||||
bool _cached;
|
||||
DBreezeEngine? _Provider;
|
||||
|
||||
public string Key { get; }
|
||||
|
||||
public DBreezeEngine Provider { get => _Provider ?? throw new ArgumentNullException(nameof(_Provider)); set => _Provider = value; }
|
||||
|
||||
public T? Default { get; }
|
||||
|
||||
public T? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_cached)
|
||||
{
|
||||
{
|
||||
using var t = Provider.GetTransaction();
|
||||
var row = t.Select<string, byte[]>(tableName, Key);
|
||||
if (row?.Value == null)
|
||||
{
|
||||
_value = Default;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
_value = Serializable.DMP<T>(row.Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
_value = Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
_cached = true;
|
||||
}
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
var comparer = EqualityComparer<T?>.Default;
|
||||
if (_cached && comparer.Equals(_value, value)) return;
|
||||
var old = _value;
|
||||
_value = value;
|
||||
_cached = true;
|
||||
SetValue(comparer, old, value);
|
||||
}
|
||||
}
|
||||
|
||||
void SetValue(EqualityComparer<T?> comparer, T? oldValue, T? newValue)
|
||||
{
|
||||
{
|
||||
using var t = Provider.GetTransaction();
|
||||
if (comparer.Equals(newValue, Default))
|
||||
t.RemoveKey(tableName, Key);
|
||||
else
|
||||
t.Insert(tableName, Key, Serializable.SMP(newValue));
|
||||
t.Commit();
|
||||
}
|
||||
OnValueChanged(oldValue, newValue);
|
||||
}
|
||||
|
||||
public override string ToString() => Value?.ToString() ?? string.Empty;
|
||||
|
||||
public void RaiseValueChanged()
|
||||
{
|
||||
var comparer = EqualityComparer<T?>.Default;
|
||||
SetValue(comparer, _value, _value);
|
||||
}
|
||||
|
||||
public SerializableProperty(string key, DBreezeEngine provider) : this(key, provider, default)
|
||||
{
|
||||
}
|
||||
|
||||
public SerializableProperty(string key, DBreezeEngine provider, T? defaultValue)
|
||||
{
|
||||
Key = key;
|
||||
Provider = provider;
|
||||
Default = defaultValue;
|
||||
}
|
||||
|
||||
public IDisposable Subscribe(Action<T?> listener, bool notifyOnInitialValue = true)
|
||||
{
|
||||
if (notifyOnInitialValue)
|
||||
listener(Value);
|
||||
return new ValueChangedEventListener(this, listener);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
var comparer = EqualityComparer<T?>.Default;
|
||||
SetValue(comparer, _value, Default);
|
||||
}
|
||||
|
||||
sealed class ValueChangedEventListener : IDisposable
|
||||
{
|
||||
private readonly Action<T?> _listener;
|
||||
private readonly SerializableProperty<T> _source;
|
||||
|
||||
public ValueChangedEventListener(SerializableProperty<T> property, Action<T?> listener)
|
||||
{
|
||||
_listener = listener;
|
||||
_source = property;
|
||||
_source.ValueChanged += HandleValueChanged;
|
||||
}
|
||||
|
||||
private void HandleValueChanged(object? sender, ValueChangedEventArgs<T?> args)
|
||||
{
|
||||
_listener(args.NewValue);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_source.ValueChanged -= HandleValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator T?(SerializableProperty<T> property) => property.Value;
|
||||
|
||||
#region events
|
||||
|
||||
public event EventHandler<ValueChangedEventArgs<T?>>? ValueChanged;
|
||||
|
||||
void OnValueChanged(T? oldValue, T? newValue) => ValueChanged?.Invoke(this, new ValueChangedEventArgs<T?>(oldValue, newValue));
|
||||
|
||||
readonly Dictionary<PropertyChangedEventHandler, EventHandler<ValueChangedEventArgs<T>>> _handlers = new();
|
||||
|
||||
event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
if (value == null) return;
|
||||
ValueChanged += _handlers[value] = (sender, args) => value(sender, new PropertyChangedEventArgs(nameof(Value)));
|
||||
}
|
||||
|
||||
remove
|
||||
{
|
||||
if (value == null) return;
|
||||
if (_handlers.TryGetValue(value, out var handler))
|
||||
{
|
||||
ValueChanged -= handler;
|
||||
_handlers.Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#if DBREEZE
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System.Application.Settings;
|
||||
|
||||
public static class SettingsHost
|
||||
{
|
||||
public static void Load() => SettingsProviderV3.Load();
|
||||
|
||||
[Obsolete]
|
||||
public static void Save()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SettingsHost2<TSettings> where TSettings : SettingsHost2<TSettings>, new()
|
||||
{
|
||||
static readonly string CategoryName = typeof(TSettings).Name;
|
||||
|
||||
static string GetKey(string propertyName) => $"{CategoryName}.{propertyName}";
|
||||
|
||||
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, [CallerMemberName] string propertyName = "") => new(GetKey(propertyName), SettingsProviderV3.Provider, defaultValue);
|
||||
|
||||
[Obsolete("autoSave N/A")]
|
||||
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave, [CallerMemberName] string propertyName = "") => new(GetKey(propertyName), SettingsProviderV3.Provider, defaultValue);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
#if DBREEZE
|
||||
using DBreeze;
|
||||
using DBreeze.Utils;
|
||||
|
||||
namespace System.Application.Settings;
|
||||
|
||||
public static class SettingsProviderV3
|
||||
{
|
||||
static DBreezeEngine? _Provider;
|
||||
static readonly object lock_load = new();
|
||||
|
||||
public static DBreezeEngine Provider
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Provider == null) Load();
|
||||
return _Provider ?? throw new ArgumentNullException(nameof(_Provider));
|
||||
}
|
||||
set => _Provider = value;
|
||||
}
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
lock (lock_load)
|
||||
{
|
||||
if (_Provider == null)
|
||||
{
|
||||
_Provider = new(Path.Combine(IOPath.AppDataDirectory, "Config"));
|
||||
|
||||
//Setting up NetJSON serializer (from NuGet) to be used by DBreeze
|
||||
CustomSerializator.ByteArraySerializator = value => Serializable.SMP(value == null ? typeof(object) : value.GetType(), value!);
|
||||
CustomSerializator.ByteArrayDeSerializator = (buffer, type) => Serializable.DMP(type, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据从
|
||||
/// <para>使用 <see cref="IDictionary{TKey, TValue}"/> + <see cref="MessagePack"/> 单文件 的 FileSettingsProvider</para>
|
||||
/// <para>迁移到</para>
|
||||
/// <para>使用 DBreeze 的 SettingsProviderV3</para>
|
||||
/// </summary>
|
||||
public static void Migrate()
|
||||
{
|
||||
var filePath = Path.Combine(IOPath.AppDataDirectory, "Config" + FileEx.MPO);
|
||||
bool exists = false;
|
||||
try
|
||||
{
|
||||
exists = File.Exists(filePath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
if (exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
|
||||
if (stream.Position > 0)
|
||||
{
|
||||
stream.Position = 0;
|
||||
}
|
||||
var source = stream.Length == 0 ? null : Serializable.DMP<IDictionary<string, object?>>(stream);
|
||||
if (source.Any_Nullable())
|
||||
{
|
||||
if (_Provider == null) Load();
|
||||
using var t = Provider.GetTransaction();
|
||||
foreach (var item in source)
|
||||
{
|
||||
if (item.Value == null) continue;
|
||||
var valueType = item.Value.GetType();
|
||||
var value = Serializable.SMP(valueType, item.Value);
|
||||
t.Insert(ISerializableProperty.tableName, item.Key, value);
|
||||
}
|
||||
t.Commit();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOPath.FileTryDelete(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace System.Application.Settings;
|
||||
|
||||
public sealed class ValueChangedEventArgs<T> : EventArgs where T : notnull
|
||||
public sealed class ValueChangedEventArgs<T> : EventArgs
|
||||
{
|
||||
public T? OldValue { get; }
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<PackageReference Include="gfoidl.Base64" />
|
||||
<PackageReference Include="MessagePack" />
|
||||
<PackageReference Include="Newtonsoft.Json" />
|
||||
<PackageReference Include="DBreeze" Condition=" $(DefineConstants.Contains('DBREEZE')) " />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
|
||||
|
||||
@@ -77,10 +77,7 @@ public static partial class DI
|
||||
/// <inheritdoc cref="Get{T}"/>
|
||||
public static T? Get_Nullable<T>() where T : notnull
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw GetDIGetFailException(typeof(T));
|
||||
}
|
||||
if (value == null) return default;
|
||||
return value.GetService<T>();
|
||||
}
|
||||
|
||||
@@ -97,10 +94,7 @@ public static partial class DI
|
||||
/// <inheritdoc cref="Get_Nullable{T}"/>
|
||||
public static object? Get_Nullable(Type serviceType)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw GetDIGetFailException(serviceType);
|
||||
}
|
||||
if (value == null) return default;
|
||||
return value.GetService(serviceType);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,16 @@ public static partial class EnumExtensions
|
||||
/// <summary>
|
||||
/// 返回一个布尔值,该值指示给定的整数值或其名称字符串是否存在于指定的枚举中
|
||||
/// </summary>
|
||||
/// <typeparam name="TEnum"></typeparam>
|
||||
/// <param name="value"></param>
|
||||
/// <returns>如果 enumType 中的某个常量的值等于 value,则为 <see langword="true"/>;否则为 <see langword="false"/></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsDefined(this Enum value) => Enum.IsDefined(value.GetType(), value);
|
||||
public static bool IsDefined<TEnum>(this TEnum value) where TEnum : struct, Enum
|
||||
#if NET5_0_OR_GREATER
|
||||
=> Enum.IsDefined(value);
|
||||
#else
|
||||
=> Enum.IsDefined(typeof(TEnum), value);
|
||||
#endif
|
||||
|
||||
public static TEnum ConvertToEnum<TEnum>(this sbyte value)
|
||||
where TEnum : Enum
|
||||
|
||||
@@ -34,4 +34,23 @@ public static class ProcessExtensions
|
||||
process.Kill();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试 Process 组件在指定的毫秒数内等待关联进程退出。
|
||||
/// </summary>
|
||||
/// <param name="process"></param>
|
||||
/// <param name="milliseconds"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryWaitForExit(this Process process, int milliseconds = 9000)
|
||||
{
|
||||
try
|
||||
{
|
||||
return process.WaitForExit(milliseconds);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,11 @@ namespace System;
|
||||
|
||||
public static partial class StringExtensions
|
||||
{
|
||||
public static string TrimStart(this string s, string trimString)
|
||||
public static string TrimStart(this string s, string value)
|
||||
{
|
||||
if (trimString.StartsWith(trimString))
|
||||
if (s.StartsWith(value))
|
||||
{
|
||||
return s[trimString.Length..];
|
||||
return s[value.Length..];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -15,11 +15,11 @@ public static partial class StringExtensions
|
||||
}
|
||||
}
|
||||
|
||||
public static string TrimEnd(this string s, string trimString)
|
||||
public static string TrimEnd(this string s, string value)
|
||||
{
|
||||
if (trimString.EndsWith(trimString))
|
||||
if (s.EndsWith(value))
|
||||
{
|
||||
return s[..^trimString.Length];
|
||||
return s[..^value.Length];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -27,11 +27,11 @@ public static partial class StringExtensions
|
||||
}
|
||||
}
|
||||
|
||||
public static string TrimStart(this string s, string trimString, StringComparison comparisonType)
|
||||
public static string TrimStart(this string s, string value, StringComparison comparisonType)
|
||||
{
|
||||
if (trimString.StartsWith(trimString, comparisonType))
|
||||
if (s.StartsWith(value, comparisonType))
|
||||
{
|
||||
return s[trimString.Length..];
|
||||
return s[value.Length..];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -39,11 +39,11 @@ public static partial class StringExtensions
|
||||
}
|
||||
}
|
||||
|
||||
public static string TrimEnd(this string s, string trimString, StringComparison comparisonType)
|
||||
public static string TrimEnd(this string s, string value, StringComparison comparisonType)
|
||||
{
|
||||
if (trimString.EndsWith(trimString, comparisonType))
|
||||
if (s.EndsWith(value, comparisonType))
|
||||
{
|
||||
return s[..^trimString.Length];
|
||||
return s[..^value.Length];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -132,6 +132,11 @@ public static class FileEx
|
||||
public const string Qt = ".qt";
|
||||
public const string Wmv = ".wmv";
|
||||
|
||||
/// <summary>
|
||||
/// 导入注册条目 (.reg) 文件是 Regedit.exe 的功能,Regedt32.exe 不支持。您可以使用 Regedit.exe 对基于 Windows NT 4.0 或基于 Windows 2000 的计算机上注册表进行一些更改,但某些更改需要 Regedt32.exe。
|
||||
/// </summary>
|
||||
public const string Reg = ".reg";
|
||||
|
||||
public static readonly string[] ImageFileExtensions = new string[]
|
||||
{
|
||||
PNG,
|
||||
|
||||
@@ -153,6 +153,89 @@ public static class IOPath
|
||||
}
|
||||
}
|
||||
|
||||
static readonly object lock_GetCacheFilePath = new();
|
||||
|
||||
/// <summary>
|
||||
/// 根据缓存子文件夹名称与文件扩展名获取一个缓存文件路径
|
||||
/// </summary>
|
||||
/// <param name="dirName">缓存子文件夹名称</param>
|
||||
/// <param name="fileNamePrefix">文件名前缀</param>
|
||||
/// <param name="fileEx">文件扩展名</param>
|
||||
public static string GetCacheFilePath(string dirName, string fileNamePrefix, string fileEx)
|
||||
{
|
||||
lock (lock_GetCacheFilePath)
|
||||
{
|
||||
var cacheDirPath = Path.Combine(CacheDirectory, dirName);
|
||||
if (!Directory.Exists(cacheDirPath))
|
||||
{
|
||||
Directory.CreateDirectory(cacheDirPath);
|
||||
return GetCacheFilePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
string cacheFilePath;
|
||||
do
|
||||
{
|
||||
cacheFilePath = GetCacheFilePath();
|
||||
} while (File.Exists(cacheFilePath));
|
||||
return cacheFilePath;
|
||||
}
|
||||
|
||||
string GetCacheFilePath() => Path.Combine(cacheDirPath, GetCacheFileName());
|
||||
string GetCacheFileName() => $"{fileNamePrefix}_{DateTimeOffset.Now.Ticks}{Random2.GenerateRandomString(4)}{fileEx}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试延时一段时间后删除文件
|
||||
/// </summary>
|
||||
/// <param name="filePath">要删除的文件路径</param>
|
||||
/// <param name="millisecondsDelay">延时等待的毫秒数</param>
|
||||
public static async void TryDeleteInDelay(string filePath, int millisecondsDelay = 9000)
|
||||
{
|
||||
await Task.Delay(millisecondsDelay);
|
||||
FileTryDelete(filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动进程后尝试延时一段时间后删除文件
|
||||
/// </summary>
|
||||
/// <param name="process">启动的进程</param>
|
||||
/// <param name="filePath">要删除的文件路径</param>
|
||||
/// <param name="millisecondsDelay">延时等待的毫秒数</param>
|
||||
/// <param name="processWaitMillisecondsDelay">启动的进程等待退出的毫秒数</param>
|
||||
public static void TryDeleteInDelay(Process? process, string filePath, int millisecondsDelay = 9000, int processWaitMillisecondsDelay = 9000)
|
||||
{
|
||||
if (process != null)
|
||||
{
|
||||
var waitForExitResult = process.TryWaitForExit(processWaitMillisecondsDelay);
|
||||
if (!waitForExitResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
process.KillEntireProcessTree();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
TryDeleteInDelay(filePath, millisecondsDelay);
|
||||
return;
|
||||
}
|
||||
}
|
||||
FileTryDelete(filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试根据缓存子文件夹名称删除整个缓存子文件夹
|
||||
/// </summary>
|
||||
/// <param name="dirName">缓存子文件夹名称</param>
|
||||
public static void TryDeleteCacheSubDir(string dirName)
|
||||
{
|
||||
var cacheDirPath = Path.Combine(CacheDirectory, dirName);
|
||||
DirTryDelete(cacheDirPath);
|
||||
}
|
||||
|
||||
public abstract class FileSystemBase
|
||||
{
|
||||
protected FileSystemBase()
|
||||
@@ -291,6 +374,10 @@ public static class IOPath
|
||||
{
|
||||
paths[i] = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
DirCreateByNotExists(paths[i]);
|
||||
}
|
||||
}
|
||||
|
||||
InitFileSystem(GetAppDataDirectory, GetCacheDirectory);
|
||||
|
||||
@@ -15,7 +15,7 @@ public static class Log
|
||||
|
||||
static ILoggerFactory? factory;
|
||||
|
||||
public static ILoggerFactory Factory => factory ??= DI.Get_Nullable<ILoggerFactory>() ?? LoggerFactory?.Invoke() ?? throw new ArgumentNullException(nameof(LoggerFactory));
|
||||
public static ILoggerFactory Factory => factory ??= (DI.IsConfigured ? DI.Get<ILoggerFactory>() : null) ?? LoggerFactory?.Invoke() ?? throw new ArgumentNullException(nameof(LoggerFactory));
|
||||
|
||||
public static ILogger CreateLogger(string tag) => Factory.CreateLogger(tag);
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ partial class GeneralHttpClientFactory
|
||||
/// <summary>
|
||||
/// https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpNoProxy.cs
|
||||
/// </summary>
|
||||
sealed class HttpNoProxy : IWebProxy
|
||||
public sealed class HttpNoProxy : IWebProxy
|
||||
{
|
||||
public static readonly HttpNoProxy Instance = new();
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ public abstract class HttpPlatformHelperService : IHttpPlatformHelperService
|
||||
ImageFormat.JPEG,
|
||||
ImageFormat.PNG,
|
||||
ImageFormat.GIF,
|
||||
ImageFormat.WebP,
|
||||
ImageFormat.BMP,
|
||||
ImageFormat.ICO,
|
||||
});
|
||||
|
||||
public virtual ImageFormat[] SupportedImageFormats => mSupportedImageFormats.Value;
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
namespace System.Properties
|
||||
{
|
||||
static partial class ThisAssembly
|
||||
{
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// <para>在以下平台中还需要将版本号写入相关的清单文件:</para>
|
||||
/// <list type="bullet">
|
||||
/// <item> iOS:\src\ST.Client.Mobile.iOS.App\Info.plist <CFBundleVersion> <CFBundleShortVersionString> </item>
|
||||
/// <item> Android:\src\ST.Client.Mobile.Droid.App\Properties\AndroidManifest.xml <manifest ... android:versionCode(long递增) android:versionName </item>
|
||||
/// <item> UWP(DesktopBridge):\src\ST.Client.Desktop.Avalonia.App.Bridge.Package\Package.appxmanifest <Identity ... Version </item>
|
||||
/// <item> macOS:\packaging\build-osx-app.sh <CFBundleVersion> <CFBundleShortVersionString> </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public const string Version = "2.8.2";
|
||||
namespace System.Properties;
|
||||
|
||||
//public const string InfoVersion = Version + "-beta";
|
||||
}
|
||||
static partial class ThisAssembly
|
||||
{
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// <para>在以下平台中还需要将版本号写入相关的清单文件:</para>
|
||||
/// <list type="bullet">
|
||||
/// <item> iOS:\src\ST.Client.Mobile.iOS.App\Info.plist <CFBundleVersion> <CFBundleShortVersionString> </item>
|
||||
/// <item> Android:\src\ST.Client.Mobile.Droid.App\Properties\AndroidManifest.xml <manifest ... android:versionCode(long递增) android:versionName </item>
|
||||
/// <item> UWP(DesktopBridge):\src\ST.Client.Desktop.Avalonia.App.Bridge.Package\Package.appxmanifest <Identity ... Version </item>
|
||||
/// <item> macOS:\packaging\build-osx-app.sh <CFBundleVersion> <CFBundleShortVersionString> </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public const string Version = "2.8.6";
|
||||
|
||||
//public const string InfoVersion = Version + "-beta";
|
||||
}
|
||||
@@ -190,6 +190,13 @@ namespace System
|
||||
|
||||
#endregion
|
||||
|
||||
// https://learn.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json/character-casing#case-insensitive-property-matching
|
||||
|
||||
static readonly SJsonSerializerOptions S_options = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
};
|
||||
|
||||
#region Deserialize(反序列化)
|
||||
|
||||
/// <summary>
|
||||
@@ -204,7 +211,7 @@ namespace System
|
||||
{
|
||||
return implType switch
|
||||
{
|
||||
JsonImplType.SystemTextJson => SJsonSerializer.Deserialize<T>(value),
|
||||
JsonImplType.SystemTextJson => SJsonSerializer.Deserialize<T>(value, S_options),
|
||||
_ =>
|
||||
#if NOT_NJSON
|
||||
throw new NotSupportedException(),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!--<TargetFrameworks>MonoAndroid12.0;netstandard2.1;net6.0-android</TargetFrameworks>-->
|
||||
<TargetFrameworks>MonoAndroid12.0;netstandard2.1</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.1</TargetFrameworks>
|
||||
<RootNamespace>System</RootNamespace>
|
||||
<AssemblyName>System.Common.PinyinLib.TinyPinyin</AssemblyName>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace System.Net.Http;
|
||||
|
||||
public sealed class ReverseProxyHttpClientHandler : DelegatingHandler
|
||||
{
|
||||
readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d);
|
||||
|
||||
public ReverseProxyHttpClientHandler()
|
||||
{
|
||||
InnerHandler = new SocketsHttpHandler()
|
||||
{
|
||||
Proxy = GeneralHttpClientFactory.HttpNoProxy.Instance,
|
||||
UseProxy = false,
|
||||
UseCookies = false,
|
||||
AllowAutoRedirect = false,
|
||||
AutomaticDecompression = DecompressionMethods.None,
|
||||
ConnectCallback = ConnectCallback,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送请求
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var uri = request.RequestUri;
|
||||
if (uri == null)
|
||||
{
|
||||
throw new ApplicationException("The requested URI must be specified.");
|
||||
}
|
||||
|
||||
// 设置请求头 host,修改协议为 http
|
||||
request.Headers.Host = uri.Host;
|
||||
request.RequestUri = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp }.Uri;
|
||||
|
||||
return await base.SendAsync(request, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接回调
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
async ValueTask<Stream> ConnectCallback(SocketsHttpConnectionContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
var innerExceptions = new List<Exception>();
|
||||
var ipEndPoints = (await Dns.GetHostAddressesAsync("steamcommunity.rmbgame.net", cancellationToken)).Select(s => new IPEndPoint(s, context.DnsEndPoint.Port));
|
||||
|
||||
foreach (var ipEndPoint in ipEndPoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var timeoutTokenSource = new CancellationTokenSource(connectTimeout);
|
||||
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutTokenSource.Token, cancellationToken);
|
||||
return await ConnectAsync(context, ipEndPoint, linkedTokenSource.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
innerExceptions.Add(new TimeoutException(
|
||||
$"HTTP connection to {ipEndPoint.Address} timed out."));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
innerExceptions.Add(ex);
|
||||
}
|
||||
}
|
||||
|
||||
throw new AggregateException("Could not find any IP that can be successfully connected.", innerExceptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 建立连接
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="ipEndPoint"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
static async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext context, IPEndPoint ipEndPoint, CancellationToken cancellationToken)
|
||||
{
|
||||
var socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
await socket.ConnectAsync(ipEndPoint, cancellationToken);
|
||||
var stream = new NetworkStream(socket, ownsSocket: true);
|
||||
|
||||
if (context.DnsEndPoint.Port != 443)
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
var sslStream = new SslStream(stream, leaveInnerStreamOpen: false);
|
||||
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
|
||||
{
|
||||
TargetHost = string.Empty,
|
||||
RemoteCertificateValidationCallback = (_, _, _, _) => true,
|
||||
}, cancellationToken);
|
||||
|
||||
return sslStream;
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,10 @@ internal static class Program
|
||||
{
|
||||
const string ExecutiveName = "Steam++";
|
||||
static BundleArch matchArch;
|
||||
static readonly SemanticVersion runtimeVersion = new(6, 0, 7);
|
||||
static readonly SemanticVersion sdkVersion = new(6, 0, 107);
|
||||
static readonly SemanticVersion runtimeVersion = new(6, 0, 12);
|
||||
static readonly SemanticVersion sdkVersion1 = new(6, 0, 112);
|
||||
static readonly SemanticVersion sdkVersion3 = new(6, 0, 307);
|
||||
static readonly SemanticVersion sdkVersion4 = new(6, 0, 404);
|
||||
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点。
|
||||
@@ -56,7 +58,7 @@ internal static class Program
|
||||
if (RuntimeInformation2.OSArchitecture != Architecture.Arm64) throw new PlatformNotSupportedException();
|
||||
break;
|
||||
}
|
||||
if (IsRuntimeInstalled(matchArch, runtimeVersion, sdkVersion))
|
||||
if (IsRuntimeInstalled(matchArch, runtimeVersion, sdkVersion1, sdkVersion3, sdkVersion4))
|
||||
{
|
||||
Run();
|
||||
}
|
||||
@@ -193,7 +195,7 @@ internal static class Program
|
||||
/// 是否已安装运行时或 SDK
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
static bool IsRuntimeInstalled(BundleArch matchArch, SemanticVersion runtimeVersion, SemanticVersion sdkVersion)
|
||||
static bool IsRuntimeInstalled(BundleArch matchArch, SemanticVersion runtimeVersion, SemanticVersion sdkVersion1, SemanticVersion sdkVersion3, SemanticVersion sdkVersion4)
|
||||
{
|
||||
// ArchiSteamFarm 依赖 ASP.NET Core
|
||||
// ASP.NET Core 运行时安装程序除 Hosting Bundle 不包含 .NET 运行时 缺少文件 C:\Program Files\dotnet\host\fxr\{version}\hostfxr.dll
|
||||
@@ -202,7 +204,12 @@ internal static class Program
|
||||
// https://github.com/dotnet/runtime/blob/v6.0.5/src/native/corehost/apphost/apphost.windows.cpp#L106-L113
|
||||
var installed = RegistryQuery.GetAllInstalledBundles().Where(m => m.Arch.HasFlags(matchArch)).ToArray();
|
||||
|
||||
var query_sdk = installed.Where(m => m.Version.Type == BundleType.Sdk && m.Version.SemVer >= sdkVersion);
|
||||
var query_sdk = installed.Where(m => m.Version.Type == BundleType.Sdk &&
|
||||
(
|
||||
(m.Version.SemVer >= sdkVersion1 && m.Version.SemVer < new SemanticVersion(sdkVersion1.Major, sdkVersion1.Minor, 199)) ||
|
||||
(m.Version.SemVer >= sdkVersion3 && m.Version.SemVer < new SemanticVersion(sdkVersion3.Major, sdkVersion3.Minor, 399)) ||
|
||||
(m.Version.SemVer >= sdkVersion4 && m.Version.SemVer < new SemanticVersion(sdkVersion4.Major, sdkVersion4.Minor, 499))
|
||||
));
|
||||
if (query_sdk.Any()) return true;
|
||||
|
||||
var query_runtime = installed.Where(m => (m.Version.Type == BundleType.Runtime || m.Version.Type == BundleType.WindowsDesktopRuntime) && m.Version.SemVer >= runtimeVersion);
|
||||
|
||||
@@ -5,6 +5,6 @@ namespace System.Properties
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// </summary>
|
||||
public const string Version = "1.1.0";
|
||||
public const string Version = "1.1.11";
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>false</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>$(MSBuildProjectDirectory)\..\..\avalonia.snk</AssemblyOriginatorKeyFile>
|
||||
<Version>2.2.255.255</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\AssemblyInfo.Version.Max.cs">
|
||||
<LinkBase>Properties</LinkBase>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Primitives" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220725" android:versionName="2.8.2" package="net.steampp.app" android:installLocation="auto">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220803" android:versionName="2.8.3" package="net.steampp.app" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
|
||||
<application android:fullBackupContent="@xml/auto_backup_rules"></application>
|
||||
<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
<AotAssemblies>false</AotAssemblies>
|
||||
<EnableLLVM>false</EnableLLVM>
|
||||
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<AndroidLinkMode>Full</AndroidLinkMode>
|
||||
<AndroidLinkTool>r8</AndroidLinkTool>
|
||||
<PublishTrimmed>false</PublishTrimmed>
|
||||
<AndroidFragmentType>AndroidX.Fragment.App.Fragment</AndroidFragmentType>
|
||||
</PropertyGroup>
|
||||
@@ -187,7 +188,7 @@
|
||||
<PackageReference Include="Xamarin.Build.Download" />
|
||||
<!--<PackageReference Include="Xamarin.AndroidX.Window" />-->
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<AndroidAsset Include="..\..\references\Android Assets\cncity.txt" Link="Assets\cncity.txt" />
|
||||
</ItemGroup>
|
||||
@@ -553,6 +554,9 @@
|
||||
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_toolbar_tablayout_viewpager2.xml">
|
||||
<Link>Resources\layout\activity_toolbar_tablayout_viewpager2.xml</Link>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_toolbar_webview.xml">
|
||||
<Link>Resources\layout\activity_toolbar_webview.xml</Link>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_about.xml">
|
||||
<Link>Resources\layout\fragment_about.xml</Link>
|
||||
</AndroidResource>
|
||||
|
||||
@@ -149,6 +149,7 @@
|
||||
<PackageReference Include="Xamarin.Google.MLKit.BarcodeScanning" />
|
||||
<PackageReference Include="Xamarin.Build.Download" />
|
||||
<!--<PackageReference Include="Xamarin.AndroidX.Window" />-->
|
||||
<PackageReference Include="Microsoft.Net.Http.Headers" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace System.Application.UI
|
||||
VisualStudioAppCenterSDK.Init();
|
||||
}
|
||||
|
||||
void IApplication.IProgramHost.ConfigureServices(DILevel level) => ConfigureServices(this, level);
|
||||
void IApplication.IProgramHost.ConfigureServices(DILevel level, bool isTrace) => ConfigureServices(this, level, isTrace: isTrace);
|
||||
|
||||
void IApplication.IProgramHost.OnStartup() => OnStartup(this);
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace System.Application.UI
|
||||
var level = DILevel.Min;
|
||||
if (IsMainProcess) level = DILevel.MainProcess;
|
||||
IApplication.IProgramHost host = this;
|
||||
host.ConfigureServices(level);
|
||||
host.ConfigureServices(level, isTrace);
|
||||
if (isTrace) StartWatchTrace.Record("Startup");
|
||||
|
||||
if (IsMainProcess)
|
||||
@@ -125,8 +125,6 @@ namespace System.Application.UI
|
||||
|
||||
if (IsMainProcess)
|
||||
{
|
||||
var vmService = IViewModelManager.Instance;
|
||||
|
||||
#if __XAMARIN_FORMS__
|
||||
Forms.Init(this, null);
|
||||
FormsMaterial.Init(this, null);
|
||||
@@ -136,8 +134,6 @@ namespace System.Application.UI
|
||||
_Current = new(RealTheme);
|
||||
if (isTrace) StartWatchTrace.Record("XFApp");
|
||||
#endif
|
||||
vmService.MainWindow!.Initialize();
|
||||
if (isTrace) StartWatchTrace.Record("MainVM.Init");
|
||||
}
|
||||
|
||||
StartupTrack = StartWatchTrace.ToString();
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!--<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-android;net6.0-windows</TargetFrameworks>-->
|
||||
<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-windows</TargetFrameworks>
|
||||
<!--<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-windows</TargetFrameworks>-->
|
||||
<TargetFrameworks>net6.0-windows</TargetFrameworks>
|
||||
<RootNamespace>System.Application.AppCenter</RootNamespace>
|
||||
<AssemblyName>System.Application.SteamTools.Client.AppCenter</AssemblyName>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
@@ -23,7 +23,7 @@ public abstract class CommandLineHost : IDisposable
|
||||
|
||||
protected abstract IApplication.IDesktopProgramHost Host { get; }
|
||||
|
||||
protected abstract void ConfigureServices(DILevel level);
|
||||
protected abstract void ConfigureServices(DILevel level, bool isTrace = false);
|
||||
|
||||
#if StartWatchTrace
|
||||
protected abstract void StartWatchTraceRecord(string? mark = null, bool dispose = false);
|
||||
@@ -136,15 +136,22 @@ public abstract class CommandLineHost : IDisposable
|
||||
void ProxyMessageReceived()
|
||||
{
|
||||
var value = Enum.TryParse<EOnOff>(args[1], out var value_) ? value_ : default;
|
||||
MainThread2.BeginInvokeOnMainThread(() =>
|
||||
try
|
||||
{
|
||||
ProxyService.Current.ProxyStatus = value switch
|
||||
MainThread2.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
EOnOff.On => true,
|
||||
EOnOff.Off => false,
|
||||
_ => !ProxyService.Current.ProxyStatus,
|
||||
};
|
||||
});
|
||||
ProxyService.Current.ProxyStatus = value switch
|
||||
{
|
||||
EOnOff.On => true,
|
||||
EOnOff.Off => false,
|
||||
_ => !ProxyService.Current.ProxyStatus,
|
||||
};
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -152,8 +159,15 @@ public abstract class CommandLineHost : IDisposable
|
||||
break;
|
||||
}
|
||||
}
|
||||
var app = await WaitForApplicationAsync();
|
||||
MainThread2.BeginInvokeOnMainThread(app.RestoreMainWindow);
|
||||
try
|
||||
{
|
||||
var app = await WaitForApplicationAsync();
|
||||
MainThread2.BeginInvokeOnMainThread(app.RestoreMainWindow);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
//#if StartWatchTrace
|
||||
@@ -231,7 +245,7 @@ public abstract class CommandLineHost : IDisposable
|
||||
// -clt steam -account
|
||||
var steamuser = new Command("steam", "Steam 相关操作");
|
||||
steamuser.AddOption(new Option<string>("-account", "指定对应 Steam 用户名"));
|
||||
steamuser.Handler = CommandHandler.Create(async (string account) =>
|
||||
steamuser.Handler = CommandHandler.Create((string account) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(account))
|
||||
{
|
||||
@@ -243,7 +257,7 @@ public abstract class CommandLineHost : IDisposable
|
||||
|
||||
var currentuser = users.Where(s => s.AccountName == account).FirstOrDefault();
|
||||
|
||||
await steamService.ShutdownSteamAsync();
|
||||
steamService.TryKillSteamProcess();
|
||||
|
||||
if (currentuser != null)
|
||||
{
|
||||
@@ -252,7 +266,7 @@ public abstract class CommandLineHost : IDisposable
|
||||
steamService.SetCurrentUser(account);
|
||||
}
|
||||
|
||||
steamService.StartSteam();
|
||||
steamService.StartSteamWithParameter();
|
||||
}
|
||||
});
|
||||
rootCommand.AddCommand(steamuser);
|
||||
@@ -297,27 +311,27 @@ public abstract class CommandLineHost : IDisposable
|
||||
|
||||
// -clt show -config -cert
|
||||
var show = new Command("show", "显示信息");
|
||||
show.AddOption(new Option<bool>("-config", "显示 Config.mpo 值"));
|
||||
//show.AddOption(new Option<bool>("-config", "显示 Config.mpo 值"));
|
||||
show.AddOption(new Option<bool>("-cert", "显示当前根证书信息"));
|
||||
show.Handler = CommandHandler.Create((bool config, bool cert) =>
|
||||
show.Handler = CommandHandler.Create((/*bool config,*/ bool cert) =>
|
||||
{
|
||||
if (OperatingSystem.IsWindows()) if (!AttachConsole()) AllocConsole();
|
||||
|
||||
if (config)
|
||||
{
|
||||
Console.WriteLine("Config: ");
|
||||
try
|
||||
{
|
||||
SettingsHost.Load();
|
||||
var configValue = SettingsHostBase.Local.ToJsonString();
|
||||
Console.WriteLine(configValue);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
//if (config)
|
||||
//{
|
||||
// Console.WriteLine("Config: ");
|
||||
// try
|
||||
// {
|
||||
// SettingsHost.Load();
|
||||
// var configValue = SettingsHostBase.Local.ToJsonString();
|
||||
// Console.WriteLine(configValue);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Console.WriteLine(e.ToString());
|
||||
// }
|
||||
// Console.WriteLine();
|
||||
//}
|
||||
|
||||
if (cert)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<Identity
|
||||
Name="4651ED44255E.47979655102CE"
|
||||
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
|
||||
Version="2.8.1.0" />
|
||||
Version="2.8.6.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Watt Toolkit</DisplayName>
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Application.Settings;
|
||||
using System.Application.CommandLine;
|
||||
using System.Application.UI.Resx;
|
||||
using NLog;
|
||||
using Avalonia;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Controls;
|
||||
using System.Net.Http;
|
||||
|
||||
#if WINDOWS || WINDOWS_DESKTOP_BRIDGE
|
||||
using WPFMessageBox = System.Windows.MessageBox;
|
||||
using WPFMessageBoxButton = System.Windows.MessageBoxButton;
|
||||
using WPFMessageBoxImage = System.Windows.MessageBoxImage;
|
||||
#endif
|
||||
|
||||
#if MAC
|
||||
[assembly: SupportedOSPlatform("macOS")]
|
||||
@@ -39,17 +48,46 @@ namespace System.Application.UI
|
||||
// fix The request was aborted: Could not create SSL/TLS secure channel
|
||||
TrySetSecurityProtocol();
|
||||
|
||||
var host = ProgramHost.Instance;
|
||||
|
||||
host.IsMainProcess = args.Length == 0;
|
||||
host.IsCLTProcess = !host.IsMainProcess && args.FirstOrDefault() == "-clt";
|
||||
#if WINDOWS || WINDOWS_DESKTOP_BRIDGE
|
||||
HttpClient.DefaultProxy = DynamicHttpWindowsProxy.Instance;
|
||||
#endif
|
||||
|
||||
#if WINDOWS_DESKTOP_BRIDGE
|
||||
if (!DesktopBridgeHelper.Init()) return 0;
|
||||
InitWithUWP(ref args);
|
||||
#elif WINDOWS
|
||||
//#if NET7_0_OR_GREATER
|
||||
// if (/*Environment.Version >= new Version(7, 0) && */!OperatingSystem2.IsWindows10AtLeast())
|
||||
// {
|
||||
// // [TBD] .NET 7 中考虑弃用对 Windows 7/2008 R2/8.1/2012 R2 的支持
|
||||
// WPFMessageBox.Show("TBD", AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
|
||||
// return 0;
|
||||
// }
|
||||
//#endif
|
||||
if (OperatingSystem2.IsWindows10AtLeast() &&
|
||||
!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 14393))
|
||||
{
|
||||
// Win10 最低需要 1607,低于此版本则弹窗错误中止运行
|
||||
// appcenter.ms 上有 10240,10586 的 crash 报告
|
||||
WPFMessageBox.Show(AppResources.Error_Lower_Than_Windows10_1607, AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
|
||||
return 0;
|
||||
}
|
||||
if (AppContext.BaseDirectory.StartsWith(Path.GetTempPath(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// 检测当前目录 Temp\Rar$ 这类目录,可能是在压缩包中直接启动程序导致的,还有一堆 文件找不到/加载失败的异常
|
||||
// System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\USER\AppData\Local\Temp\Rar$EXa15528.13350\Cache\switchproxy.reg'.
|
||||
// System.IO.FileLoadException ...
|
||||
// System.IO.FileNotFoundException: Could not load file or assembly ...
|
||||
WPFMessageBox.Show(AppResources.Error_BaseDir_StartsWith_Temp, AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
|
||||
return 0;
|
||||
}
|
||||
#elif MAC
|
||||
InitWithMAC(args);
|
||||
#endif
|
||||
var host = ProgramHost.Instance;
|
||||
host.IsMainProcess = args.Length == 0;
|
||||
host.IsCLTProcess = !host.IsMainProcess && args.FirstOrDefault() == "-clt";
|
||||
|
||||
OnCreateAppExecuting();
|
||||
// InitCefNetApp(args);
|
||||
|
||||
@@ -87,7 +125,7 @@ namespace System.Application.UI
|
||||
{
|
||||
ServicePointManager.SecurityProtocol = type;
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
@@ -205,7 +243,7 @@ namespace System.Application.UI
|
||||
static void StartAvaloniaApp(string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
|
||||
{
|
||||
var builder = BuildAvaloniaApp();
|
||||
builder.StartWithClassicDesktopLifetime(args, shutdownMode);
|
||||
builder.StartWithClassicDesktopLifetime2(args, shutdownMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ static partial class
|
||||
|
||||
public EOnOff ProxyStatus { get; set; }
|
||||
|
||||
void IApplication.IProgramHost.ConfigureServices(DILevel level) => ConfigureServices(level);
|
||||
void IApplication.IProgramHost.ConfigureServices(DILevel level, bool isTrace) => ConfigureServices(level, isTrace);
|
||||
|
||||
public void InitVisualStudioAppCenterSDK()
|
||||
{
|
||||
@@ -55,6 +55,14 @@ static partial class
|
||||
IApplication IApplication.IProgramHost.Application => App.Instance;
|
||||
|
||||
void IApplication.IDesktopProgramHost.OnCreateAppExecuted(Action<IViewModelManager>? handlerViewModelManager, bool isTrace) => Program.OnCreateAppExecuted(this, handlerViewModelManager, isTrace);
|
||||
|
||||
DeploymentMode IApplication.IDesktopProgramHost.DeploymentMode => DeploymentMode.
|
||||
#if FRAMEWORK_DEPENDENT || !PUBLISH
|
||||
FDE
|
||||
#else
|
||||
SCD
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
partial class ProgramHost : CommandLineHost
|
||||
@@ -63,7 +71,7 @@ static partial class
|
||||
|
||||
public Action<DILevel>? ConfigureServicesDelegate { get; set; }
|
||||
|
||||
protected override void ConfigureServices(DILevel level)
|
||||
protected override void ConfigureServices(DILevel level, bool isTrace = false)
|
||||
{
|
||||
if (ConfigureServicesDelegate != null)
|
||||
{
|
||||
@@ -71,7 +79,7 @@ static partial class
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.ConfigureServices(this, level);
|
||||
Program.ConfigureServices(this, level, isTrace: isTrace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,14 +32,22 @@
|
||||
<DefineConstants>MAC;PUBLISH;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(ExtraDefineConstants)' == 'win-x64' Or '$(ExtraDefineConstants)' == 'dev-win-x64' ">
|
||||
<PropertyGroup Condition=" '$(ExtraDefineConstants)' == 'win-x64' Or '$(ExtraDefineConstants)' == 'dev-win-x64' Or '$(ExtraDefineConstants)' == 'win-x86' Or '$(ExtraDefineConstants)' == 'dev-win-x86' ">
|
||||
<DefineConstants>PUBLISH;PUBLISH_WIN7;WINDOWS;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(ExtraDefineConstants)' == 'fd-win-x64' Or '$(ExtraDefineConstants)' == 'dev-fd-win-x64' ">
|
||||
<PropertyGroup Condition=" '$(ExtraDefineConstants)' == 'win-arm64' Or '$(ExtraDefineConstants)' == 'dev-arm64' ">
|
||||
<DefineConstants>PUBLISH;WINDOWS;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(ExtraDefineConstants)' == 'fd-win-x64' Or '$(ExtraDefineConstants)' == 'dev-fd-win-x64' Or '$(ExtraDefineConstants)' == 'fd-win-x86' Or '$(ExtraDefineConstants)' == 'dev-fd-win-x86' ">
|
||||
<DefineConstants>FRAMEWORK_DEPENDENT;PUBLISH;PUBLISH_WIN7;WINDOWS;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(ExtraDefineConstants)' == 'fd-win-arm64' Or '$(ExtraDefineConstants)' == 'dev-fd-arm64' ">
|
||||
<DefineConstants>FRAMEWORK_DEPENDENT;PUBLISH;WINDOWS;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or $(ExtraDefineConstants.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
|
||||
<DefineConstants>WINDOWS;$(DefineConstants)</DefineConstants>
|
||||
<ApplicationIcon>..\ST.Client.Desktop.Avalonia\Application\UI\Assets\Icon.ico</ApplicationIcon>
|
||||
|
||||
@@ -482,7 +482,15 @@ namespace System.Application.UI
|
||||
#endif
|
||||
//AppHelper.TryShutdown();
|
||||
|
||||
INotificationService.ILifeCycle.Instance?.OnShutdown();
|
||||
try
|
||||
{
|
||||
// https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/952960442u/overview
|
||||
INotificationService.ILifeCycle.Instance?.OnShutdown();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyIcon_Click(object? sender, EventArgs e)
|
||||
@@ -667,12 +675,6 @@ namespace System.Application.UI
|
||||
|
||||
object IApplication.CurrentPlatformUIHost => MainWindow!;
|
||||
|
||||
DeploymentMode IApplication.DeploymentMode => DeploymentMode.
|
||||
#if FRAMEWORK_DEPENDENT || !PUBLISH
|
||||
FDE
|
||||
#else
|
||||
SCD
|
||||
#endif
|
||||
;
|
||||
DeploymentMode IApplication.DeploymentMode => ProgramHost.DeploymentMode;
|
||||
}
|
||||
}
|
||||
@@ -253,7 +253,7 @@ namespace System.Application.UI
|
||||
//#endif
|
||||
// }
|
||||
static NativeMenuItem? exitMenuItem;
|
||||
static Dictionary<TabItemViewModel, NativeMenuItem>? tabItems;
|
||||
static Dictionary<TabItemViewModel.TabItemId, NativeMenuItem>? tabItems;
|
||||
|
||||
static IDisposable? InitMenuItems(NativeMenu menu)
|
||||
{
|
||||
@@ -262,19 +262,15 @@ namespace System.Application.UI
|
||||
#else
|
||||
MainWindowViewModel main = new();
|
||||
#endif
|
||||
var query = from x in main.AllTabItems
|
||||
let tabItem = x is TabItemViewModel item ? item : null
|
||||
where tabItem != null
|
||||
select tabItem;
|
||||
tabItems = new();
|
||||
foreach (var item in query)
|
||||
foreach (var item in main.AllTabIdItems)
|
||||
{
|
||||
var menuItem = new NativeMenuItem
|
||||
{
|
||||
Header = item.Name,
|
||||
Header = TabItemViewModel.GetName(item),
|
||||
Command = ReactiveCommand.Create(() =>
|
||||
{
|
||||
OnMenuClick(item.Id);
|
||||
OnMenuClick(item);
|
||||
}),
|
||||
};
|
||||
tabItems.Add(item, menuItem);
|
||||
@@ -299,7 +295,7 @@ namespace System.Application.UI
|
||||
}
|
||||
foreach (var item in tabItems)
|
||||
{
|
||||
item.Value.Header = item.Key.Name;
|
||||
item.Value.Header = TabItemViewModel.GetName(item.Key);
|
||||
}
|
||||
});
|
||||
#else
|
||||
|
||||
+3
-3
@@ -193,15 +193,15 @@
|
||||
Margin="10">
|
||||
<controls:ScrollingTextBlock Text="{Binding Name}" Classes="h6 semibold"/>
|
||||
<!--Foreground="#D22222"-->
|
||||
<!--<controls:ScrollingTextBlock Text="{Binding Amount,Converter={StaticResource StringFormatConverter},ConverterParameter={ReflectionBinding CurrencyCode}}"/>-->
|
||||
<controls:ScrollingTextBlock>
|
||||
<controls:ScrollingTextBlock Text="{Binding Amount,Converter={StaticResource StringFormatConverter},ConverterParameter={ReflectionBinding CurrencyCode}}"/>
|
||||
<!--<controls:ScrollingTextBlock>
|
||||
<controls:ScrollingTextBlock.Text>
|
||||
<MultiBinding Converter="{StaticResource StringFormatConverter}" ConverterParameter="money">
|
||||
<Binding Path="Amount"/>
|
||||
<Binding Path="CurrencyCode"/>
|
||||
</MultiBinding>
|
||||
</controls:ScrollingTextBlock.Text>
|
||||
</controls:ScrollingTextBlock>
|
||||
</controls:ScrollingTextBlock>-->
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
+3
-3
@@ -34,7 +34,7 @@ namespace System.Application.UI.Views.Pages
|
||||
EnableNullSplitting = false,
|
||||
DataLabelsSize = 12,
|
||||
Stroke = LiveChartsSkiaSharp.DefaultPaint,
|
||||
TooltipLabelFormatter = (e) => $"{AppResources.Upload} {IOPath.GetDisplayFileSizeString(e.PrimaryValue)}/s",
|
||||
TooltipLabelFormatter = (e) => $"Upload {IOPath.GetDisplayFileSizeString(e.PrimaryValue)}/s",
|
||||
Mapping = (rate, point) =>
|
||||
{
|
||||
point.PrimaryValue = rate.Rate;
|
||||
@@ -51,7 +51,7 @@ namespace System.Application.UI.Views.Pages
|
||||
EnableNullSplitting = false,
|
||||
DataLabelsSize = 12,
|
||||
Stroke = LiveChartsSkiaSharp.DefaultPaint,
|
||||
TooltipLabelFormatter = (e) => $"{AppResources.Download} {IOPath.GetDisplayFileSizeString(e.PrimaryValue)}/s",
|
||||
TooltipLabelFormatter = (e) => $"Download {IOPath.GetDisplayFileSizeString(e.PrimaryValue)}/s",
|
||||
Mapping = (rate, point) =>
|
||||
{
|
||||
point.PrimaryValue = rate.Rate;
|
||||
@@ -160,7 +160,7 @@ namespace System.Application.UI.Views.Pages
|
||||
chart.Series = new ISeries[] { readSeries, writeSeries };
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
catch
|
||||
{
|
||||
}
|
||||
finally
|
||||
|
||||
+7
@@ -39,6 +39,13 @@
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{ReflectionBinding Path=Res.Settings_Steam_RunSteamChina,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
|
||||
<ToggleSwitch IsChecked="{ReflectionBinding Source={x:Static ms:SteamSettings.IsRunSteamChina},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="Item">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{ReflectionBinding Path=Res.Settings_Steam_CheckSteamRuningNotification,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
|
||||
|
||||
@@ -94,13 +94,13 @@
|
||||
<Border.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding #u.DataContext.SteamId_Click}"
|
||||
Command="{ReflectionBinding #u.DataContext.SteamId_ClickCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{ReflectionBinding Path=Res.UserChange_BtnText,
|
||||
Mode=OneWay,
|
||||
Source={x:Static resx:R.Current}}" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_Click}"
|
||||
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_ClickCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{ReflectionBinding Path=Res.UserChange_OfflineBtn,
|
||||
Mode=OneWay,
|
||||
@@ -231,7 +231,7 @@
|
||||
Source={x:Static resx:R.Current}}">
|
||||
<i:Interaction.Behaviors>
|
||||
<ia:EventTriggerBehavior EventName="Tapped" SourceObject="{ReflectionBinding #nickname}">
|
||||
<ia:InvokeCommandAction Command="{ReflectionBinding #u.DataContext.SteamId_Click}" CommandParameter="{Binding}" />
|
||||
<ia:InvokeCommandAction Command="{ReflectionBinding #u.DataContext.SteamId_ClickCommand}" CommandParameter="{Binding}" />
|
||||
</ia:EventTriggerBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
</controls:ScrollingTextBlock>
|
||||
@@ -343,7 +343,7 @@
|
||||
Mode=OneWay,
|
||||
Source={x:Static resx:R.Current}}"
|
||||
Classes="flatbutton"
|
||||
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_Click}"
|
||||
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_ClickCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Cursor="Hand">
|
||||
<controls:ScrollingTextBlock Text="{ReflectionBinding Path=Res.UserChange_OfflineBtn, Mode=OneWay, Source={x:Static resx:R.Current}}" />
|
||||
@@ -359,7 +359,7 @@
|
||||
MaxWidth="250"
|
||||
HorizontalAlignment="Stretch"
|
||||
Classes="flatbutton"
|
||||
Command="{ReflectionBinding #u.DataContext.SteamId_Click}"
|
||||
Command="{ReflectionBinding #u.DataContext.SteamId_ClickCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Cursor="Hand">
|
||||
<controls:ScrollingTextBlock Text="{ReflectionBinding Path=Res.UserChange_BtnText, Mode=OneWay, Source={x:Static resx:R.Current}}" />
|
||||
|
||||
+26
-8
@@ -1,19 +1,37 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using System.Application.Services;
|
||||
|
||||
namespace System.Application.UI.Views.Pages
|
||||
namespace System.Application.UI.Views.Pages;
|
||||
|
||||
public partial class UserItem : UserControl
|
||||
{
|
||||
public partial class UserItem : UserControl
|
||||
public UserItem()
|
||||
{
|
||||
public UserItem()
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (UserService.Current.User != null)
|
||||
{
|
||||
InitializeComponent();
|
||||
var lastSignInTime = UserService.Current.LastSignInTime;
|
||||
if (lastSignInTime.HasValue)
|
||||
{
|
||||
if (DateTimeOffset.Now - lastSignInTime.Value >= TimeSpan.FromDays(1))
|
||||
{
|
||||
UserService.Current.User.IsSignIn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
}
|
||||
}
|
||||
|
||||
+16
-6
@@ -48,6 +48,12 @@
|
||||
Maximum="65535"/>
|
||||
</DockPanel>-->
|
||||
|
||||
<!--<DockPanel>
|
||||
<TextBlock Text="IPV6支持:" />
|
||||
<TextBlock Text="IPV6地址" ></TextBlock>
|
||||
<Button Content="{ReflectionBinding Path=Res.Refresh,Mode=OneWay,Source={x:Static resx:R.Current}}"></Button>
|
||||
</DockPanel>-->
|
||||
|
||||
<DockPanel>
|
||||
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_AutoRunProxy,Mode=OneWay,Source={x:Static resx:R.Current}}" ></TextBlock>
|
||||
<ToggleSwitch
|
||||
@@ -59,13 +65,13 @@
|
||||
<ToggleSwitch
|
||||
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.OnlyEnableProxyScript},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>
|
||||
|
||||
|
||||
<DockPanel>
|
||||
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_EnableHttpProxyToHttps,Mode=OneWay,Source={x:Static resx:R.Current}}" ></TextBlock>
|
||||
<ToggleSwitch
|
||||
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.EnableHttpProxyToHttps},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>
|
||||
|
||||
|
||||
<!--<DockPanel>
|
||||
<Label Content="自定义根证书密码"></Label>
|
||||
<TextBox></TextBox>
|
||||
@@ -86,11 +92,13 @@
|
||||
</DockPanel>
|
||||
</Expander.Header>
|
||||
<StackPanel Spacing="10">
|
||||
--><!--<DockPanel>
|
||||
-->
|
||||
<!--<DockPanel>
|
||||
<TextBlock Text="启用" ></TextBlock>
|
||||
<ToggleSwitch
|
||||
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.Socks5ProxyEnable},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>--><!--
|
||||
</DockPanel>-->
|
||||
<!--
|
||||
<DockPanel>
|
||||
<Label Content="{ReflectionBinding Path=Res.Settings_Proxy_ProxyPort,Mode=OneWay,Source={x:Static resx:R.Current}}"></Label>
|
||||
<NumericUpDown Maximum="65535"
|
||||
@@ -109,11 +117,13 @@
|
||||
</DockPanel>
|
||||
</Expander.Header>
|
||||
<StackPanel Spacing="10">
|
||||
--><!--<DockPanel>
|
||||
-->
|
||||
<!--<DockPanel>
|
||||
<TextBlock Text="启用" ></TextBlock>
|
||||
<ToggleSwitch
|
||||
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.TwoLevelAgentEnable},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>--><!--
|
||||
</DockPanel>-->
|
||||
<!--
|
||||
|
||||
<DockPanel>
|
||||
<Label Content="{ReflectionBinding Path=Res.Settings_Proxy_ProxyType,Mode=OneWay,Source={x:Static resx:R.Current}}"></Label>
|
||||
|
||||
@@ -89,6 +89,27 @@ namespace System.Application.Services.Implementation
|
||||
|
||||
ValueTask IPlatformService.RunShellAsync(string script, bool admin) => RunShellAsync(script, admin);
|
||||
|
||||
async ValueTask<bool?> IPlatformService.TrustRootCertificate(string filePath)
|
||||
{
|
||||
var script = $"security add-trusted-cert -d -r trustRoot -k /Users/{Environment.UserName}/Library/Keychains/login.keychain-db";
|
||||
TextBoxWindowViewModel vm = new()
|
||||
{
|
||||
Title = AppResources.MacTrustRootCertificateTips,
|
||||
InputType = TextBoxWindowViewModel.TextBoxInputType.Password,
|
||||
Description = AppResources.MacSudoPasswordTips + $"\r\n sudo {script} \"{filePath}\"",
|
||||
};
|
||||
var scriptContent = $"osascript -e 'tell app \"Terminal\" to do script \"sudo -S {script} \\\"{filePath}\\\"\"'";
|
||||
var msg = UnixHelper.RunShell(scriptContent.ToString());
|
||||
if (await TextBoxWindowViewModel.ShowDialogAsync(vm) == null)
|
||||
return null;
|
||||
if (!string.IsNullOrWhiteSpace(msg))
|
||||
{
|
||||
Toast.Show(msg);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试删除证书
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationCore/SR.cs
|
||||
|
||||
#if !NETFRAMEWORK && WINDOWS
|
||||
|
||||
namespace MS.Internal.PresentationCore;
|
||||
|
||||
internal static class SR
|
||||
{
|
||||
public static string Get(string name) => name switch
|
||||
{
|
||||
SRID.CantShowMBServiceWithOwner => "Cannot show MessageBox Service with Owner.",
|
||||
_ => "",
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
#if !NETFRAMEWORK && WINDOWS
|
||||
|
||||
namespace MS.Internal.PresentationCore;
|
||||
|
||||
static class SRID
|
||||
{
|
||||
/// <summary>
|
||||
/// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Resources/Strings.resx#L510
|
||||
/// </summary>
|
||||
public const string CantShowMBServiceWithOwner = "CantShowMBServiceWithOwner";
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ExternDll.cs
|
||||
|
||||
#if !NETFRAMEWORK && WINDOWS
|
||||
|
||||
namespace MS.Win32;
|
||||
|
||||
internal static class ExternDll
|
||||
{
|
||||
//public const string Activeds = "activeds.dll";
|
||||
//public const string Advapi32 = "advapi32.dll";
|
||||
//public const string Comctl32 = "comctl32.dll";
|
||||
//public const string Comdlg32 = "comdlg32.dll";
|
||||
//public const string DwmAPI = "dwmapi.dll";
|
||||
//public const string Gdi32 = "gdi32.dll";
|
||||
//public const string Gdiplus = "gdiplus.dll";
|
||||
//public const string Hhctrl = "hhctrl.ocx";
|
||||
//public const string Imm32 = "imm32.dll";
|
||||
//public const string Kernel32 = "kernel32.dll";
|
||||
//public const string Loadperf = "Loadperf.dll";
|
||||
//public const string Mqrt = "mqrt.dll";
|
||||
//public const string Mscoree = "mscoree.dll";
|
||||
//public const string MsDrm = "msdrm.dll";
|
||||
//public const string Mshwgst = "mshwgst.dll";
|
||||
//public const string Msi = "msi.dll";
|
||||
//public const string NaturalLanguage6 = "naturallanguage6.dll";
|
||||
//public const string Ntdll = "ntdll.dll";
|
||||
//public const string Ole32 = "ole32.dll";
|
||||
//public const string Oleacc = "oleacc.dll";
|
||||
//public const string Oleaut32 = "oleaut32.dll";
|
||||
//public const string Olepro32 = "olepro32.dll";
|
||||
//public const string Penimc = "PenIMC_cor3.dll";
|
||||
//public const string PresentationCore = "PresentationCore.dll";
|
||||
//public const string PresentationFramework = "PresentationFramework.dll";
|
||||
//public const string PresentationHostDll = "PresentationHost_cor3.dll";
|
||||
//public const string PresentationNativeDll = "PresentationNative_cor3.dll";
|
||||
//public const string Psapi = "psapi.dll";
|
||||
//public const string Shcore = "shcore.dll";
|
||||
//public const string Shell32 = "shell32.dll";
|
||||
//public const string Shfolder = "shfolder.dll";
|
||||
//public const string Urlmon = "urlmon.dll";
|
||||
public const string User32 = "user32.dll";
|
||||
//public const string Uxtheme = "uxtheme.dll";
|
||||
//public const string Version = "version.dll";
|
||||
//public const string Vsassert = "vsassert.dll";
|
||||
//public const string WindowsBase = "windowsbase.dll";
|
||||
//public const string Wininet = "wininet.dll";
|
||||
//public const string Winmm = "winmm.dll";
|
||||
//public const string Winspool = "winspool.drv";
|
||||
//public const string Wldp = "wldp.dll";
|
||||
//public const string WpfGfx = "WpfGfx_cor3.dll";
|
||||
//public const string WtsApi32 = "wtsapi32.dll";
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs
|
||||
|
||||
#if !NETFRAMEWORK && WINDOWS
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MS.Win32;
|
||||
|
||||
internal static class UnsafeNativeMethods
|
||||
{
|
||||
[DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr GetActiveWindow();
|
||||
|
||||
[DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
|
||||
public static extern int MessageBox(HandleRef hWnd, string text, string caption, int type);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,248 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/MessageBox.cs
|
||||
|
||||
#if !NETFRAMEWORK && WINDOWS
|
||||
|
||||
using MS.Win32;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using SR_ = MS.Internal.PresentationCore.SR;
|
||||
using SRID = MS.Internal.PresentationCore.SRID;
|
||||
|
||||
namespace System.Windows;
|
||||
|
||||
public static class MessageBox
|
||||
{
|
||||
const int IDOK = 1;
|
||||
const int IDCANCEL = 2;
|
||||
const int IDYES = 6;
|
||||
const int IDNO = 7;
|
||||
const int DEFAULT_BUTTON1 = 0x00000000;
|
||||
const int DEFAULT_BUTTON2 = 0x00000100;
|
||||
const int DEFAULT_BUTTON3 = 0x00000200;
|
||||
|
||||
static MessageBoxResult Win32ToMessageBoxResult(int value) => value switch
|
||||
{
|
||||
IDOK => MessageBoxResult.OK,
|
||||
IDCANCEL => MessageBoxResult.Cancel,
|
||||
IDYES => MessageBoxResult.Yes,
|
||||
IDNO => MessageBoxResult.No,
|
||||
_ => MessageBoxResult.No,
|
||||
};
|
||||
|
||||
public static MessageBoxResult Show(
|
||||
string messageBoxText,
|
||||
string caption,
|
||||
MessageBoxButton button,
|
||||
MessageBoxImage icon,
|
||||
MessageBoxResult defaultResult,
|
||||
MessageBoxOptions options) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, defaultResult, options);
|
||||
|
||||
public static MessageBoxResult Show(
|
||||
string messageBoxText,
|
||||
string caption,
|
||||
MessageBoxButton button,
|
||||
MessageBoxImage icon,
|
||||
MessageBoxResult defaultResult) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, defaultResult, 0);
|
||||
|
||||
public static MessageBoxResult Show(
|
||||
string messageBoxText,
|
||||
string caption,
|
||||
MessageBoxButton button,
|
||||
MessageBoxImage icon) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, 0, 0);
|
||||
|
||||
public static MessageBoxResult Show(
|
||||
string messageBoxText,
|
||||
string caption,
|
||||
MessageBoxButton button) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, MessageBoxImage.None, 0, 0);
|
||||
|
||||
public static MessageBoxResult Show(string messageBoxText, string caption) => ShowCore(IntPtr.Zero, messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None, 0, 0);
|
||||
|
||||
public static MessageBoxResult Show(string messageBoxText) => ShowCore(IntPtr.Zero, messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None, 0, 0);
|
||||
|
||||
static int DefaultResultToButtonNumber(MessageBoxResult result, MessageBoxButton button)
|
||||
{
|
||||
if (result == 0) return DEFAULT_BUTTON1;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case MessageBoxButton.OK:
|
||||
return DEFAULT_BUTTON1;
|
||||
case MessageBoxButton.OKCancel:
|
||||
if (result == MessageBoxResult.Cancel) return DEFAULT_BUTTON2;
|
||||
return DEFAULT_BUTTON1;
|
||||
case MessageBoxButton.YesNo:
|
||||
if (result == MessageBoxResult.No) return DEFAULT_BUTTON2;
|
||||
return DEFAULT_BUTTON1;
|
||||
case MessageBoxButton.YesNoCancel:
|
||||
if (result == MessageBoxResult.No) return DEFAULT_BUTTON2;
|
||||
if (result == MessageBoxResult.Cancel) return DEFAULT_BUTTON3;
|
||||
return DEFAULT_BUTTON1;
|
||||
default:
|
||||
return DEFAULT_BUTTON1;
|
||||
}
|
||||
}
|
||||
|
||||
internal static MessageBoxResult ShowCore(
|
||||
IntPtr owner,
|
||||
string messageBoxText,
|
||||
string caption,
|
||||
MessageBoxButton button,
|
||||
MessageBoxImage icon,
|
||||
MessageBoxResult defaultResult,
|
||||
MessageBoxOptions options)
|
||||
{
|
||||
if (!IsValidMessageBoxButton(button))
|
||||
{
|
||||
throw new InvalidEnumArgumentException("button", (int)button, typeof(MessageBoxButton));
|
||||
}
|
||||
if (!IsValidMessageBoxImage(icon))
|
||||
{
|
||||
throw new InvalidEnumArgumentException("icon", (int)icon, typeof(MessageBoxImage));
|
||||
}
|
||||
if (!IsValidMessageBoxResult(defaultResult))
|
||||
{
|
||||
throw new InvalidEnumArgumentException("defaultResult", (int)defaultResult, typeof(MessageBoxResult));
|
||||
}
|
||||
if (!IsValidMessageBoxOptions(options))
|
||||
{
|
||||
throw new InvalidEnumArgumentException("options", (int)options, typeof(MessageBoxOptions));
|
||||
}
|
||||
|
||||
// UserInteractive??
|
||||
//
|
||||
/*if (!SystemInformation.UserInteractive && (options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) == 0) {
|
||||
throw new InvalidOperationException("UNDONE: SR.GetString(SR.CantShowModalOnNonInteractive)");
|
||||
}*/
|
||||
|
||||
if ((options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) != 0)
|
||||
{
|
||||
if (owner != IntPtr.Zero)
|
||||
{
|
||||
throw new ArgumentException(SR_.Get(SRID.CantShowMBServiceWithOwner));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (owner == IntPtr.Zero)
|
||||
{
|
||||
owner = UnsafeNativeMethods.GetActiveWindow();
|
||||
}
|
||||
}
|
||||
|
||||
int style = (int)button | (int)icon | (int)DefaultResultToButtonNumber(defaultResult, button) | (int)options;
|
||||
|
||||
// modal dialog notification?
|
||||
//
|
||||
//Application.BeginModalMessageLoop();
|
||||
//MessageBoxResult result = Win32ToMessageBoxResult(SafeNativeMethods.MessageBox(new HandleRef(owner, handle), messageBoxText, caption, style));
|
||||
MessageBoxResult result = Win32ToMessageBoxResult(UnsafeNativeMethods.MessageBox(new HandleRef(null, owner), messageBoxText, caption, style));
|
||||
// modal dialog notification?
|
||||
//
|
||||
//Application.EndModalMessageLoop();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool IsValidMessageBoxButton(MessageBoxButton value) => value == MessageBoxButton.OK
|
||||
|| value == MessageBoxButton.OKCancel
|
||||
|| value == MessageBoxButton.YesNo
|
||||
|| value == MessageBoxButton.YesNoCancel;
|
||||
|
||||
static bool IsValidMessageBoxImage(MessageBoxImage value) => value == MessageBoxImage.Asterisk
|
||||
|| value == MessageBoxImage.Error
|
||||
|| value == MessageBoxImage.Exclamation
|
||||
|| value == MessageBoxImage.Hand
|
||||
|| value == MessageBoxImage.Information
|
||||
|| value == MessageBoxImage.None
|
||||
|| value == MessageBoxImage.Question
|
||||
|| value == MessageBoxImage.Stop
|
||||
|| value == MessageBoxImage.Warning;
|
||||
|
||||
static bool IsValidMessageBoxResult(MessageBoxResult value) => value == MessageBoxResult.Cancel
|
||||
|| value == MessageBoxResult.No
|
||||
|| value == MessageBoxResult.None
|
||||
|| value == MessageBoxResult.OK
|
||||
|| value == MessageBoxResult.Yes;
|
||||
|
||||
static bool IsValidMessageBoxOptions(MessageBoxOptions value)
|
||||
{
|
||||
int mask = ~((int)MessageBoxOptions.ServiceNotification |
|
||||
(int)MessageBoxOptions.DefaultDesktopOnly |
|
||||
(int)MessageBoxOptions.RightAlign |
|
||||
(int)MessageBoxOptions.RtlReading);
|
||||
|
||||
if (((int)value & mask) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MessageBoxResult
|
||||
{
|
||||
None = 0,
|
||||
|
||||
OK = 1,
|
||||
|
||||
Cancel = 2,
|
||||
|
||||
Yes = 6,
|
||||
|
||||
No = 7,
|
||||
|
||||
// NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxResult()
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MessageBoxOptions
|
||||
{
|
||||
None = 0x00000000,
|
||||
|
||||
ServiceNotification = 0x00200000,
|
||||
|
||||
DefaultDesktopOnly = 0x00020000,
|
||||
|
||||
RightAlign = 0x00080000,
|
||||
|
||||
RtlReading = 0x00100000,
|
||||
}
|
||||
|
||||
public enum MessageBoxImage
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Hand = 0x00000010,
|
||||
|
||||
Question = 0x00000020,
|
||||
|
||||
Exclamation = 0x00000030,
|
||||
|
||||
Asterisk = 0x00000040,
|
||||
|
||||
Stop = Hand,
|
||||
|
||||
Error = Hand,
|
||||
|
||||
Warning = Exclamation,
|
||||
|
||||
Information = Asterisk,
|
||||
|
||||
// NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxIcon()
|
||||
}
|
||||
|
||||
public enum MessageBoxButton
|
||||
{
|
||||
OK = 0x00000000,
|
||||
|
||||
OKCancel = 0x00000001,
|
||||
|
||||
YesNoCancel = 0x00000003,
|
||||
|
||||
YesNo = 0x00000004,
|
||||
|
||||
// NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxButton()
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,7 @@
|
||||
using DnsClient;
|
||||
using DnsClient.Protocol;
|
||||
using DynamicData;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
using System.Collections.Generic;
|
||||
@@ -14,18 +16,23 @@ namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed class DnsAnalysisServiceImpl : IDnsAnalysisService
|
||||
{
|
||||
public DnsAnalysisServiceImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static readonly LookupClient lookupClient = new();
|
||||
|
||||
public int AnalysisHostnameTime(string url)
|
||||
public async Task<int> AnalysisHostnameTime(string url, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
var client = lookupClient;
|
||||
var result = client.Query(url, QueryType.A);
|
||||
var result = await client.QueryAsync(url, QueryType.A, QueryClass.IN, cancellationToken);
|
||||
if (result.Answers.Count > 0)
|
||||
{
|
||||
var value = result.Answers.ARecords().FirstOrDefault()?.InitialTimeToLive;
|
||||
if (value.HasValue) return value.Value;
|
||||
return value ?? 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -140,6 +147,11 @@ namespace System.Application.Services.Implementation
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<IPAddress?> GetHostIpv6Addres()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +162,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddDnsAnalysisService(this IServiceCollection services)
|
||||
{
|
||||
//services.AddSingleton<IDnsAnalysisService, DnsDohAnalysisService>();
|
||||
services.AddSingleton<IDnsAnalysisService, DnsAnalysisServiceImpl>();
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,14 @@ using System.Application.Settings;
|
||||
using System.Application.UI;
|
||||
using System.Application.UI.Resx;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
#if WINDOWS
|
||||
using System.Management;
|
||||
#endif
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.Versioning;
|
||||
@@ -143,6 +147,41 @@ namespace System.Application.Services.Implementation
|
||||
/// <returns></returns>
|
||||
private Process? GetSteamProces() => GetSteamProcesses().FirstOrDefault();
|
||||
|
||||
public bool IsSteamChinaLauncher()
|
||||
{
|
||||
#if WINDOWS
|
||||
var process = GetSteamProces();
|
||||
if (process != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetCommandLineArgsCore().Contains("-steamchina", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
catch (Win32Exception ex) when ((uint)ex.ErrorCode == 0x80004005)
|
||||
{
|
||||
// 没有对该进程的安全访问权限。
|
||||
return false;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// 进程已退出。
|
||||
return false;
|
||||
}
|
||||
}
|
||||
string GetCommandLineArgsCore()
|
||||
{
|
||||
using (var searcher = new ManagementObjectSearcher(
|
||||
"SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id))
|
||||
using (var objects = searcher.Get())
|
||||
{
|
||||
var @object = objects.Cast<ManagementBaseObject>().SingleOrDefault();
|
||||
return @object?["CommandLine"]?.ToString() ?? "";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
public void StartSteam(string? arguments = null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(SteamProgramPath) && File.Exists(SteamProgramPath))
|
||||
@@ -495,6 +534,9 @@ namespace System.Application.Services.Implementation
|
||||
|
||||
private uint univeseNumber;
|
||||
private const uint MagicNumber = 123094055U;
|
||||
private const uint MagicNumberV2 = 123094056U;
|
||||
|
||||
private static readonly Lazy<uint[]> MagicNumbers = new(new uint[] { MagicNumber, MagicNumberV2 });
|
||||
|
||||
/// <summary>
|
||||
/// 从steam本地客户端缓存文件中读取游戏数据
|
||||
@@ -516,15 +558,17 @@ namespace System.Application.Services.Implementation
|
||||
}
|
||||
using BinaryReader binaryReader = new(stream);
|
||||
uint num = binaryReader.ReadUInt32();
|
||||
if (num != MagicNumber)
|
||||
if (!MagicNumbers.Value.Contains(num))
|
||||
{
|
||||
Log.Error(nameof(GetAppInfos), string.Format("\"{0}\" magic code is not supported: 0x{1:X8}", Path.GetFileName(AppInfoPath), num));
|
||||
var msg = string.Format("\"{0}\" magic code is not supported: 0x{1:X8}", Path.GetFileName(AppInfoPath), num);
|
||||
Log.Error(nameof(GetAppInfos), msg);
|
||||
Toast.Show(msg, ToastLength.Long);
|
||||
return apps;
|
||||
}
|
||||
SteamApp? app = new();
|
||||
univeseNumber = binaryReader.ReadUInt32();
|
||||
var installAppIds = GetInstalledAppIds();
|
||||
while ((app = SteamApp.FromReader(binaryReader, installAppIds, isSaveProperties)) != null)
|
||||
while ((app = SteamApp.FromReader(binaryReader, installAppIds, isSaveProperties, num == MagicNumberV2)) != null)
|
||||
{
|
||||
if (app.AppId > 0)
|
||||
{
|
||||
|
||||
+15
@@ -106,6 +106,21 @@ namespace System.Application.Services.Implementation
|
||||
return SteamClient.SteamUtils.IsSteamChinaLauncher();
|
||||
}
|
||||
|
||||
public bool IsSteamInBigPictureMode()
|
||||
{
|
||||
return SteamClient.SteamUtils.IsSteamInBigPictureMode();
|
||||
}
|
||||
|
||||
public uint GetSecondsSinceAppActive()
|
||||
{
|
||||
return SteamClient.SteamUtils.GetSecondsSinceAppActive();
|
||||
}
|
||||
|
||||
public uint GetServerRealTime()
|
||||
{
|
||||
return SteamClient.SteamUtils.GetServerRealTime();
|
||||
}
|
||||
|
||||
public bool IsAppInstalled(uint appid)
|
||||
{
|
||||
return SteamClient.SteamApps008.IsAppInstalled(appid);
|
||||
|
||||
+30
-1
@@ -31,11 +31,24 @@ namespace System.Application.Services.Implementation
|
||||
}
|
||||
|
||||
public async Task<byte[]> ProtectAsync(byte[] data)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await ProtectCoreAsync(data);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return await ProtectCore2Async(data);
|
||||
}
|
||||
}
|
||||
|
||||
static async Task<byte[]> ProtectCoreAsync(byte[] data)
|
||||
{
|
||||
// LOCAL=user and LOCAL=machine do not require enterprise auth capability
|
||||
var provider = GetDataProtectionProvider("LOCAL=user");
|
||||
|
||||
// https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/842356268u/overview
|
||||
// https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/1550045210u/overview
|
||||
// System.Runtime.InteropServices.COMException: 无法在设置线程模式后对其加以更改。 (0x80010106 (RPC_E_CHANGED_MODE))
|
||||
|
||||
var buffer = await provider.ProtectAsync(data.AsBuffer());
|
||||
@@ -45,7 +58,9 @@ namespace System.Application.Services.Implementation
|
||||
return encBytes;
|
||||
}
|
||||
|
||||
public async Task<byte[]> UnprotectAsync(byte[] data)
|
||||
static async Task<byte[]> ProtectCore2Async(byte[] data) => await await Task.Factory.StartNew(async () => await ProtectCoreAsync(data));
|
||||
|
||||
static async Task<byte[]> UnprotectCoreAsync(byte[] data)
|
||||
{
|
||||
var provider = GetDataProtectionProvider();
|
||||
|
||||
@@ -53,5 +68,19 @@ namespace System.Application.Services.Implementation
|
||||
|
||||
return buffer.ToArray();
|
||||
}
|
||||
|
||||
static async Task<byte[]> UnprotectCore2Async(byte[] data) => await await Task.Factory.StartNew(async () => await UnprotectCoreAsync(data));
|
||||
|
||||
public async Task<byte[]> UnprotectAsync(byte[] data)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await UnprotectCoreAsync(data);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return await UnprotectCore2Async(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -2,6 +2,11 @@ namespace System.Application.Services.Implementation
|
||||
{
|
||||
partial class WindowsPlatformServiceImpl : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于 <see cref="IOPath.GetCacheFilePath(string, string, string)"/> 中 dirName,临时文件夹名称,在程序退出时将删除整个文件夹
|
||||
/// </summary>
|
||||
const string CacheTempDirName = "Temporary";
|
||||
|
||||
bool disposedValue;
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
@@ -12,6 +17,8 @@ namespace System.Application.Services.Implementation
|
||||
{
|
||||
// TODO: 释放托管状态(托管对象)
|
||||
isLightOrDarkThemeWatch?.Dispose();
|
||||
|
||||
IOPath.TryDeleteCacheSubDir(CacheTempDirName);
|
||||
}
|
||||
|
||||
// TODO: 释放未托管的资源(未托管的对象)并重写终结器
|
||||
|
||||
+360
-271
@@ -1,6 +1,5 @@
|
||||
using Microsoft.Win32;
|
||||
using System.Application.Models;
|
||||
using System.Application.UI;
|
||||
using System.Application.UI.Resx;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
@@ -11,326 +10,416 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using Windows.ApplicationModel;
|
||||
using System.Application.Properties;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using _SR = System.Application.Properties.SR;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
namespace System.Application.Services.Implementation;
|
||||
|
||||
internal sealed partial class WindowsPlatformServiceImpl : IPlatformService
|
||||
{
|
||||
internal sealed partial class WindowsPlatformServiceImpl : IPlatformService
|
||||
const string TAG = "WindowsPlatformS";
|
||||
const string SteamRegistryPath = @"SOFTWARE\Valve\Steam";
|
||||
|
||||
public string? GetRegistryVdfPath() { return null; }
|
||||
|
||||
public string GetCommandLineArgs(Process process)
|
||||
{
|
||||
const string TAG = "WindowsPlatformS";
|
||||
const string SteamRegistryPath = @"SOFTWARE\Valve\Steam";
|
||||
|
||||
public string? GetRegistryVdfPath() { return null; }
|
||||
|
||||
public string GetCommandLineArgs(Process process)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
using var searcher = new ManagementObjectSearcher(
|
||||
"SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id);
|
||||
using var objects = searcher.Get();
|
||||
var @object = objects.Cast<ManagementBaseObject>().SingleOrDefault();
|
||||
return @object?["CommandLine"]?.ToString() ?? "";
|
||||
}
|
||||
catch (Win32Exception ex) when ((uint)ex.ErrorCode == 0x80004005)
|
||||
{
|
||||
// 没有对该进程的安全访问权限。
|
||||
return string.Empty;
|
||||
}
|
||||
using var searcher = new ManagementObjectSearcher(
|
||||
"SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id);
|
||||
using var objects = searcher.Get();
|
||||
var @object = objects.Cast<ManagementBaseObject>().SingleOrDefault();
|
||||
return @object?["CommandLine"]?.ToString() ?? "";
|
||||
}
|
||||
|
||||
static readonly Lazy<string> mHostsFilePath = new(() =>
|
||||
catch (Win32Exception ex) when ((uint)ex.ErrorCode == 0x80004005)
|
||||
{
|
||||
return Path.Combine(Environment.SystemDirectory, "drivers", "etc", "hosts");
|
||||
});
|
||||
// 没有对该进程的安全访问权限。
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public string HostsFilePath => mHostsFilePath.Value;
|
||||
static readonly Lazy<string> mHostsFilePath = new(() =>
|
||||
{
|
||||
return Path.Combine(Environment.SystemDirectory, "drivers", "etc", "hosts");
|
||||
});
|
||||
|
||||
public string DefaultHostsContent => _SR.hosts;
|
||||
public string HostsFilePath => mHostsFilePath.Value;
|
||||
|
||||
static string GetFolderPath(Environment.SpecialFolder folder)
|
||||
public string DefaultHostsContent => _SR.hosts;
|
||||
|
||||
static string GetFolderPath(Environment.SpecialFolder folder)
|
||||
{
|
||||
switch (folder)
|
||||
{
|
||||
switch (folder)
|
||||
{
|
||||
case Environment.SpecialFolder.ProgramFiles:
|
||||
var trimEndMark = " (x86)";
|
||||
var value = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
if (value.EndsWith(trimEndMark, StringComparison.OrdinalIgnoreCase))
|
||||
case Environment.SpecialFolder.ProgramFiles:
|
||||
var trimEndMark = " (x86)";
|
||||
var value = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
if (value.EndsWith(trimEndMark, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var value2 = value[..^trimEndMark.Length];
|
||||
if (Directory.Exists(value2))
|
||||
{
|
||||
var value2 = value.Substring(0, value.Length - trimEndMark.Length);
|
||||
if (Directory.Exists(value2))
|
||||
{
|
||||
return value2;
|
||||
}
|
||||
return value2;
|
||||
}
|
||||
return value;
|
||||
default:
|
||||
return Environment.GetFolderPath(folder);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
default:
|
||||
return Environment.GetFolderPath(folder);
|
||||
}
|
||||
}
|
||||
|
||||
const string explorer = "explorer.exe";
|
||||
public void OpenFolderByDirectoryPath(DirectoryInfo info)
|
||||
{
|
||||
StartProcessExplorer($"\"{info.FullName}\"");
|
||||
}
|
||||
|
||||
static string Explorer => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), explorer);
|
||||
public void OpenFolderSelectFilePath(FileInfo info)
|
||||
{
|
||||
StartProcessExplorer($"/select,\"{info.FullName}\"");
|
||||
}
|
||||
|
||||
public void OpenFolderByDirectoryPath(DirectoryInfo info)
|
||||
public string? GetFileName(TextReaderProvider provider)
|
||||
{
|
||||
switch (provider)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = Explorer,
|
||||
Arguments = $"\"{info.FullName}\"",
|
||||
UseShellExecute = false,
|
||||
});
|
||||
}
|
||||
case TextReaderProvider.VSCode:
|
||||
var vsCodePaths = new[] {
|
||||
GetFolderPath(Environment.SpecialFolder.ProgramFiles),
|
||||
GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
|
||||
}.Distinct().Select(x => Path.Combine(x, "Microsoft VS Code", "Code.exe"));
|
||||
|
||||
public void OpenFolderSelectFilePath(FileInfo info)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = Explorer,
|
||||
Arguments = $"/select,\"{info.FullName}\"",
|
||||
UseShellExecute = false,
|
||||
});
|
||||
}
|
||||
|
||||
public string? GetFileName(TextReaderProvider provider)
|
||||
{
|
||||
switch (provider)
|
||||
{
|
||||
case TextReaderProvider.VSCode:
|
||||
var vsCodePaths = new[] {
|
||||
GetFolderPath(Environment.SpecialFolder.ProgramFiles),
|
||||
GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
|
||||
}.Distinct().Select(x => Path.Combine(x, "Microsoft VS Code", "Code.exe"));
|
||||
|
||||
foreach (var vsCodePath in vsCodePaths)
|
||||
foreach (var vsCodePath in vsCodePaths)
|
||||
{
|
||||
if (File.Exists(vsCodePath))
|
||||
{
|
||||
if (File.Exists(vsCodePath))
|
||||
{
|
||||
return vsCodePath;
|
||||
}
|
||||
return vsCodePath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
case TextReaderProvider.Notepad:
|
||||
return "notepad";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
case TextReaderProvider.Notepad:
|
||||
return "notepad";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSystemSessionEnding(Action action)
|
||||
public void SetSystemSessionEnding(Action action)
|
||||
{
|
||||
SystemEvents.SessionEnding += (sender, e) =>
|
||||
{
|
||||
SystemEvents.SessionEnding += (sender, e) =>
|
||||
{
|
||||
//IDesktopAppService.Instance.CompositeDisposable.Dispose();
|
||||
action.Invoke();
|
||||
};
|
||||
//IDesktopAppService.Instance.CompositeDisposable.Dispose();
|
||||
action.Invoke();
|
||||
};
|
||||
}
|
||||
|
||||
static string? GetFullPath(string s)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(s))
|
||||
{
|
||||
return Path.GetFullPath(s);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static string? GetFullPath(string s)
|
||||
public string? GetSteamDirPath()
|
||||
=> GetFullPath(Registry.CurrentUser.Read(SteamRegistryPath, "SteamPath"));
|
||||
|
||||
public string? GetSteamProgramPath()
|
||||
=> GetFullPath(Registry.CurrentUser.Read(SteamRegistryPath, "SteamExe"));
|
||||
|
||||
public string GetLastSteamLoginUserName()
|
||||
=> Registry.CurrentUser.Read(SteamRegistryPath, "AutoLoginUser");
|
||||
|
||||
public void SetCurrentUser(string userName)
|
||||
{
|
||||
if (DesktopBridge.IsRunningAsUwp)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(s))
|
||||
{
|
||||
return Path.GetFullPath(s);
|
||||
}
|
||||
var reg = $"Windows Registry Editor Version 5.00{Environment.NewLine}[HKEY_CURRENT_USER\\Software\\Valve\\Steam]{Environment.NewLine}\"AutoLoginUser\"=\"{userName}\"";
|
||||
var path = IOPath.GetCacheFilePath(CacheTempDirName, "SwitchSteamUser", FileEx.Reg);
|
||||
File.WriteAllText(path, reg, Encoding.UTF8);
|
||||
var p = StartProcessRegedit($"/s \"{path}\"");
|
||||
IOPath.TryDeleteInDelay(p, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
Registry.CurrentUser.AddOrUpdate(SteamRegistryPath, "AutoLoginUser", userName, RegistryValueKind.String);
|
||||
}
|
||||
}
|
||||
|
||||
static string GetMachineSecretKey()
|
||||
=> Registry.LocalMachine.Read(@"SOFTWARE\Microsoft\Cryptography", "MachineGuid");
|
||||
|
||||
static readonly Lazy<(byte[] key, byte[] iv)> mMachineSecretKey = IPlatformService.GetMachineSecretKey(GetMachineSecretKey);
|
||||
|
||||
public (byte[] key, byte[] iv) MachineSecretKey => mMachineSecretKey.Value;
|
||||
|
||||
/// <summary>
|
||||
/// %windir%
|
||||
/// </summary>
|
||||
static readonly Lazy<string> _windir = new(() => Environment.GetFolderPath(Environment.SpecialFolder.Windows));
|
||||
|
||||
//const string runas_exe = "runas.exe";
|
||||
//static Process? StartAsInvokerByRunas(string fileName, string? arguments = null)
|
||||
//{
|
||||
// // https://blog.lindexi.com/post/%E5%A6%82%E4%BD%95%E5%9C%A8-RunAs-%E5%90%AF%E5%8A%A8%E7%9A%84%E8%BD%AF%E4%BB%B6%E4%BC%A0%E5%85%A5%E5%B8%A6%E7%A9%BA%E6%A0%BC%E7%9A%84%E8%B7%AF%E5%BE%84%E5%B8%A6%E7%A9%BA%E6%A0%BC%E5%8F%82%E6%95%B0.html
|
||||
// string arguments_;
|
||||
// if (string.IsNullOrEmpty(arguments))
|
||||
// arguments_ = $"/trustlevel:0x20000 \"{fileName}\"";
|
||||
// else arguments_ = $"/trustlevel:0x20000 \"{fileName} \"{arguments}\"\"";
|
||||
// return Process.Start(runas_exe, arguments_);
|
||||
//}
|
||||
|
||||
static readonly Lazy<string> _explorer_exe = new(() => Path.Combine(_windir.Value, "explorer.exe"));
|
||||
|
||||
/// <summary>
|
||||
/// %windir%\explorer.exe
|
||||
/// </summary>
|
||||
static string Explorer => _explorer_exe.Value;
|
||||
|
||||
/// <summary>
|
||||
/// 带参数(可选/null)启动 %windir%\explorer.exe
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
static Process? StartProcessExplorer(string args) => Process2.Start(Explorer, args, workingDirectory: _windir.Value);
|
||||
|
||||
static readonly Lazy<string> _regedit_exe = new(() => Path.Combine(_windir.Value, "regedit.exe"));
|
||||
|
||||
/// <summary>
|
||||
/// %windir%\regedit.exe
|
||||
/// </summary>
|
||||
static string Regedit => _regedit_exe.Value;
|
||||
|
||||
/// <summary>
|
||||
/// 带参数(可选/null)启动 %windir%\regedit.exe
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
static Process? StartProcessRegedit(string? args) => Process2.Start(Regedit, args, workingDirectory: _windir.Value);
|
||||
|
||||
/// <summary>
|
||||
/// 使用 Explorer 降权运行进程
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="arguments"></param>
|
||||
/// <returns></returns>
|
||||
static Process? StartAsInvokerByExplorer(string fileName, string? arguments = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arguments))
|
||||
return StartProcessExplorer($"\"{fileName}\"");
|
||||
//var processName = Path.GetFileNameWithoutExtension(fileName);
|
||||
var cacheCmdFile = IOPath.GetCacheFilePath(CacheTempDirName, "StartAsInvokerByExplorer", FileEx.CMD);
|
||||
File.WriteAllText(cacheCmdFile, $"@echo {Constants.HARDCODED_APP_NAME} StartAsInvokerByExplorer{Environment.NewLine}start \"\" \"{fileName}\" {arguments}{Environment.NewLine}del %0");
|
||||
var process = StartProcessExplorer($"\"{cacheCmdFile}\"");
|
||||
//if (process != null)
|
||||
//{
|
||||
// TryDeleteInDelay(process, cacheCmdFile, processName);
|
||||
//}
|
||||
return process;
|
||||
|
||||
//static async void TryDeleteInDelay(Process process, string filePath, string processName, int millisecondsDelay = 9000, int processWaitMillisecondsDelay = 9000)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// var waitForExitResult = process.WaitForExit(processWaitMillisecondsDelay);
|
||||
// if (!waitForExitResult)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// process.KillEntireProcessTree();
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// millisecondsDelay = 0;
|
||||
// }
|
||||
// if (millisecondsDelay > 0)
|
||||
// {
|
||||
// var token = new CancellationTokenSource(millisecondsDelay);
|
||||
// try
|
||||
// {
|
||||
// await Task.Run(async () =>
|
||||
// {
|
||||
// while (true)
|
||||
// {
|
||||
// await Task.Delay(100, token.Token);
|
||||
// if (Process.GetProcessesByName(processName).Any())
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }, token.Token);
|
||||
// }
|
||||
// catch (TaskCanceledException)
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// IOPath.FileTryDelete(filePath);
|
||||
//}
|
||||
}
|
||||
|
||||
public Process? StartAsInvoker(string fileName, string? arguments = null)
|
||||
{
|
||||
if (((IPlatformService)this).IsAdministrator)
|
||||
{
|
||||
// runas /trustlevel:0x20000 没有真正的降权,只是作为具有限制特权,使用 explorer 最好,但不接受参数,可以创建一个临时cmd脚本启动
|
||||
//return StartAsInvokerByRunas(fileName, arguments);
|
||||
//return StartAsInvokerByExplorer(fileName, arguments);
|
||||
var currentDirectory = Path.GetDirectoryName(fileName) ?? "";
|
||||
Microsoft.NodejsTools.SharedProject.SystemUtility.
|
||||
ExecuteProcessUnElevated(fileName, arguments ?? "", currentDirectory);
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public string? GetSteamDirPath()
|
||||
=> GetFullPath(Registry.CurrentUser.Read(SteamRegistryPath, "SteamPath"));
|
||||
|
||||
public string? GetSteamProgramPath()
|
||||
=> GetFullPath(Registry.CurrentUser.Read(SteamRegistryPath, "SteamExe"));
|
||||
|
||||
public string GetLastSteamLoginUserName()
|
||||
=> Registry.CurrentUser.Read(SteamRegistryPath, "AutoLoginUser");
|
||||
|
||||
public void SetCurrentUser(string userName)
|
||||
else
|
||||
{
|
||||
if (DesktopBridge.IsRunningAsUwp)
|
||||
{
|
||||
var reg = $"Windows Registry Editor Version 5.00{Environment.NewLine}[HKEY_CURRENT_USER\\Software\\Valve\\Steam]{Environment.NewLine}\"AutoLoginUser\"=\"{userName}\"";
|
||||
var path = Path.Combine(IOPath.CacheDirectory, "switchuser.reg");
|
||||
File.WriteAllText(path, reg, Text.Encoding.UTF8);
|
||||
var p = Process2.Start("regedit", $"/s \"{path}\"", true);
|
||||
p?.WaitForExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
Registry.CurrentUser.AddOrUpdate(SteamRegistryPath, "AutoLoginUser", userName, RegistryValueKind.String);
|
||||
}
|
||||
return Process2.Start(fileName, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
static string GetMachineSecretKey()
|
||||
=> Registry.LocalMachine.Read(@"SOFTWARE\Microsoft\Cryptography", "MachineGuid");
|
||||
//public Process? StartAsInvoker(ProcessStartInfo startInfo)
|
||||
//{
|
||||
// startInfo.FileName = runas_exe;
|
||||
// startInfo.Arguments = $"/trustlevel:0x20000 \"{startInfo.FileName}\"";
|
||||
// return Process.Start(startInfo);
|
||||
//}
|
||||
|
||||
static readonly Lazy<(byte[] key, byte[] iv)> mMachineSecretKey = IPlatformService.GetMachineSecretKey(GetMachineSecretKey);
|
||||
//public Process? GetProcessByPortOccupy(ushort port, bool isTCPorUDP = true)
|
||||
//{
|
||||
// if (isTCPorUDP)
|
||||
// {
|
||||
// return SocketHelper.GetProcessByTcpPort(port);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new NotSupportedException();
|
||||
// }
|
||||
// //try
|
||||
// //{
|
||||
// // using var p = new Process
|
||||
// // {
|
||||
// // StartInfo = new ProcessStartInfo
|
||||
// // {
|
||||
// // FileName = "cmd",
|
||||
// // UseShellExecute = false,
|
||||
// // RedirectStandardInput = true,
|
||||
// // RedirectStandardOutput = true,
|
||||
// // CreateNoWindow = true,
|
||||
// // },
|
||||
// // };
|
||||
// // p.Start();
|
||||
// // p.StandardInput.WriteLine($"netstat -ano|findstr \"{port}\"&exit");
|
||||
// // p.StandardInput.AutoFlush = true;
|
||||
// // var reader = p.StandardOutput;
|
||||
// // while (!reader.EndOfStream)
|
||||
// // {
|
||||
// // var line = reader.ReadLine();
|
||||
// // if (line == null) break;
|
||||
// // var lineArray = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
// // if (lineArray.Length != 5) continue;
|
||||
// // if (!lineArray[0].Equals(isTCPorUDP ? "TCP" : "UDP", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
// // if (!lineArray[3].Equals("LISTENING", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
// // if (!lineArray[1].EndsWith($":{port}")) continue;
|
||||
// // if (!ushort.TryParse(lineArray[4], out var pid)) continue;
|
||||
// // p.Close();
|
||||
// // return Process.GetProcessById(pid);
|
||||
// // }
|
||||
// // _ = p.WaitForExit(550);
|
||||
// //}
|
||||
// //catch
|
||||
// //{
|
||||
// //}
|
||||
// //return default;
|
||||
//}
|
||||
|
||||
public (byte[] key, byte[] iv) MachineSecretKey => mMachineSecretKey.Value;
|
||||
const string ProxyOverride = "\"ProxyOverride\"=\"localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*\"";
|
||||
|
||||
//const string runas_exe = "runas.exe";
|
||||
//static Process? StartAsInvokerByRunas(string fileName, string? arguments = null)
|
||||
//{
|
||||
// // https://blog.lindexi.com/post/%E5%A6%82%E4%BD%95%E5%9C%A8-RunAs-%E5%90%AF%E5%8A%A8%E7%9A%84%E8%BD%AF%E4%BB%B6%E4%BC%A0%E5%85%A5%E5%B8%A6%E7%A9%BA%E6%A0%BC%E7%9A%84%E8%B7%AF%E5%BE%84%E5%B8%A6%E7%A9%BA%E6%A0%BC%E5%8F%82%E6%95%B0.html
|
||||
// string arguments_;
|
||||
// if (string.IsNullOrEmpty(arguments))
|
||||
// arguments_ = $"/trustlevel:0x20000 \"{fileName}\"";
|
||||
// else arguments_ = $"/trustlevel:0x20000 \"{fileName} \"{arguments}\"\"";
|
||||
// return Process.Start(runas_exe, arguments_);
|
||||
//}
|
||||
|
||||
const string explorer_exe = "explorer.exe";
|
||||
|
||||
static Process? StartAsInvokerByExplorer(string fileName, string? arguments = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arguments))
|
||||
return Process.Start(explorer_exe, $"\"{fileName}\"");
|
||||
var cacheCmdFile = Path.Combine(IOPath.CacheDirectory, "StartAsInvokerByExplorer" + FileEx.CMD);
|
||||
if (File.Exists(cacheCmdFile)) File.Delete(cacheCmdFile);
|
||||
File.WriteAllText(cacheCmdFile, $"@echo {Constants.HARDCODED_APP_NAME} StartAsInvokerByExplorer{Environment.NewLine}start \"\" \"{fileName}\" {arguments}{Environment.NewLine}exit 0");
|
||||
return Process.Start(explorer_exe, $"\"{cacheCmdFile}\"");
|
||||
}
|
||||
|
||||
public Process? StartAsInvoker(string fileName, string? arguments = null)
|
||||
{
|
||||
if (((IPlatformService)this).IsAdministrator)
|
||||
{
|
||||
// runas /trustlevel:0x20000 没有真正的降权,只是作为具有限制特权,使用 explorer 最好,但不接受参数,可以创建一个临时cmd脚本启动
|
||||
//return StartAsInvokerByRunas(fileName, arguments);
|
||||
return StartAsInvokerByExplorer(fileName, arguments);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return Process2.Start(fileName, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
//public Process? StartAsInvoker(ProcessStartInfo startInfo)
|
||||
//{
|
||||
// startInfo.FileName = runas_exe;
|
||||
// startInfo.Arguments = $"/trustlevel:0x20000 \"{startInfo.FileName}\"";
|
||||
// return Process.Start(startInfo);
|
||||
//}
|
||||
|
||||
//public Process? GetProcessByPortOccupy(ushort port, bool isTCPorUDP = true)
|
||||
//{
|
||||
// if (isTCPorUDP)
|
||||
// {
|
||||
// return SocketHelper.GetProcessByTcpPort(port);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new NotSupportedException();
|
||||
// }
|
||||
// //try
|
||||
// //{
|
||||
// // using var p = new Process
|
||||
// // {
|
||||
// // StartInfo = new ProcessStartInfo
|
||||
// // {
|
||||
// // FileName = "cmd",
|
||||
// // UseShellExecute = false,
|
||||
// // RedirectStandardInput = true,
|
||||
// // RedirectStandardOutput = true,
|
||||
// // CreateNoWindow = true,
|
||||
// // },
|
||||
// // };
|
||||
// // p.Start();
|
||||
// // p.StandardInput.WriteLine($"netstat -ano|findstr \"{port}\"&exit");
|
||||
// // p.StandardInput.AutoFlush = true;
|
||||
// // var reader = p.StandardOutput;
|
||||
// // while (!reader.EndOfStream)
|
||||
// // {
|
||||
// // var line = reader.ReadLine();
|
||||
// // if (line == null) break;
|
||||
// // var lineArray = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
// // if (lineArray.Length != 5) continue;
|
||||
// // if (!lineArray[0].Equals(isTCPorUDP ? "TCP" : "UDP", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
// // if (!lineArray[3].Equals("LISTENING", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
// // if (!lineArray[1].EndsWith($":{port}")) continue;
|
||||
// // if (!ushort.TryParse(lineArray[4], out var pid)) continue;
|
||||
// // p.Close();
|
||||
// // return Process.GetProcessById(pid);
|
||||
// // }
|
||||
// // _ = p.WaitForExit(550);
|
||||
// //}
|
||||
// //catch
|
||||
// //{
|
||||
// //}
|
||||
// //return default;
|
||||
//}
|
||||
|
||||
const string ProxyOverride = "\"ProxyOverride\"=\"localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*\"";
|
||||
|
||||
/// <summary>
|
||||
/// 设置启用或关闭系统代理
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="ip"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetAsSystemProxy(bool state, IPAddress? ip, int port)
|
||||
/// <summary>
|
||||
/// 设置启用或关闭系统代理
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="ip"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetAsSystemProxy(bool state, IPAddress? ip, int port)
|
||||
{
|
||||
try
|
||||
{
|
||||
var proxyEnable = $"\"ProxyEnable\"=dword:{(state ? "00000001" : "00000000")}";
|
||||
var hasIpAndProt = ip != null && port >= 0;
|
||||
var proxyServer = hasIpAndProt ? $"\"proxyServer\"=\"{ip}:{port}\"" : "";
|
||||
var reg = $"Windows Registry Editor Version 5.00{Environment.NewLine}[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings]{Environment.NewLine}{proxyEnable}{Environment.NewLine}{(state ? $"{ProxyOverride}{Environment.NewLine}" : "")}{proxyServer}";
|
||||
var path = Path.Combine(IOPath.CacheDirectory, "switchproxy.reg");
|
||||
File.WriteAllText(path, reg, Text.Encoding.UTF8);
|
||||
var p = Process2.Start("regedit", $"/s \"{path}\"", true);
|
||||
p?.WaitForExit();
|
||||
var path = IOPath.GetCacheFilePath(CacheTempDirName, "SwitchProxy", FileEx.Reg);
|
||||
File.WriteAllText(path, reg, Encoding.UTF8);
|
||||
var p = StartProcessRegedit($"/s \"{path}\"");
|
||||
IOPath.TryDeleteInDelay(p, path);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Toast.LogAndShowT(ex, TAG);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置启用或关闭PAC代理
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetAsSystemPACProxy(bool state, string? url = null)
|
||||
/// <summary>
|
||||
/// 设置启用或关闭PAC代理
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public bool SetAsSystemPACProxy(bool state, string? url = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var regAutoConfigUrl = state ? $"\"AutoConfigURL\"=\"{url}\"" : "\"AutoConfigURL\"=\"\"";
|
||||
var reg = $"Windows Registry Editor Version 5.00{Environment.NewLine}[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings]{Environment.NewLine}{regAutoConfigUrl}";
|
||||
var path = Path.Combine(IOPath.CacheDirectory, "switchpacproxy.reg");
|
||||
File.WriteAllText(path, reg, Text.Encoding.UTF8);
|
||||
var p = Process2.Start("regedit", $"/s \"{path}\"", true);
|
||||
p?.WaitForExit();
|
||||
var path = IOPath.GetCacheFilePath(CacheTempDirName, "SwitchPacProxy", FileEx.Reg);
|
||||
File.WriteAllText(path, reg, Encoding.UTF8);
|
||||
var p = StartProcessRegedit($"/s \"{path}\"");
|
||||
IOPath.TryDeleteInDelay(p, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<KeyValuePair<string, string>> GetFontsByGdiPlus()
|
||||
catch (Exception ex)
|
||||
{
|
||||
// https://docs.microsoft.com/zh-cn/typography/font-list
|
||||
var culture = R.Culture;
|
||||
InstalledFontCollection ifc = new();
|
||||
var list = ifc.Families.Where(x => x.IsStyleAvailable(FontStyle.Regular)).Select(x => KeyValuePair.Create(x.GetName(culture.LCID), x.GetName(1033))).ToList();
|
||||
list.Insert(0, IFontManager.Default);
|
||||
return list;
|
||||
Toast.LogAndShowT(ex, TAG);
|
||||
return false;
|
||||
}
|
||||
|
||||
#region IsInstall
|
||||
|
||||
static readonly Lazy<bool> _IsInstall = new(() =>
|
||||
{
|
||||
using var reg32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
|
||||
var value = reg32.Read(@"SOFTWARE\Steam++", "InstPath").TrimEnd(Path.DirectorySeparatorChar);
|
||||
return string.Equals(IOPath.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar), value, StringComparison.OrdinalIgnoreCase);
|
||||
});
|
||||
|
||||
/// <inheritdoc cref="IPlatformService.IsInstall"/>
|
||||
public static bool IsInstall => _IsInstall.Value;
|
||||
|
||||
bool IPlatformService.IsInstall => IsInstall;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<KeyValuePair<string, string>> GetFontsByGdiPlus()
|
||||
{
|
||||
// https://docs.microsoft.com/zh-cn/typography/font-list
|
||||
var culture = R.Culture;
|
||||
InstalledFontCollection ifc = new();
|
||||
var list = ifc.Families.Where(x => x.IsStyleAvailable(FontStyle.Regular)).Select(x => KeyValuePair.Create(x.GetName(culture.LCID), x.GetName(1033))).ToList();
|
||||
list.Insert(0, IFontManager.Default);
|
||||
return list;
|
||||
}
|
||||
|
||||
#region IsInstall
|
||||
|
||||
static readonly Lazy<bool> _IsInstall = new(() =>
|
||||
{
|
||||
using var reg32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
|
||||
var value = reg32.Read(@"SOFTWARE\Steam++", "InstPath").TrimEnd(Path.DirectorySeparatorChar);
|
||||
return string.Equals(IOPath.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar), value, StringComparison.OrdinalIgnoreCase);
|
||||
});
|
||||
|
||||
/// <inheritdoc cref="IPlatformService.IsInstall"/>
|
||||
public static bool IsInstall => _IsInstall.Value;
|
||||
|
||||
bool IPlatformService.IsInstall => IsInstall;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// https://github.com/microsoft/nodejstools/blob/main/Nodejs/Product/Nodejs/SharedProject/SystemUtilities.cs
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.NodejsTools.SharedProject;
|
||||
|
||||
/// <summary>
|
||||
/// Utility for accessing window IShell* interfaces in order to use them to launch a process unelevated
|
||||
/// </summary>
|
||||
internal static class SystemUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// We are elevated and should launch the process unelevated. We can't create the
|
||||
/// process directly without it becoming elevated. So to workaround this, we have
|
||||
/// explorer do the process creation (explorer is typically running unelevated).
|
||||
/// </summary>
|
||||
internal static void ExecuteProcessUnElevated(string process, string args, string currentDirectory = "")
|
||||
{
|
||||
var shellWindows = (IShellWindows)new CShellWindows();
|
||||
|
||||
// Get the desktop window
|
||||
object loc = CSIDL_Desktop;
|
||||
object unused = new object();
|
||||
var serviceProvider = (IServiceProvider)shellWindows.FindWindowSW(ref loc, ref unused, SWC_DESKTOP, out var _, SWFO_NEEDDISPATCH);
|
||||
|
||||
// Get the shell browser
|
||||
var serviceGuid = SID_STopLevelBrowser;
|
||||
var interfaceGuid = typeof(IShellBrowser).GUID;
|
||||
var shellBrowser = (IShellBrowser)serviceProvider.QueryService(ref serviceGuid, ref interfaceGuid);
|
||||
|
||||
// Get the shell dispatch
|
||||
var dispatch = typeof(IDispatch).GUID;
|
||||
var folderView = (IShellFolderViewDual)shellBrowser.QueryActiveShellView().GetItemObject(SVGIO_BACKGROUND, ref dispatch);
|
||||
var shellDispatch = (IShellDispatch2)folderView.Application;
|
||||
|
||||
// Use the dispatch (which is unelevated) to launch the process for us
|
||||
shellDispatch.ShellExecute(process, args, currentDirectory, string.Empty, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interop definitions
|
||||
/// </summary>
|
||||
private const int CSIDL_Desktop = 0;
|
||||
private const int SWC_DESKTOP = 8;
|
||||
private const int SWFO_NEEDDISPATCH = 1;
|
||||
private const int SW_SHOWNORMAL = 1;
|
||||
private const int SVGIO_BACKGROUND = 0;
|
||||
private static readonly Guid SID_STopLevelBrowser = new("4C96BE40-915C-11CF-99D3-00AA004AE837");
|
||||
|
||||
[ComImport]
|
||||
[Guid("9BA05972-F6A8-11CF-A442-00A0C90A8F39")]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
private class CShellWindows
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("85CB6900-4D95-11CF-960C-0080C7F4EE85")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||
private interface IShellWindows
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.IDispatch)]
|
||||
object FindWindowSW([MarshalAs(UnmanagedType.Struct)] ref object pvarloc, [MarshalAs(UnmanagedType.Struct)] ref object pvarlocRoot, int swClass, out int pHWND, int swfwOptions);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IServiceProvider
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object QueryService(ref Guid guidService, ref Guid riid);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("000214E2-0000-0000-C000-000000000046")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IShellBrowser
|
||||
{
|
||||
void VTableGap01(); // GetWindow
|
||||
|
||||
void VTableGap02(); // ContextSensitiveHelp
|
||||
|
||||
void VTableGap03(); // InsertMenusSB
|
||||
|
||||
void VTableGap04(); // SetMenuSB
|
||||
|
||||
void VTableGap05(); // RemoveMenusSB
|
||||
|
||||
void VTableGap06(); // SetStatusTextSB
|
||||
|
||||
void VTableGap07(); // EnableModelessSB
|
||||
|
||||
void VTableGap08(); // TranslateAcceleratorSB
|
||||
|
||||
void VTableGap09(); // BrowseObject
|
||||
|
||||
void VTableGap10(); // GetViewStateStream
|
||||
|
||||
void VTableGap11(); // GetControlWindow
|
||||
|
||||
void VTableGap12(); // SendControlMsg
|
||||
|
||||
IShellView QueryActiveShellView();
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("000214E3-0000-0000-C000-000000000046")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IShellView
|
||||
{
|
||||
void VTableGap01(); // GetWindow
|
||||
|
||||
void VTableGap02(); // ContextSensitiveHelp
|
||||
|
||||
void VTableGap03(); // TranslateAcceleratorA
|
||||
|
||||
void VTableGap04(); // EnableModeless
|
||||
|
||||
void VTableGap05(); // UIActivate
|
||||
|
||||
void VTableGap06(); // Refresh
|
||||
|
||||
void VTableGap07(); // CreateViewWindow
|
||||
|
||||
void VTableGap08(); // DestroyViewWindow
|
||||
|
||||
void VTableGap09(); // GetCurrentInfo
|
||||
|
||||
void VTableGap10(); // AddPropertySheetPages
|
||||
|
||||
void VTableGap11(); // SaveViewState
|
||||
|
||||
void VTableGap12(); // SelectItem
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetItemObject(uint aspectOfView, ref Guid riid);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("00020400-0000-0000-C000-000000000046")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||
private interface IDispatch
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("E7A1AF80-4D96-11CF-960C-0080C7F4EE85")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||
private interface IShellFolderViewDual
|
||||
{
|
||||
object Application
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.IDispatch)]
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("A4C6892C-3BA9-11D2-9DEA-00C04FB16162")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||
public interface IShellDispatch2
|
||||
{
|
||||
void ShellExecute([MarshalAs(UnmanagedType.BStr)] string file, [MarshalAs(UnmanagedType.Struct)] object vArgs, [MarshalAs(UnmanagedType.Struct)] object vDir, [MarshalAs(UnmanagedType.Struct)] object vOperation, [MarshalAs(UnmanagedType.Struct)] object vShow);
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@
|
||||
<ProjectReference Include="..\Common.CoreLib\Common.CoreLib.csproj" />
|
||||
<ProjectReference Include="..\ST.Client.CommandLine\ST.Client.CommandLine.csproj" />
|
||||
<ProjectReference Include="..\ST.Client.Maui\ST.Client.Maui.csproj" />
|
||||
<ProjectReference Include="..\ST.Client.ReverseProxy.Yarp\ST.Client.ReverseProxy.Yarp.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
|
||||
|
||||
@@ -86,7 +86,7 @@ public partial class AppShell : Shell, IViewFor<MainWindowViewModel>
|
||||
|
||||
void InitTabItems(MainWindowViewModel mainWindow, IEnumerable<TabItemId>? topTabs = null)
|
||||
{
|
||||
var tabItems = mainWindow.AllTabItems.Where(x => x.Id != TabItemId.GameList);
|
||||
var tabItems = mainWindow.TabItems.Where(x => x.Id != TabItemId.GameList);
|
||||
if (topTabs.Any_Nullable())
|
||||
{
|
||||
tabItems = tabItems.Where(x => topTabs.Contains(x.Id)).Concat(tabItems.Where(x => !topTabs.Contains(x.Id)));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220725" android:versionName="2.8.2" package="net.steampp.app" android:installLocation="auto">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220814" android:versionName="2.8.3" package="net.steampp.app" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
|
||||
<application android:fullBackupContent="@xml/auto_backup_rules"></application>
|
||||
<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
<Import Condition=" Exists('$(MSBuildProjectDirectory)\..\..\Xamarin.Android.KeyStore.props') " Project="..\..\Xamarin.Android.KeyStore.props" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties XamarinHotReloadWrongLinkerErrorInfoBarSTClientMobileDroidAppHideInfoBar="True" XamarinHotReloadDebuggerTimeoutExceptionSTClientAndroidAppHideInfoBar="True" />
|
||||
<UserProperties XamarinHotReloadDebuggerTimeoutExceptionSTClientAndroidAppHideInfoBar="True" XamarinHotReloadWrongLinkerErrorInfoBarSTClientMobileDroidAppHideInfoBar="True" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
@@ -56,8 +56,8 @@ sealed partial class TitaniumCertificateManagerImpl : CertificateManagerImpl, IC
|
||||
=> manager.CreateRootCertificate(true);
|
||||
|
||||
protected override void SharedRemoveTrustedRootCertificate()
|
||||
=> manager.RemoveTrustedRootCertificate(false);
|
||||
=> manager.RemoveTrustedRootCertificate(true);
|
||||
|
||||
protected override void SharedTrustRootCertificate()
|
||||
=> manager.TrustRootCertificate(false);
|
||||
=> manager.TrustRootCertificate(true);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,9 @@ public static partial class ServiceCollectionExtensions
|
||||
internal static IServiceCollection AddReverseProxyServer(this IServiceCollection services)
|
||||
{
|
||||
// https://github.com/dotnetcore/FastGithub/blob/2.1.4/FastGithub.HttpServer/ServiceCollectionExtensions.cs#L15
|
||||
|
||||
CookieHttpClient.AddHttpClient(services);
|
||||
|
||||
return services
|
||||
.AddMemoryCache()
|
||||
.AddHttpForwarder()
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Net;
|
||||
|
||||
namespace System.Application.Services.Implementation;
|
||||
|
||||
sealed class CookieHttpClient
|
||||
{
|
||||
public static readonly CookieContainer CookieContainer = new();
|
||||
|
||||
public const string HttpClientName = "CookieHttpClient";
|
||||
|
||||
readonly IHttpClientFactory httpClientFactory;
|
||||
|
||||
public CookieHttpClient(IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
this.httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public HttpClient HttpClient => httpClientFactory.CreateClient(HttpClientName);
|
||||
|
||||
public static void AddHttpClient(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<CookieHttpClient>();
|
||||
services.AddHttpClient(HttpClientName, (s, c) =>
|
||||
{
|
||||
c.Timeout = GeneralHttpClientFactory.DefaultTimeout;
|
||||
}).ConfigurePrimaryHttpMessageHandler(() => GeneralHttpClientFactory.CreateSocketsHttpHandler(new()
|
||||
{
|
||||
UseCookies = true,
|
||||
CookieContainer = CookieContainer,
|
||||
}));
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -11,11 +11,11 @@ namespace System.Application.Services.Implementation.Http;
|
||||
/// </summary>
|
||||
public class ReverseProxyHttpClient : HttpMessageInvoker
|
||||
{
|
||||
/// <summary>
|
||||
/// 插入的 UserAgent 标记
|
||||
/// </summary>
|
||||
static readonly ProductInfoHeaderValue userAgent
|
||||
= new(new ProductHeaderValue(Constants.HARDCODED_APP_NAME_NEW, ThisAssembly.Version));
|
||||
///// <summary>
|
||||
///// 插入的 UserAgent 标记
|
||||
///// </summary>
|
||||
//static readonly ProductInfoHeaderValue userAgent
|
||||
// = new(new ProductHeaderValue(Constants.HARDCODED_APP_NAME_NEW + "_" + DateTimeOffset.UtcNow.Ticks, ThisAssembly.Version));
|
||||
|
||||
public ReverseProxyHttpClient(IDomainConfig domainConfig, IDomainResolver domainResolver)
|
||||
: this(new ReverseProxyHttpClientHandler(domainConfig, domainResolver), disposeHandler: true)
|
||||
@@ -36,14 +36,14 @@ public class ReverseProxyHttpClient : HttpMessageInvoker
|
||||
/// <exception cref="Exception"></exception>
|
||||
public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (request.Headers.UserAgent.Contains(userAgent))
|
||||
{
|
||||
const string message =
|
||||
$"Because {{0}} actually points to {Constants.HARDCODED_APP_NAME_NEW} itself, " +
|
||||
$"{Constants.HARDCODED_APP_NAME_NEW} has interrupted this forwarding";
|
||||
throw new ApplicationException(string.Format(message, request.RequestUri));
|
||||
}
|
||||
request.Headers.UserAgent.Add(userAgent);
|
||||
//if (request.Headers.UserAgent.Contains(userAgent))
|
||||
//{
|
||||
// const string message =
|
||||
// $"Because {{0}} actually points to {Constants.HARDCODED_APP_NAME_NEW} itself, " +
|
||||
// $"{Constants.HARDCODED_APP_NAME_NEW} has interrupted this forwarding";
|
||||
// throw new ApplicationException(string.Format(message, request.RequestUri));
|
||||
//}
|
||||
//request.Headers.UserAgent.Add(userAgent);
|
||||
var response = await base.SendAsync(request, cancellationToken);
|
||||
response.Headers.Server.TryParseAdd(Constants.HARDCODED_APP_NAME_NEW);
|
||||
return response;
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ sealed class ReverseProxyHttpClientHandler : DelegatingHandler
|
||||
/// <returns></returns>
|
||||
SocketsHttpHandler CreateSocketsHttpHandler() => GeneralHttpClientFactory.CreateSocketsHttpHandler(new()
|
||||
{
|
||||
Proxy = null,
|
||||
Proxy = GeneralHttpClientFactory.HttpNoProxy.Instance,
|
||||
UseProxy = false,
|
||||
UseCookies = false,
|
||||
AllowAutoRedirect = false,
|
||||
|
||||
+96
-68
@@ -3,6 +3,7 @@ using System.Application.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using System.Net;
|
||||
|
||||
namespace System.Application.Services.Implementation.HttpServer.Middleware;
|
||||
|
||||
@@ -12,10 +13,16 @@ namespace System.Application.Services.Implementation.HttpServer.Middleware;
|
||||
sealed class HttpLocalRequestMiddleware
|
||||
{
|
||||
readonly IReverseProxyConfig reverseProxyConfig;
|
||||
readonly CookieHttpClient cookieHttpClient;
|
||||
|
||||
public HttpLocalRequestMiddleware(IReverseProxyConfig reverseProxyConfig)
|
||||
HttpClient HttpClient => cookieHttpClient.HttpClient;
|
||||
|
||||
public HttpLocalRequestMiddleware(
|
||||
IReverseProxyConfig reverseProxyConfig,
|
||||
CookieHttpClient cookieHttpClient)
|
||||
{
|
||||
this.reverseProxyConfig = reverseProxyConfig;
|
||||
this.cookieHttpClient = cookieHttpClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -26,9 +33,15 @@ sealed class HttpLocalRequestMiddleware
|
||||
/// <returns></returns>
|
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||
{
|
||||
if (HttpMethods.IsOptions(context.Request.Method) && context.Request.Headers.ContainsKey("Access-Control-Request-Private-Network"))
|
||||
{
|
||||
// https://wicg.github.io/private-network-access/
|
||||
context.Response.Headers["Access-Control-Allow-Private-Network"] = "true";
|
||||
}
|
||||
|
||||
if (context.Request.Host.Host.Equals(IReverseProxyService.LocalDomain, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (context.Request.Method.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase))
|
||||
if (HttpMethods.IsOptions(context.Request.Method))
|
||||
{
|
||||
context.Response.Headers.AccessControlAllowOrigin = context.Request.Headers.Origin.Count == 0 ? "*" : context.Request.Headers.Origin;
|
||||
context.Response.Headers.AccessControlAllowHeaders = "*";
|
||||
@@ -66,6 +79,7 @@ sealed class HttpLocalRequestMiddleware
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await next(context);
|
||||
}
|
||||
|
||||
@@ -74,81 +88,98 @@ sealed class HttpLocalRequestMiddleware
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
static async Task HandleHttpRequestAsync(HttpContext context)
|
||||
async Task HandleHttpRequestAsync(HttpContext context)
|
||||
{
|
||||
if (string.IsNullOrEmpty(context.Request.QueryString.Value))
|
||||
return;
|
||||
|
||||
var url = Web.HttpUtility.UrlDecode(context.Request.QueryString.Value.Replace("?request=", ""));
|
||||
string? cookie = context.Request.Headers["cookie-steamTool"];
|
||||
if (string.IsNullOrEmpty(cookie))
|
||||
cookie = context.Request.Headers["Cookie"];
|
||||
string? referer = context.Request.Headers["Referer-steamTool"];
|
||||
|
||||
context.Response.Headers.AccessControlAllowOrigin = context.Request.Headers.Origin.Count == 0 ? "*" : context.Request.Headers.Origin;
|
||||
context.Response.Headers.AccessControlAllowHeaders = "*";
|
||||
context.Response.Headers.AccessControlAllowMethods = "*";
|
||||
context.Response.Headers.AccessControlAllowCredentials = "true";
|
||||
|
||||
//if (cookie != null)
|
||||
// context.Response.Cookies.Append(cookie);
|
||||
|
||||
if (context.Request.ContentType != null)
|
||||
context.Response.Headers.ContentType = context.Request.ContentType;
|
||||
|
||||
if (context.Request.Method == HttpMethods.Get)
|
||||
try
|
||||
{
|
||||
var body = await IHttpService.Instance.GetAsync<string>(url, cookie: cookie);
|
||||
if (string.IsNullOrEmpty(body))
|
||||
if (string.IsNullOrEmpty(context.Request.QueryString.Value))
|
||||
return;
|
||||
|
||||
var url = Web.HttpUtility.UrlDecode(context.Request.QueryString.Value.Replace("?request=", ""));
|
||||
string? cookie = context.Request.Headers["cookie-steamTool"];
|
||||
if (string.IsNullOrEmpty(cookie))
|
||||
cookie = context.Request.Headers["Cookie"];
|
||||
string? referer = context.Request.Headers["Referer-steamTool"];
|
||||
|
||||
context.Response.Headers.AccessControlAllowOrigin = context.Request.Headers.Origin.Count == 0 ? "*" : context.Request.Headers.Origin;
|
||||
context.Response.Headers.AccessControlAllowHeaders = "*";
|
||||
context.Response.Headers.AccessControlAllowMethods = "*";
|
||||
context.Response.Headers.AccessControlAllowCredentials = "true";
|
||||
|
||||
//if (cookie != null)
|
||||
// context.Response.Cookies.Append(cookie);
|
||||
|
||||
if (context.Request.ContentType != null)
|
||||
context.Response.Headers.ContentType = context.Request.ContentType;
|
||||
|
||||
async Task SendAsync()
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
}
|
||||
await context.Response.WriteAsync(body);
|
||||
}
|
||||
else if (context.Request.Method == HttpMethods.Post)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (context.Request.ContentLength > 0)
|
||||
var method = context.Request.Method;
|
||||
var hasContent = method != HttpMethods.Get && context.Request.ContentLength > 0;
|
||||
var req = new HttpRequestMessage
|
||||
{
|
||||
var conext = await IHttpService.Instance.SendAsync<string>(url, () =>
|
||||
RequestUri = new Uri(url),
|
||||
Method = new(method),
|
||||
Content = hasContent ? new StreamContent(context.Request.Body) : null,
|
||||
};
|
||||
req.Headers.UserAgent.ParseAdd(context.Request.Headers.UserAgent);
|
||||
if (cookie != null)
|
||||
{
|
||||
CookieHttpClient.CookieContainer.Add(new Cookie
|
||||
{
|
||||
var req = new HttpRequestMessage
|
||||
{
|
||||
RequestUri = new Uri(url),
|
||||
Method = HttpMethod.Post,
|
||||
Content = new StreamContent(context.Request.Body),
|
||||
};
|
||||
if (cookie != null)
|
||||
{
|
||||
req.Headers.Add("Cookie", cookie);
|
||||
}
|
||||
if (referer != null)
|
||||
req.Headers.Referrer = new Uri(referer);
|
||||
|
||||
req.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(context.Request.ContentType);
|
||||
req.Content.Headers.ContentLength = context.Request.ContentLength;
|
||||
return req;
|
||||
}, null/*, false*/, default);
|
||||
|
||||
if (string.IsNullOrEmpty(conext))
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
return;
|
||||
}
|
||||
await context.Response.WriteAsync(conext);
|
||||
CommentUri = req.RequestUri,
|
||||
Domain = req.RequestUri.Host,
|
||||
Value = cookie
|
||||
});
|
||||
// req.Headers.Add("Cookie", cookie);
|
||||
}
|
||||
if (referer != null) req.Headers.Referrer = new Uri(referer);
|
||||
if (hasContent)
|
||||
{
|
||||
req.Content!.Headers.ContentType = MediaTypeHeaderValue.Parse(context.Request.ContentType);
|
||||
req.Content.Headers.ContentLength = context.Request.ContentLength;
|
||||
}
|
||||
var rsp = await HttpClient.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted).ConfigureAwait(false);
|
||||
if (rsp.IsSuccessStatusCode && rsp.Content != null)
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status200OK;
|
||||
using var body = await rsp.Content.ReadAsStreamAsync(context.RequestAborted);
|
||||
await body.CopyToAsync(context.Response.BodyWriter.AsStream(), context.RequestAborted);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception error)
|
||||
|
||||
if (context.Request.Method == HttpMethods.Get)
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
await context.Response.WriteAsync(error.Message);
|
||||
await SendAsync();
|
||||
return;
|
||||
}
|
||||
else if (context.Request.Method == HttpMethods.Post)
|
||||
{
|
||||
if (context.Request.ContentLength > 0)
|
||||
{
|
||||
await SendAsync();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
await context.Response.WriteAsync(error.Message, context.RequestAborted);
|
||||
}
|
||||
}
|
||||
|
||||
static async Task HandleStatusCodeAsync(HttpContext context, int statusCode)
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(string.Empty, context.RequestAborted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -156,9 +187,6 @@ sealed class HttpLocalRequestMiddleware
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
static async Task Handle404NotFoundAsync(HttpContext context)
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status404NotFound;
|
||||
await context.Response.WriteAsync(string.Empty);
|
||||
}
|
||||
static Task Handle404NotFoundAsync(HttpContext context)
|
||||
=> HandleStatusCodeAsync(context, StatusCodes.Status404NotFound);
|
||||
}
|
||||
|
||||
+34
-21
@@ -1,5 +1,6 @@
|
||||
// https://github.com/dotnetcore/FastGithub/blob/2.1.4/FastGithub.HttpServer/HttpReverseProxyMiddleware.cs
|
||||
|
||||
using DynamicData.Kernel;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -60,17 +61,28 @@ sealed class HttpReverseProxyMiddleware
|
||||
if (TryGetDomainConfig(url, out var domainConfig) == false)
|
||||
{
|
||||
await next(context);
|
||||
if (isScriptInject)
|
||||
await HandleScriptInject(context, scriptConfigs, memoryStream!, originalBody!);
|
||||
return;
|
||||
}
|
||||
|
||||
if (domainConfig == defaultDomainConfig &&
|
||||
!reverseProxyConfig.Service.OnlyEnableProxyScript)
|
||||
{
|
||||
//部分运营商将奇怪的域名解析到127.0.0.1 再此排除这些不支持的代理域名
|
||||
var ip = await reverseProxyConfig.DnsAnalysis.AnalysisDomainIpAsync(context.Request.Host.Value, IDnsAnalysisService.DNS_Dnspods).FirstOrDefaultAsync();
|
||||
if (ip == null || IPAddress.IsLoopback(ip))
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||
await context.Response.WriteAsync($"域名 {context.Request.Host.Host} 可能已经被 DNS 污染,如果域名为本机域名,请解析为非回环 IP。", Encoding.UTF8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (domainConfig.Items.Any_Nullable())
|
||||
domainConfig = RecursionMatchDomainConfig(url, domainConfig);
|
||||
|
||||
if (domainConfig.Response == null)
|
||||
{
|
||||
if (IReverseProxyService.Instance.EnableHttpProxyToHttps && context.Request.Scheme == Uri.UriSchemeHttp)
|
||||
if (reverseProxyConfig.Service.EnableHttpProxyToHttps && context.Request.Scheme == Uri.UriSchemeHttp)
|
||||
{
|
||||
context.Response.Redirect(Uri.UriSchemeHttps + "://" + context.Request.Host.Host + context.Request.RawUrl());
|
||||
return;
|
||||
@@ -126,7 +138,7 @@ sealed class HttpReverseProxyMiddleware
|
||||
{
|
||||
domainConfig = null;
|
||||
|
||||
if (!IReverseProxyService.Instance.OnlyEnableProxyScript && reverseProxyConfig.TryGetDomainConfig(uri, out domainConfig) == true)
|
||||
if (!reverseProxyConfig.Service.OnlyEnableProxyScript && reverseProxyConfig.TryGetDomainConfig(uri, out domainConfig) == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -135,9 +147,8 @@ sealed class HttpReverseProxyMiddleware
|
||||
// 未配置的域名,但仍然被解析到本机 IP 的域名
|
||||
if (IsDomain(host))
|
||||
{
|
||||
if (IReverseProxyService.Instance.ProxyMode != ProxyMode.System)
|
||||
logger.LogWarning(
|
||||
$"域名 {host} 可能已经被 DNS 污染,如果域名为本机域名,请解析为非回环 IP。");
|
||||
logger.LogWarning(
|
||||
$"域名 {host} 可能已经被 DNS 污染,如果域名为本机域名,请解析为非回环 IP。");
|
||||
domainConfig = defaultDomainConfig;
|
||||
return true;
|
||||
}
|
||||
@@ -180,11 +191,7 @@ sealed class HttpReverseProxyMiddleware
|
||||
/// <returns></returns>
|
||||
static async Task HandleErrorAsync(HttpContext context, ForwarderError error)
|
||||
{
|
||||
await context.Response.WriteAsJsonAsync(new
|
||||
{
|
||||
error = error.ToString(),
|
||||
message = context.GetForwarderErrorFeature()?.Exception?.Message,
|
||||
});
|
||||
await context.Response.WriteAsync($"{error}:{context.GetForwarderErrorFeature()?.Exception?.Message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -487,18 +494,24 @@ sealed class HttpReverseProxyMiddleware
|
||||
match_mark_start_index++;
|
||||
if (match_mark_start_index >= mark_start.Length)
|
||||
{
|
||||
const int matchCharCount = 4;
|
||||
var index_name_start = i + mark_start.Length;
|
||||
var name = encoding.GetString(buffer.Span[index_name_start..index_name_end]);
|
||||
if (name.Equals("body", StringComparison.OrdinalIgnoreCase) ||
|
||||
name.Equals("head", StringComparison.OrdinalIgnoreCase))
|
||||
//if (encoding.GetMaxCharCount(index_name_end - index_name_start) >= matchCharCount)
|
||||
//{
|
||||
var bytes = buffer.Span[index_name_start..index_name_end];
|
||||
var charCount = encoding.GetCharCount(bytes);
|
||||
if (charCount == matchCharCount)
|
||||
{
|
||||
insertPosition = index_name_start - mark_start.Length;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto reset;
|
||||
var name = encoding.GetString(bytes);
|
||||
if (name.Equals("body", StringComparison.OrdinalIgnoreCase) ||
|
||||
name.Equals("head", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
insertPosition = index_name_start - mark_start.Length;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//}
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -78,7 +78,7 @@ sealed partial class YarpCertificateManagerImpl : CertificateManagerImpl, ICerti
|
||||
"Could not remove certificate as it is null or empty.");
|
||||
}
|
||||
|
||||
using var x509Store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
|
||||
using var x509Store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -96,7 +96,7 @@ sealed partial class YarpCertificateManagerImpl : CertificateManagerImpl, ICerti
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(TAG, new ApplicationException(
|
||||
"Failed to remove root certificate trust for CurrentUser store location. You may need admin rights.", e), nameof(SharedRemoveTrustedRootCertificate));
|
||||
"Failed to remove root certificate trust for LocalMachine store location. You may need admin rights.", e), nameof(SharedRemoveTrustedRootCertificate));
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -112,7 +112,7 @@ sealed partial class YarpCertificateManagerImpl : CertificateManagerImpl, ICerti
|
||||
"Could not install certificate as it is null or empty.");
|
||||
}
|
||||
|
||||
using var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
|
||||
using var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
|
||||
try
|
||||
{
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
|
||||
+2
-1
@@ -68,7 +68,8 @@ sealed partial class YarpReverseProxyServiceImpl : ReverseProxyServiceImpl, IRev
|
||||
else
|
||||
{
|
||||
options.ListenHttpsReverseProxy();
|
||||
options.ListenHttpReverseProxy();
|
||||
if (EnableHttpProxyToHttps)
|
||||
options.ListenHttpReverseProxy();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -78,13 +78,13 @@ public interface ICertificateManager
|
||||
/// <summary>
|
||||
/// 由平台实现的信任根证书引导,有 Root 权限将尝试执行信任,否则则 UI 引导,跳转网页或弹窗
|
||||
/// </summary>
|
||||
void PlatformTrustRootCertificateGuide();
|
||||
ValueTask PlatformTrustRootCertificateGuide();
|
||||
|
||||
/// <summary>
|
||||
/// 安装根证书,如果没有证书将生成一个新的
|
||||
/// </summary>
|
||||
/// <returns>返回根证书是否受信任</returns>
|
||||
bool SetupRootCertificate();
|
||||
ValueTask<bool> SetupRootCertificate();
|
||||
|
||||
/// <summary>
|
||||
/// 删除根证书,如果没有证书将返回 <see langword="true"/>
|
||||
|
||||
@@ -117,7 +117,7 @@ public interface IReverseProxyService : IDisposable
|
||||
/// <returns></returns>
|
||||
bool PortInUse(int port);
|
||||
|
||||
Task<bool> StartProxy();
|
||||
ValueTask<bool> StartProxy();
|
||||
|
||||
Task StopProxy();
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ abstract partial class CertificateManagerImpl
|
||||
}
|
||||
}
|
||||
|
||||
void TrustRootCertificate()
|
||||
async ValueTask TrustRootCertificate()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -102,17 +102,17 @@ abstract partial class CertificateManagerImpl
|
||||
catch { }
|
||||
#endif
|
||||
|
||||
PlatformTrustRootCertificateGuide();
|
||||
await PlatformTrustRootCertificateGuide();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICertificateManager.PlatformTrustRootCertificateGuide"/>
|
||||
public void PlatformTrustRootCertificateGuide()
|
||||
public async ValueTask PlatformTrustRootCertificateGuide()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (OperatingSystem2.IsMacOS())
|
||||
{
|
||||
TrustRootCertificateMacOS();
|
||||
await TrustRootCertificateMacOS();
|
||||
}
|
||||
else if (OperatingSystem2.IsLinux() && !OperatingSystem2.IsAndroid())
|
||||
{
|
||||
@@ -130,11 +130,14 @@ abstract partial class CertificateManagerImpl
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("macOS")]
|
||||
void TrustRootCertificateMacOS()
|
||||
async ValueTask TrustRootCertificateMacOS()
|
||||
{
|
||||
var filePath = GetCerFilePathGeneratedWhenNoFileExists();
|
||||
if (filePath == null) return;
|
||||
platformService.RunShell($"security add-trusted-cert -d -r trustRoot -k /Users/{Environment.UserName}/Library/Keychains/login.keychain-db \\\"{filePath}\\\"", true);
|
||||
var state = await platformService.TrustRootCertificate(filePath);
|
||||
//await platformService.RunShellAsync($"security add-trusted-cert -d -r trustRoot -k /Users/{Environment.UserName}/Library/Keychains/login.keychain-db \\\"{filePath}\\\"", true);
|
||||
if (state != null && !IsRootCertificateInstalled)
|
||||
await TrustRootCertificateMacOS();
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("Linux")]
|
||||
@@ -152,12 +155,12 @@ abstract partial class CertificateManagerImpl
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICertificateManager.SetupRootCertificate"/>
|
||||
public bool SetupRootCertificate()
|
||||
public async ValueTask<bool> SetupRootCertificate()
|
||||
{
|
||||
if (!GenerateCertificate()) return false;
|
||||
if (!IsRootCertificateInstalled)
|
||||
{
|
||||
TrustRootCertificate();
|
||||
await TrustRootCertificate();
|
||||
return IsRootCertificateInstalled;
|
||||
}
|
||||
return true;
|
||||
@@ -207,7 +210,7 @@ abstract partial class CertificateManagerImpl
|
||||
[SupportedOSPlatform("Linux")]
|
||||
void DeleteRootCertificateLinux()
|
||||
{
|
||||
using var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
|
||||
using var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
var collection = store.Certificates.Find(X509FindType.FindByIssuerName, IReverseProxyService.RootCertificateName, false);
|
||||
foreach (var item in collection)
|
||||
@@ -230,7 +233,7 @@ abstract partial class CertificateManagerImpl
|
||||
[SupportedOSPlatform("macOS")]
|
||||
async void DeleteRootCertificateMacOS()
|
||||
{
|
||||
using var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
|
||||
using var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
var collection = store.Certificates.Find(X509FindType.FindByIssuerName, IReverseProxyService.RootCertificateName, false);
|
||||
foreach (var item in collection)
|
||||
@@ -284,7 +287,7 @@ abstract partial class CertificateManagerImpl
|
||||
}
|
||||
else
|
||||
{
|
||||
using var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
|
||||
using var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
return store.Certificates.Contains(certificate2);
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@ abstract class ReverseProxyServiceImpl
|
||||
|
||||
public ReverseProxyServiceImpl(
|
||||
IPlatformService platformService,
|
||||
IDnsAnalysisService dnsAnalysis)
|
||||
IDnsAnalysisService dnsAnalyses)
|
||||
{
|
||||
this.platformService = platformService;
|
||||
DnsAnalysis = dnsAnalysis;
|
||||
DnsAnalysis = dnsAnalyses;
|
||||
}
|
||||
|
||||
public IDnsAnalysisService DnsAnalysis { get; }
|
||||
public IDnsAnalysisService? DnsAnalysis { get; }
|
||||
|
||||
public abstract ICertificateManager CertificateManager { get; }
|
||||
|
||||
@@ -153,14 +153,15 @@ abstract class ReverseProxyServiceImpl
|
||||
|
||||
public abstract EReverseProxyEngine ReverseProxyEngine { get; }
|
||||
|
||||
public async Task<bool> StartProxy()
|
||||
public async ValueTask<bool> StartProxy()
|
||||
{
|
||||
if (!CertificateManager.IsRootCertificateInstalled)
|
||||
{
|
||||
//CertificateManager.DeleteRootCertificate();
|
||||
var isOk = CertificateManager.SetupRootCertificate();
|
||||
var isOk = await CertificateManager.SetupRootCertificate();
|
||||
if (!isOk)
|
||||
{
|
||||
Log.Error("StartProxy", "证书安装失败,或未信任。");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,7 +805,7 @@ namespace System.Application.Models
|
||||
return this;
|
||||
}
|
||||
|
||||
public static SteamApp? FromReader(BinaryReader reader, uint[]? installedAppIds = null, bool isSaveProperties = false)
|
||||
public static SteamApp? FromReader(BinaryReader reader, uint[]? installedAppIds = null, bool isSaveProperties = false, bool is0x07564428 = true)
|
||||
{
|
||||
uint id = reader.ReadUInt32();
|
||||
if (id == 0)
|
||||
@@ -825,6 +825,9 @@ namespace System.Application.Models
|
||||
binaryReader.ReadBytes(20);
|
||||
app._changeNumber = binaryReader.ReadUInt32();
|
||||
|
||||
if (is0x07564428)
|
||||
binaryReader.ReadBytes(20);
|
||||
|
||||
var properties = SteamAppPropertyHelper.ReadPropertyTable(binaryReader);
|
||||
|
||||
if (properties == null)
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
<AssemblyName>System.Application.SteamTools.Client</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" $(TargetFramework.Contains('-android')) ">
|
||||
<DefineConstants>EXCLUDE_ASF;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
@@ -37,13 +41,18 @@
|
||||
<!--<PackageReference Include="CommunityToolkit.Mvvm"/>-->
|
||||
<PackageReference Include="ReactiveUI.Fody" />
|
||||
<!--<PackageReference Include="ArchiSteamFarm.Library" />-->
|
||||
<PackageReference Include="Ae.DNS.Client" />
|
||||
<!--<PackageReference Include="Ae.Dns.Protocol" />-->
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
|
||||
<PackageReference Include="JustArchiNET.Madness" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ItemGroup Condition=" !$(TargetFramework.Contains('-android')) ">
|
||||
<ProjectReference Include="..\..\references\ArchiSteamFarm\ArchiSteamFarm.Library\ArchiSteamFarm.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Common.PinyinLib\Common.PinyinLib.csproj" />
|
||||
<ProjectReference Include="..\Repositories.sqlite-net-pcl\Repositories.sqlite-net-pcl.csproj" />
|
||||
<ProjectReference Include="..\ST.Client.ReverseProxy\ST.Client.ReverseProxy.csproj" />
|
||||
@@ -84,4 +93,5 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !EXCLUDE_ASF
|
||||
using ArchiSteamFarm;
|
||||
using ArchiSteamFarm.Steam;
|
||||
using ArchiSteamFarm.Storage;
|
||||
@@ -79,4 +80,5 @@ namespace System.Application.Services
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !EXCLUDE_ASF
|
||||
using ArchiSteamFarm;
|
||||
using System.Application.Settings;
|
||||
using System.Collections.Generic;
|
||||
@@ -30,3 +31,4 @@ partial interface IArchiSteamFarmService : IArchiSteamFarmHelperService
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -12,9 +12,16 @@ namespace System.Application.Services
|
||||
/// </summary>
|
||||
public interface IDnsAnalysisService
|
||||
{
|
||||
protected const string TAG = "DnsAnalysisService";
|
||||
|
||||
static IDnsAnalysisService Instance => DI.Get<IDnsAnalysisService>();
|
||||
|
||||
#region DNS常量
|
||||
const string DNS_Ali_DohAddres = "https://dns.alidns.com";
|
||||
const string Dnspod_DohAddres = "https://1.12.12.12";
|
||||
const string Google_DohAddres = "https://dns.google";
|
||||
const string Cloudflare_DohAddres = "https://cloudflare-dns.com";
|
||||
|
||||
protected const string PrimaryDNS_IPV6_Ali = "2400:3200::1";
|
||||
|
||||
const string PrimaryDNS_Ali = "223.5.5.5";
|
||||
@@ -66,7 +73,7 @@ namespace System.Application.Services
|
||||
return r.RoundtripTime;
|
||||
}
|
||||
|
||||
int AnalysisHostnameTime(string url);
|
||||
Task<int> AnalysisHostnameTime(string url, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 解析域名 IP 地址
|
||||
@@ -119,6 +126,19 @@ namespace System.Application.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DOH 解析域名 IP 地址
|
||||
/// </summary>
|
||||
/// <param name="hostNameOrAddress">要解析的主机名或 IP 地址</param>
|
||||
/// <param name="dnsServers">自定义 DNS 服务器,可选的值有 <see cref="DNS_Alis"/>, <see cref="DNS_114s"/>, <see cref="DNS_Cloudflares"/>, <see cref="DNS_Dnspods"/>, <see cref="DNS_Googles"/></param>
|
||||
/// <param name="isIPv6"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<IPAddress>? DohAnalysisDomainIpAsync(string hostNameOrAddress, string? dnsServers, bool isIPv6, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
async Task<string?> GetHostByIPAddress(IPAddress ip)
|
||||
{
|
||||
var hostEntry = await Dns.GetHostEntryAsync(ip);
|
||||
@@ -126,5 +146,7 @@ namespace System.Application.Services
|
||||
}
|
||||
|
||||
Task<bool> GetIsIpv6Support() => Task.FromResult(false);
|
||||
|
||||
Task<IPAddress?> GetHostIpv6Addres() => Task.FromResult(default(IPAddress));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Application.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// DNS 解析服务
|
||||
/// </summary>
|
||||
public interface IDnsDohAnalysisService
|
||||
{
|
||||
protected const string TAG = "DnsDohAnalysisService";
|
||||
|
||||
static IDnsDohAnalysisService Instance => DI.Get<IDnsDohAnalysisService>();
|
||||
|
||||
#region DNS常量
|
||||
const string DNS_Ali_DohAddres = "https://dns.alidns.com/dns-query";
|
||||
|
||||
const string Dnspod_DohAddres = "https://1.12.12.12/dns-query";
|
||||
|
||||
const string Google_DohAddres = "https://dns.google/dns-query";
|
||||
|
||||
const string Cloudflare_DohAddres = "https://cloudflare-dns.com/dns-query";
|
||||
#endregion
|
||||
|
||||
protected const string IPV6_TESTDOMAIN = "ipv6.rmbgame.net";
|
||||
|
||||
/// <summary>
|
||||
/// 解析域名 IP 地址
|
||||
/// </summary>
|
||||
/// <param name="hostNameOrAddress">要解析的主机名或 IP 地址</param>
|
||||
/// <param name="isIPv6"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<IPAddress> AnalysisDomainIpAsync(string hostNameOrAddress, bool isIPv6, CancellationToken cancellationToken = default)
|
||||
=> AnalysisDomainIpAsync(hostNameOrAddress, default, isIPv6, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 解析域名 IP 地址
|
||||
/// </summary>
|
||||
/// <param name="hostNameOrAddress">要解析的主机名或 IP 地址</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<IPAddress> AnalysisDomainIpAsync(string hostNameOrAddress, CancellationToken cancellationToken = default)
|
||||
=> AnalysisDomainIpAsync(hostNameOrAddress, default, default, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 解析域名 IP 地址
|
||||
/// </summary>
|
||||
/// <param name="hostNameOrAddress">要解析的主机名或 IP 地址</param>
|
||||
/// <param name="dnsServers">自定义 DNS 服务器,可选的值有 <see cref="DNS_Alis"/>, <see cref="DNS_114s"/>, <see cref="DNS_Cloudflares"/>, <see cref="DNS_Dnspods"/>, <see cref="DNS_Googles"/></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<IPAddress> AnalysisDomainIpAsync(string hostNameOrAddress, string? dnsServers, CancellationToken cancellationToken = default)
|
||||
=> AnalysisDomainIpAsync(hostNameOrAddress, dnsServers, default, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 解析域名 IP 地址
|
||||
/// </summary>
|
||||
/// <param name="hostNameOrAddress">要解析的主机名或 IP 地址</param>
|
||||
/// <param name="dnsServers">自定义 DNS 服务器,可选的值有 <see cref="DNS_Alis"/>, <see cref="DNS_114s"/>, <see cref="DNS_Cloudflares"/>, <see cref="DNS_Dnspods"/>, <see cref="DNS_Googles"/></param>
|
||||
/// <param name="isIPv6"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<IPAddress> AnalysisDomainIpAsync(string hostNameOrAddress, string? dnsServers, bool isIPv6, CancellationToken cancellationToken = default);
|
||||
|
||||
Task<bool> GetIsIpv6Support() => Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user