Skip to content

Commit

Permalink
fix: 修复系统代理失败的问题&&升级程序崩溃的问题&&恢复上次退出时的位置
Browse files Browse the repository at this point in the history
  • Loading branch information
ZGGSONG committed Jan 11, 2024
1 parent 741a1dc commit 52ef164
Show file tree
Hide file tree
Showing 20 changed files with 2,411 additions and 52 deletions.
11 changes: 11 additions & 0 deletions STranslate.Model/ConfigModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,21 @@ public partial class ConfigModel : ObservableObject
/// </summary>
public DoubleTapFuncEnum DoubleTapTrayFunc { get; set; } = DoubleTapFuncEnum.InputFunc;

/// <summary>
/// 原始语言
/// </summary>
public string SourceLanguage { get; set; } = string.Empty;

/// <summary>
/// 目标语言
/// </summary>
public string TargetLanguage { get; set; } = string.Empty;

/// <summary>
/// 退出时的位置
/// </summary>
public string Position { get; set; } = string.Empty;

/// <summary>
/// 服务
/// </summary>
Expand Down
4 changes: 3 additions & 1 deletion STranslate.Updater/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
Title="STranslate 升级程序"
Width="420"
Height="300"
d:DataContext="{d:DesignInstance Type=local:MainViewModel}"
Icon="favicon.ico"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
Expand Down
61 changes: 17 additions & 44 deletions STranslate.Util/HttpUtil.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Linq;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -15,7 +14,7 @@ public class HttpUtil
/// 异步Get请求(不带Token)
/// </summary>
/// <param name="url"></param>
/// <param name="req"></param>
/// <param name="timeout"></param>
/// <returns></returns>
public static async Task<string> GetAsync(string url, int timeout = 10) => await GetAsync(url, CancellationToken.None, timeout);

Expand All @@ -27,10 +26,7 @@ public class HttpUtil
/// <returns></returns>
public static async Task<string> GetAsync(string url, CancellationToken token, int timeout = 10)
{
using var client = new HttpClient()
{
Timeout = TimeSpan.FromSeconds(timeout),
};
using var client = new HttpClient(new SocketsHttpHandler()) { Timeout = TimeSpan.FromSeconds(timeout) };

try
{
Expand All @@ -54,29 +50,24 @@ public static async Task<string> GetAsync(string url, CancellationToken token, i
/// <param name="token">取消令牌</param>
/// <param name="timeout">超时时间(秒)</param>
/// <returns></returns>
public static async Task<string> GetAsync(string url, Dictionary<string, string> queryParams, CancellationToken token, int timeout = 10)
public static async Task<string> GetAsync(
string url,
Dictionary<string, string> queryParams,
CancellationToken token,
int timeout = 10
)
{
using var client = new HttpClient()
{
Timeout = TimeSpan.FromSeconds(timeout),
};
using var client = new HttpClient(new SocketsHttpHandler()) { Timeout = TimeSpan.FromSeconds(timeout), };

try
{
// 构建带查询参数的URL
if (queryParams != null && queryParams.Count > 0)
{
var queryBuilder = new StringBuilder();
foreach (var kvp in queryParams)
{
queryBuilder.Append(Uri.EscapeDataString(kvp.Key));
queryBuilder.Append("=");
queryBuilder.Append(Uri.EscapeDataString(kvp.Value));
queryBuilder.Append("&");
}

string queryString = queryBuilder.ToString().TrimEnd('&');
url += "?" + queryString;
var uriBuilder = new UriBuilder(url);
var query = queryParams.Select(kvp => $"{Uri.EscapeDataString(kvp.Key)}={Uri.EscapeDataString(kvp.Value)}");
uriBuilder.Query = string.Join("&", query);
url = uriBuilder.ToString();
}

var respContent = await client.GetAsync(url, token);
Expand All @@ -91,14 +82,14 @@ public static async Task<string> GetAsync(string url, Dictionary<string, string>
}
}


/// <summary>
/// 异步Post请求(不带Token)
/// </summary>
/// <param name="url"></param>
/// <param name="req"></param>
/// <returns></returns>
public static async Task<string> PostAsync(string url, string req, int timeout = 10) => await PostAsync(url, req, CancellationToken.None, timeout);
public static async Task<string> PostAsync(string url, string req, int timeout = 10) =>
await PostAsync(url, req, CancellationToken.None, timeout);

/// <summary>
/// 异步Post请求
Expand All @@ -109,10 +100,7 @@ public static async Task<string> GetAsync(string url, Dictionary<string, string>
/// <returns></returns>
public static async Task<string> PostAsync(string url, string req, CancellationToken token, int timeout = 10)
{
using var client = new HttpClient()
{
Timeout = TimeSpan.FromSeconds(timeout),
};
using var client = new HttpClient(new SocketsHttpHandler()) { Timeout = TimeSpan.FromSeconds(timeout), };

try
{
Expand All @@ -129,20 +117,5 @@ public static async Task<string> PostAsync(string url, string req, CancellationT
throw;
}
}

/// <summary>
/// 支持系统代理
/// </summary>
public static void SupportSystemAgent()
{
WebRequest.DefaultWebProxy = WebRequest.GetSystemWebProxy();
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
}
//TODO: 如果一开始没有开系统代理,软件开启后再打开系统代理仍然会代理不上
//LogService.Logger.Info("START");
//var ret = await HttpUtil.GetAsync("https://rsshub.zggsong.workers.dev/", timeout: 10);
//LogService.Logger.Info(ret);
//LogService.Logger.Info("END");
//return;
}
}
153 changes: 153 additions & 0 deletions STranslate.Util/Proxy/DynamicHttpWindowsProxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
using System;
using System.Net;
using System.Runtime.Versioning;
using System.Threading.Tasks;

namespace STranslate.Util.Proxy;

/// <summary>
/// 自动跟随系统代理的代理
/// </summary>
[SupportedOSPlatform("windows")]
public class DynamicHttpWindowsProxy : IWebProxy, IDisposable
{
/// <summary>
/// 创建自动跟随系统代理的代理
/// </summary>
public DynamicHttpWindowsProxy()
{
if (HttpWindowsProxy.TryCreate(out var proxy))
{
_innerProxy = proxy;
}
else
{
_innerProxy = new HttpNoProxy();
}
}

/// <summary>
/// 开始根据注册表变更动态修改代理,需要开启一个线程监听注册表
/// </summary>
public void Start()
{
_registryMonitor = new RegistryMonitor(
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
);
_registryMonitor.RegChanged += RegistryMonitor_RegChanged;
_registryMonitor.Start();

// 启动完成之后,更新一次吧
UpdateProxy();
}

private void RegistryMonitor_RegChanged(object? sender, EventArgs e)
{
UpdateProxy();
}

private void UpdateProxy()
{
if (HttpWindowsProxy.TryCreate(out var proxy))
{
InnerProxy = proxy;
}
else
{
InnerProxy = new HttpNoProxy();
}
}

private RegistryMonitor? _registryMonitor;

private IWebProxy InnerProxy
{
set
{
if (ReferenceEquals(_innerProxy, value))
{
return;
}

if (_innerProxy is IDisposable disposable)
{
disposable.Dispose();
}

_innerProxy = value;
}
get => _innerProxy;
}

/// <inheritdoc />
public ICredentials? Credentials
{
get => InnerProxy.Credentials;
set => InnerProxy.Credentials = value;
}

/// <summary>
/// 超过多少次超时之后,就再也不拿代理了
/// </summary>
public int MaxTimeoutCount { set; get; } = 5;

/// <summary>
/// 获取代理的超时时间,默认 15 秒
/// </summary>
public TimeSpan TimeoutForGetProxy { set; get; } = TimeSpan.FromSeconds(15);

/// <inheritdoc />
public Uri? GetProxy(Uri destination)
{
if (InnerProxy is HttpNoProxy)
{
// 如果是啥都没的代理,那返回即可
return InnerProxy.GetProxy(destination);
}
else
{
if (_timeoutCount > MaxTimeoutCount)
{
// 超过 5 次都超时,那就别拿代理了
return null;
}

var task = Task.Run(() => InnerProxy.GetProxy(destination));
var delayTask = Task.Delay(TimeoutForGetProxy);

Task.WaitAny(task, delayTask);

if (task.IsCompleted)
{
return task.Result;
}
else
{
// 超时
_timeoutCount++;
return null;
}
}
}

private int _timeoutCount;

/// <inheritdoc />
public bool IsBypassed(Uri host)
{
return InnerProxy.IsBypassed(host);
}

/// <inheritdoc />
public void Dispose()
{
if (_innerProxy is IDisposable disposable)
{
disposable.Dispose();
}

_registryMonitor?.Dispose();
}

private IWebProxy _innerProxy;
}
Loading

0 comments on commit 52ef164

Please sign in to comment.