-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: 修复系统代理失败的问题&&升级程序崩溃的问题&&恢复上次退出时的位置
- Loading branch information
Showing
20 changed files
with
2,411 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
Oops, something went wrong.