提交 2d0646c2 编写于 作者: A Aigio Liu

🐛 hosts update in admin proc

上级 8d24cc0d
......@@ -81,7 +81,7 @@ public sealed class Plugin : PluginBase<Plugin>, IPlugin
{
var subProcessPath = SubProcessPath;
var p = await ipc.StartSubProcessAsync(subProcessPath.ThrowIsNull(),
isAdministrator: true);
isAdministrator: false);
return p;
});
}
......
......@@ -14,7 +14,7 @@ public sealed partial class ProxyService
readonly IReverseProxyService reverseProxyService = IReverseProxyService.Constants.Instance;
readonly IScriptManager scriptManager = IScriptManager.Instance;
readonly IHostsFileService hostsFileService = IHostsFileService.Instance;
readonly IHostsFileService hostsFileService = IHostsFileService.Constants.Instance;
readonly IPlatformService platformService = IPlatformService.Instance;
ProxyService()
......
......@@ -35,7 +35,7 @@ public sealed partial class AcceleratorPageViewModel
if (IApplication.IsDesktop())
{
hostsFileService = IHostsFileService.Instance;
hostsFileService = IHostsFileService.Constants.Instance;
SetupCertificateCommand = ReactiveCommand.Create(SetupCertificate_OnClick);
DeleteCertificateCommand = ReactiveCommand.Create(DeleteCertificate_OnClick);
EditHostsFileCommand = ReactiveCommand.Create(hostsFileService.OpenFile);
......
namespace BD.WTTS.Models;
/// <inheritdoc cref="OperationResultBase{T}"/>
public class OperationResult : OperationResultBase<object>
public sealed class OperationResult : OperationResultBase<object>
{
/// <inheritdoc cref="OperationResultBase{T}.OperationResultBase(OperationResultType)"/>
public OperationResult()
......@@ -33,7 +33,17 @@ public class OperationResult : OperationResultBase<object>
{
}
public override object AppendData
public OperationResult(IOperationResult result)
{
ResultType = result.ResultType;
Message = result.Message;
LogMessage = result.LogMessage;
}
[MPIgnore, MP2Ignore]
[N_JsonIgnore]
[S_JsonIgnore]
public sealed override object AppendData
{
get => null!;
set { }
......@@ -41,7 +51,7 @@ public class OperationResult : OperationResultBase<object>
}
/// <inheritdoc cref="OperationResultBase{T}"/>
public class OperationResult<T> : OperationResultBase<T>
public sealed class OperationResult<T> : OperationResultBase<T>
{
/// <inheritdoc cref="OperationResultBase{T}.OperationResultBase(OperationResultType)"/>
public OperationResult()
......@@ -72,4 +82,23 @@ public class OperationResult<T> : OperationResultBase<T>
public OperationResult(OperationResultType resultType, string message, string logMessage, T appendData) : base(resultType, message, logMessage, appendData)
{
}
public OperationResult(IOperationResult result)
{
ResultType = result.ResultType;
Message = result.Message;
LogMessage = result.LogMessage;
if (result is IOperationResult<T> result2)
{
AppendData = result2.AppendData;
}
}
public OperationResult(IOperationResult<T> result)
{
ResultType = result.ResultType;
Message = result.Message;
LogMessage = result.LogMessage;
AppendData = result.AppendData;
}
}
\ No newline at end of file
......@@ -137,12 +137,14 @@ public sealed partial class IPCMainProcessServiceImpl : IPCMainProcessService
{
var pipeName = ipcProvider.ThrowIsNull().IpcContext.PipeName;
var pid = Environment.ProcessId;
const bool useShellExecute =
#if DEBUG
true; // 调试模式下此子进程与主进程不使用同一个控制台窗口
#else
false;
#endif
// const bool useShellExecute =
//#if DEBUG
// true; // 调试模式下此子进程与主进程不使用同一个控制台窗口
//#else
// false;
//#endif
// System.InvalidOperationException: The Process object must have the UseShellExecute property set to false in order to use environment variables.
const bool useShellExecute = false;
const bool createNoWindow =
#if DEBUG
false; // 调试模式下显示窗口
......
......@@ -15,10 +15,20 @@ internal sealed class HostsFileServiceImpl
readonly IPlatformService s;
readonly object lockObj = new();
readonly IHostsFileService? privilegedThis;
public HostsFileServiceImpl(IPlatformService s)
const string TAG = "HostsFileS";
public HostsFileServiceImpl(IServiceProvider serviceProvider, IPlatformService s)
{
this.s = s;
#if WINDOWS
if (Startup.Instance.IsMainProcess && !WindowsPlatformServiceImpl.IsPrivilegedProcess)
{
var ipc = serviceProvider.GetService<IPCSubProcessService>();
privilegedThis = ipc?.GetService<IHostsFileService>();
}
#endif
}
#region Mark
......@@ -488,24 +498,38 @@ internal sealed class HostsFileServiceImpl
public async void ResetFile()
{
var r = await MessageBox.ShowAsync(
AppResources.CommunityFix_ResetHostsFileTip,
AppResources.Warning,
button: MessageBox.Button.OKCancel,
rememberChooseKey: MessageBox.DontPromptType.ResetHostsFile);
if (r.IsOK())
if (Startup.Instance.IsMainProcess)
{
try
var r = await MessageBox.ShowAsync(
AppResources.CommunityFix_ResetHostsFileTip,
AppResources.Warning,
button: MessageBox.Button.OKCancel,
rememberChooseKey: MessageBox.DontPromptType.ResetHostsFile);
if (r.IsOK())
{
s.WriteDefaultHostsContent();
Toast.Show(AppResources.CommunityFix_ResetHostsFileOk);
}
catch (Exception e)
{
Log.Error(TAG, e, nameof(ResetFile));
Toast.Show(AppResources.CommunityFix_ResetHostsFileCatchTip_.Format(e.Message));
try
{
if (privilegedThis != null)
{
privilegedThis.ResetFile();
}
else
{
s.WriteDefaultHostsContent();
}
Toast.Show(ToastIcon.Success, AppResources.CommunityFix_ResetHostsFileOk);
}
catch (Exception e)
{
Log.Error(TAG, e, nameof(ResetFile));
Toast.Show(ToastIcon.Error, AppResources.CommunityFix_ResetHostsFileCatchTip_.Format(e.Message));
}
}
}
else
{
s.WriteDefaultHostsContent();
}
}
/// <summary>
......@@ -547,7 +571,7 @@ internal sealed class HostsFileServiceImpl
return dict;
}
public IOperationResult<List<(string ip, string domain)>> ReadHostsAllLines()
public OperationResult<List<(string ip, string domain)>> ReadHostsAllLines()
{
lock (lockObj)
{
......@@ -620,8 +644,12 @@ internal sealed class HostsFileServiceImpl
}
}
public IOperationResult UpdateHosts(string ip, string domain)
public OperationResult UpdateHosts(string ip, string domain)
{
if (privilegedThis != null)
{
return privilegedThis.UpdateHosts(ip, domain);
}
var dict = new Dictionary<string, string>
{
{ domain, ip },
......@@ -629,8 +657,12 @@ internal sealed class HostsFileServiceImpl
return UpdateHosts(dict);
}
public IOperationResult UpdateHosts(IEnumerable<(string ip, string domain)> hosts)
public OperationResult UpdateHosts(IEnumerable<(string ip, string domain)> hosts)
{
if (privilegedThis != null)
{
return privilegedThis.UpdateHosts(hosts);
}
//var value = hosts.ToDictionary(k => k.domain, v => v.ip);
var value = new Dictionary<string, string>();
foreach (var (ip, domain) in hosts)
......@@ -638,25 +670,48 @@ internal sealed class HostsFileServiceImpl
return UpdateHosts(value);
}
public IOperationResult UpdateHosts(IReadOnlyDictionary<string, string> hosts)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static OperationResult Convert(IOperationResult result)
{
return HandleHosts(isUpdateOrRemove: true, hosts);
if (result is OperationResult operationResult)
return operationResult;
return new OperationResult(result);
}
public IOperationResult RemoveHosts(string ip, string domain)
public OperationResult UpdateHosts(IReadOnlyDictionary<string, string> hosts)
{
if (privilegedThis != null)
{
return privilegedThis.UpdateHosts(hosts);
}
var result = HandleHosts(isUpdateOrRemove: true, hosts);
return Convert(result);
}
public OperationResult RemoveHosts(string ip, string domain)
{
if (privilegedThis != null)
{
return privilegedThis.RemoveHosts(ip, domain);
}
var hosts = new Dictionary<string, string>
{
{ domain, ip },
};
return HandleHosts(isUpdateOrRemove: false, hosts);
var result = HandleHosts(isUpdateOrRemove: false, hosts);
return Convert(result);
}
public IOperationResult RemoveHosts(string domain) => RemoveHosts(string.Empty, domain);
public OperationResult RemoveHosts(string domain) => RemoveHosts(string.Empty, domain);
public IOperationResult RemoveHostsByTag()
public OperationResult RemoveHostsByTag()
{
return HandleHosts(isUpdateOrRemove: false);
if (privilegedThis != null)
{
return privilegedThis.RemoveHostsByTag();
}
var result = HandleHosts(isUpdateOrRemove: false);
return Convert(result);
}
static IOperationResult<T> TryReadHosts<T>(Func<T> func, string methodName)
......@@ -692,14 +747,14 @@ internal sealed class HostsFileServiceImpl
}
else
{
Toast.Show(AppResources.OperationHostsError_.Format(result.Message));
Toast.Show(ToastIcon.Error, AppResources.OperationHostsError_.Format(result.Message));
}
}
}
catch (Exception ex)
{
Log.Error(TAG, ex, "ContainsHostsByTag fail.");
Toast.Show(AppResources.OperationHostsError_.Format(ex.GetAllMessage()));
Toast.Show(ToastIcon.Error, AppResources.OperationHostsError_.Format(ex.GetAllMessage()));
}
return false;
}
......@@ -722,6 +777,11 @@ internal sealed class HostsFileServiceImpl
public void OccupyHosts()
{
if (privilegedThis != null)
{
privilegedThis.OccupyHosts();
return;
}
mOccupyHostsFileStream = new FileStream(s.HostsFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
#endif
......
#if (WINDOWS || MACCATALYST || MACOS || LINUX) && !(IOS || ANDROID)
using dotnetCampus.Ipc.CompilerServices.Attributes;
// ReSharper disable once CheckNamespace
namespace BD.WTTS.Services;
......@@ -6,11 +7,13 @@ namespace BD.WTTS.Services;
/// <summary>
/// hosts 文件助手服务,修改需要管理员权限或 Root 权限
/// </summary>
[IpcPublic(Timeout = AssemblyInfo.IpcTimeout, IgnoresIpcException = false)]
public interface IHostsFileService
{
static IHostsFileService Instance => Ioc.Get<IHostsFileService>();
protected const string TAG = "HostsFileS";
static class Constants
{
public static IHostsFileService Instance => Ioc.Get<IHostsFileService>();
}
/// <summary>
/// 打开 hosts 文件
......@@ -31,7 +34,7 @@ public interface IHostsFileService
/// 读取 hosts 文件
/// </summary>
/// <returns></returns>
IOperationResult<List<(string ip, string domain)>> ReadHostsAllLines();
OperationResult<List<(string ip, string domain)>> ReadHostsAllLines();
/// <summary>
/// 更新一条 hosts 纪录
......@@ -39,17 +42,17 @@ public interface IHostsFileService
/// <param name="ip"></param>
/// <param name="domain"></param>
/// <returns></returns>
IOperationResult UpdateHosts(string ip, string domain);
OperationResult UpdateHosts(string ip, string domain);
/// <inheritdoc cref="UpdateHosts(IReadOnlyDictionary{string, string})"/>
IOperationResult UpdateHosts(IEnumerable<(string ip, string domain)> hosts);
OperationResult UpdateHosts(IEnumerable<(string ip, string domain)> hosts);
/// <summary>
/// 更新多条 hosts 纪录
/// </summary>
/// <param name="hosts"></param>
/// <returns></returns>
IOperationResult UpdateHosts(IReadOnlyDictionary<string, string> hosts);
OperationResult UpdateHosts(IReadOnlyDictionary<string, string> hosts);
/// <summary>
/// 移除一条 hosts 纪录
......@@ -57,16 +60,16 @@ public interface IHostsFileService
/// <param name="ip"></param>
/// <param name="domain"></param>
/// <returns></returns>
IOperationResult RemoveHosts(string ip, string domain);
OperationResult RemoveHosts(string ip, string domain);
/// <inheritdoc cref="RemoveHosts(string, string)"/>
IOperationResult RemoveHosts(string domain);
OperationResult RemoveHosts(string domain);
/// <summary>
/// 移除当前程序写入的 hosts 纪录并还原写入时冲突的备份纪录
/// </summary>
/// <returns></returns>
IOperationResult RemoveHostsByTag();
OperationResult RemoveHostsByTag();
/// <summary>
/// 当程序退出时还原 hosts 文件
......
......@@ -315,10 +315,12 @@ partial class Startup // 自定义控制台命令参数
{
// 添加平台服务(供主进程的 IPC 远程访问)
var platformService = IPlatformService.Instance;
IHostsFileService hostsFileService = IHostsFileService.Constants.Instance;
#if DEBUG
Console.WriteLine(platformService.GetDebugString());
#endif
ipcProvider.CreateIpcJoint<IPCPlatformService>(platformService);
ipcProvider.CreateIpcJoint(hostsFileService);
}, new[] { n, p.ToString() });
return exitCode;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册