Compare commits

..

No commits in common. "6de5a5215d99659ab8bf4bf623f4ff9eb7fb3f65" and "091b79f7cf2d15d8baac881761cf67af4587caa2" have entirely different histories.

17 changed files with 374 additions and 237 deletions

View file

@ -3,7 +3,7 @@ using System.IO.Compression;
namespace ServiceLib.Common; namespace ServiceLib.Common;
public static class FileUtils public static class FileManager
{ {
private static readonly string _tag = "FileManager"; private static readonly string _tag = "FileManager";

View file

@ -1,4 +1,4 @@
namespace ServiceLib.Models; namespace ServiceLib.Common;
public class SemanticVersion public class SemanticVersion
{ {

View file

@ -0,0 +1,177 @@
namespace ServiceLib.Common;
/*
* See:
* http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net
*/
public sealed class WindowsJob : IDisposable
{
private IntPtr handle = IntPtr.Zero;
public WindowsJob()
{
handle = CreateJobObject(IntPtr.Zero, null);
var extendedInfoPtr = IntPtr.Zero;
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
{
LimitFlags = 0x2000
};
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
BasicLimitInformation = info
};
try
{
var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
(uint)length))
{
throw new Exception(string.Format("Unable to set information. Error: {0}",
Marshal.GetLastWin32Error()));
}
}
finally
{
if (extendedInfoPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(extendedInfoPtr);
}
}
}
public bool AddProcess(IntPtr processHandle)
{
var succ = AssignProcessToJobObject(handle, processHandle);
if (!succ)
{
Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
}
return succ;
}
public bool AddProcess(int processId)
{
return AddProcess(Process.GetProcessById(processId).Handle);
}
#region IDisposable
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposed)
{
return;
}
disposed = true;
if (disposing)
{
// no managed objects to free
}
if (handle != IntPtr.Zero)
{
CloseHandle(handle);
handle = IntPtr.Zero;
}
}
~WindowsJob()
{
Dispose(false);
}
#endregion IDisposable
#region Interop
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(IntPtr a, string? lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
#endregion Interop
}
#region Helper classes
[StructLayout(LayoutKind.Sequential)]
internal struct IO_COUNTERS
{
public ulong ReadOperationCount;
public ulong WriteOperationCount;
public ulong OtherOperationCount;
public ulong ReadTransferCount;
public ulong WriteTransferCount;
public ulong OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public long PerProcessUserTimeLimit;
public long PerJobUserTimeLimit;
public uint LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public uint ActiveProcessLimit;
public UIntPtr Affinity;
public uint PriorityClass;
public uint SchedulingClass;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public uint nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UIntPtr ProcessMemoryLimit;
public UIntPtr JobMemoryLimit;
public UIntPtr PeakProcessMemoryUsed;
public UIntPtr PeakJobMemoryUsed;
}
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
}
#endregion Helper classes

View file

@ -6,7 +6,7 @@ public static class ConnectionHandler
public static async Task<string> RunAvailabilityCheck() public static async Task<string> RunAvailabilityCheck()
{ {
var time = await GetRealPingTimeInfo(); var time = await GetRealPingTime();
var ip = time > 0 ? await GetIPInfo() ?? Global.None : Global.None; var ip = time > 0 ? await GetIPInfo() ?? Global.None : Global.None;
return string.Format(ResUI.TestMeOutput, time, ip); return string.Format(ResUI.TestMeOutput, time, ip);
@ -39,7 +39,7 @@ public static class ConnectionHandler
return $"({country ?? "unknown"}) {ip}"; return $"({country ?? "unknown"}) {ip}";
} }
private static async Task<int> GetRealPingTimeInfo() private static async Task<int> GetRealPingTime()
{ {
var responseTime = -1; var responseTime = -1;
try try
@ -50,7 +50,7 @@ public static class ConnectionHandler
for (var i = 0; i < 2; i++) for (var i = 0; i < 2; i++)
{ {
responseTime = await GetRealPingTime(url, webProxy, 10); responseTime = await HttpClientHelper.Instance.GetRealPingTime(url, webProxy, 10);
if (responseTime > 0) if (responseTime > 0)
{ {
break; break;
@ -65,34 +65,4 @@ public static class ConnectionHandler
} }
return responseTime; return responseTime;
} }
public static async Task<int> GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout)
{
var responseTime = -1;
try
{
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(downloadTimeout));
using var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = webProxy,
UseProxy = webProxy != null
});
List<int> oneTime = new();
for (var i = 0; i < 2; i++)
{
var timer = Stopwatch.StartNew();
await client.GetAsync(url, cts.Token).ConfigureAwait(false);
timer.Stop();
oneTime.Add((int)timer.Elapsed.TotalMilliseconds);
await Task.Delay(100);
}
responseTime = oneTime.Where(x => x > 0).OrderBy(x => x).FirstOrDefault();
}
catch
{
}
return responseTime;
}
} }

View file

@ -18,7 +18,7 @@ public static class ProxySettingLinux
private static async Task ExecCmd(List<string> args) private static async Task ExecCmd(List<string> args)
{ {
var fileName = await FileUtils.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false); var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false);
await Utils.GetCliWrapOutput(fileName, args); await Utils.GetCliWrapOutput(fileName, args);
} }

View file

@ -23,7 +23,7 @@ public static class ProxySettingOSX
private static async Task ExecCmd(List<string> args) private static async Task ExecCmd(List<string> args)
{ {
var fileName = await FileUtils.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false); var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false);
await Utils.GetCliWrapOutput(fileName, args); await Utils.GetCliWrapOutput(fileName, args);
} }

View file

@ -48,7 +48,15 @@ public class HttpClientHelper
} }
return await httpClient.GetStringAsync(url); return await httpClient.GetStringAsync(url);
} }
public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token = default)
{
if (url.IsNullOrEmpty())
{
return null;
}
return await client.GetStringAsync(url, token);
}
public async Task PutAsync(string url, Dictionary<string, string> headers) public async Task PutAsync(string url, Dictionary<string, string> headers)
{ {
@ -73,5 +81,155 @@ public class HttpClientHelper
await httpClient.DeleteAsync(url); await httpClient.DeleteAsync(url);
} }
public static async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress<double>? progress, CancellationToken token = default)
{
ArgumentNullException.ThrowIfNull(url);
ArgumentNullException.ThrowIfNull(fileName);
if (File.Exists(fileName))
{
File.Delete(fileName);
}
using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.StatusCode.ToString());
}
var total = response.Content.Headers.ContentLength ?? -1L;
var canReportProgress = total != -1 && progress != null;
await using var stream = await response.Content.ReadAsStreamAsync(token);
await using var file = File.Create(fileName);
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var progressPercentage = 0;
while (true)
{
token.ThrowIfCancellationRequested();
var read = await stream.ReadAsync(buffer, token);
totalRead += read;
if (read == 0)
{
break;
}
await file.WriteAsync(buffer.AsMemory(0, read), token);
if (canReportProgress)
{
var percent = (int)(100.0 * totalRead / total);
//if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress?.Report(percent);
}
}
}
if (canReportProgress)
{
progress?.Report(101);
}
}
public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress<string> progress, CancellationToken token = default)
{
if (url.IsNullOrEmpty())
{
throw new ArgumentNullException(nameof(url));
}
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.StatusCode.ToString());
}
//var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
//var canReportProgress = total != -1 && progress != null;
await using var stream = await response.Content.ReadAsStreamAsync(token);
var totalRead = 0L;
var buffer = new byte[1024 * 64];
var isMoreToRead = true;
var progressSpeed = string.Empty;
var totalDatetime = DateTime.Now;
var totalSecond = 0;
do
{
if (token.IsCancellationRequested)
{
if (totalRead > 0)
{
return;
}
else
{
token.ThrowIfCancellationRequested();
}
}
var read = await stream.ReadAsync(buffer, token);
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
totalRead += read;
var ts = DateTime.Now - totalDatetime;
if (progress != null && ts.Seconds > totalSecond)
{
totalSecond = ts.Seconds;
var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
if (progressSpeed != speed)
{
progressSpeed = speed;
progress.Report(speed);
}
}
}
} while (isMoreToRead);
}
public async Task<int> GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout)
{
var responseTime = -1;
try
{
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(downloadTimeout));
using var client = new HttpClient(new SocketsHttpHandler()
{
Proxy = webProxy,
UseProxy = webProxy != null
});
List<int> oneTime = new();
for (var i = 0; i < 2; i++)
{
var timer = Stopwatch.StartNew();
await client.GetAsync(url, cts.Token).ConfigureAwait(false);
timer.Stop();
oneTime.Add((int)timer.Elapsed.TotalMilliseconds);
await Task.Delay(100);
}
responseTime = oneTime.Where(x => x > 0).OrderBy(x => x).FirstOrDefault();
}
catch //(Exception ex)
{
//Utile.SaveLog(ex.Message, ex);
}
return responseTime;
}
} }

View file

@ -35,7 +35,7 @@ public class CoreAdminManager
sb.AppendLine("#!/bin/bash"); sb.AppendLine("#!/bin/bash");
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}"; var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
sb.AppendLine($"exec sudo -S -- {cmdLine}"); sb.AppendLine($"exec sudo -S -- {cmdLine}");
var shFilePath = await FileUtils.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true); var shFilePath = await FileManager.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true);
var procService = new ProcessService( var procService = new ProcessService(
fileName: shFilePath, fileName: shFilePath,
@ -68,7 +68,7 @@ public class CoreAdminManager
try try
{ {
var shellFileName = Utils.IsOSX() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName; var shellFileName = Utils.IsOSX() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName;
var shFilePath = await FileUtils.CreateLinuxShellFile("kill_as_sudo.sh", EmbedUtils.GetEmbedText(shellFileName), true); var shFilePath = await FileManager.CreateLinuxShellFile("kill_as_sudo.sh", EmbedUtils.GetEmbedText(shellFileName), true);
if (shFilePath.Contains(' ')) if (shFilePath.Contains(' '))
{ {
shFilePath = shFilePath.AppendQuotes(); shFilePath = shFilePath.AppendQuotes();

View file

@ -8,7 +8,7 @@ public class CoreManager
private static readonly Lazy<CoreManager> _instance = new(() => new()); private static readonly Lazy<CoreManager> _instance = new(() => new());
public static CoreManager Instance => _instance.Value; public static CoreManager Instance => _instance.Value;
private Config _config; private Config _config;
private WindowsJobService? _processJob; private WindowsJob? _processJob;
private ProcessService? _processService; private ProcessService? _processService;
private ProcessService? _processPreService; private ProcessService? _processPreService;
private bool _linuxSudo = false; private bool _linuxSudo = false;
@ -27,7 +27,7 @@ public class CoreManager
var toPath = Utils.GetBinPath(""); var toPath = Utils.GetBinPath("");
if (fromPath != toPath) if (fromPath != toPath)
{ {
FileUtils.CopyDirectory(fromPath, toPath, true, false); FileManager.CopyDirectory(fromPath, toPath, true, false);
} }
} }

View file

@ -56,9 +56,9 @@ public class TaskManager
{ {
//Logging.SaveLog("Execute delete expired files"); //Logging.SaveLog("Execute delete expired files");
FileUtils.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1)); FileManager.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1));
FileUtils.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1)); FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
FileUtils.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1)); FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
try try
{ {

View file

@ -268,13 +268,10 @@ public partial class CoreConfigSingboxService
.Select(s => s + "\n-----END CERTIFICATE-----") .Select(s => s + "\n-----END CERTIFICATE-----")
.Select(s => s.Replace("\r\n", "\n")) .Select(s => s.Replace("\r\n", "\n"))
.ToList() ?? new(); .ToList() ?? new();
if (certs.Count > 0) tls.certificate = certs.Count > 0 ? certs : null;
{ tls.insecure = false;
tls.certificate = certs;
tls.insecure = false;
}
} }
else if (node.StreamSecurity == Global.StreamSecurityReality) else
{ {
tls.reality = new Reality4Sbox() tls.reality = new Reality4Sbox()
{ {

View file

@ -71,7 +71,7 @@ public class DownloadService
AllowAutoRedirect = false, AllowAutoRedirect = false,
Proxy = await GetWebProxy(blProxy) Proxy = await GetWebProxy(blProxy)
}; };
var client = new HttpClient(webRequestHandler); HttpClient client = new(webRequestHandler);
var response = await client.GetAsync(url); var response = await client.GetAsync(url);
if (response.StatusCode == HttpStatusCode.Redirect && response.Headers.Location is not null) if (response.StatusCode == HttpStatusCode.Redirect && response.Headers.Location is not null)
@ -156,7 +156,7 @@ public class DownloadService
} }
using var cts = new CancellationTokenSource(); using var cts = new CancellationTokenSource();
var result = await client.GetStringAsync(url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); var result = await HttpClientHelper.Instance.GetAsync(client, url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
return result; return result;
} }
catch (Exception ex) catch (Exception ex)

View file

@ -272,7 +272,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
private async Task<int> DoRealPing(ServerTestItem it) private async Task<int> DoRealPing(ServerTestItem it)
{ {
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}"); var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
var responseTime = await ConnectionHandler.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10); var responseTime = await HttpClientHelper.Instance.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime); ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
await UpdateFunc(it.IndexId, responseTime.ToString()); await UpdateFunc(it.IndexId, responseTime.ToString());

View file

@ -1,12 +1,18 @@
namespace ServiceLib.Services; namespace ServiceLib.Services;
public class UpdateService(Config config, Func<bool, string, Task> updateFunc) public class UpdateService
{ {
private readonly Config? _config = config; private readonly Config? _config;
private readonly Func<bool, string, Task>? _updateFunc = updateFunc; private readonly Func<bool, string, Task>? _updateFunc;
private readonly int _timeout = 30; private readonly int _timeout = 30;
private static readonly string _tag = "UpdateService"; private static readonly string _tag = "UpdateService";
public UpdateService(Config config, Func<bool, string, Task> updateFunc)
{
_config = config;
_updateFunc = updateFunc;
}
public async Task CheckUpdateGuiN(bool preRelease) public async Task CheckUpdateGuiN(bool preRelease)
{ {
var url = string.Empty; var url = string.Empty;

View file

@ -1,171 +0,0 @@
namespace ServiceLib.Services;
/// <summary>
/// http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net
/// </summary>
public sealed class WindowsJobService : IDisposable
{
private nint handle = nint.Zero;
public WindowsJobService()
{
handle = CreateJobObject(nint.Zero, null);
var extendedInfoPtr = nint.Zero;
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
{
LimitFlags = 0x2000
};
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
BasicLimitInformation = info
};
try
{
var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
(uint)length))
{
throw new Exception(string.Format("Unable to set information. Error: {0}",
Marshal.GetLastWin32Error()));
}
}
finally
{
if (extendedInfoPtr != nint.Zero)
{
Marshal.FreeHGlobal(extendedInfoPtr);
}
}
}
public bool AddProcess(nint processHandle)
{
var succ = AssignProcessToJobObject(handle, processHandle);
if (!succ)
{
Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
}
return succ;
}
public bool AddProcess(int processId)
{
return AddProcess(Process.GetProcessById(processId).Handle);
}
#region IDisposable
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposed)
{
return;
}
disposed = true;
if (disposing)
{
// no managed objects to free
}
if (handle != nint.Zero)
{
CloseHandle(handle);
handle = nint.Zero;
}
}
~WindowsJobService()
{
Dispose(false);
}
#endregion IDisposable
#region Interop
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern nint CreateJobObject(nint a, string? lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetInformationJobObject(nint hJob, JobObjectInfoType infoType, nint lpJobObjectInfo, uint cbJobObjectInfoLength);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AssignProcessToJobObject(nint job, nint process);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(nint hObject);
#endregion Interop
}
[StructLayout(LayoutKind.Sequential)]
internal struct IO_COUNTERS
{
public ulong ReadOperationCount;
public ulong WriteOperationCount;
public ulong OtherOperationCount;
public ulong ReadTransferCount;
public ulong WriteTransferCount;
public ulong OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public long PerProcessUserTimeLimit;
public long PerJobUserTimeLimit;
public uint LimitFlags;
public nuint MinimumWorkingSetSize;
public nuint MaximumWorkingSetSize;
public uint ActiveProcessLimit;
public nuint Affinity;
public uint PriorityClass;
public uint SchedulingClass;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public uint nLength;
public nint lpSecurityDescriptor;
public int bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public nuint ProcessMemoryLimit;
public nuint JobMemoryLimit;
public nuint PeakProcessMemoryUsed;
public nuint PeakJobMemoryUsed;
}
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
}

View file

@ -119,7 +119,7 @@ public class BackupAndRestoreViewModel : MyReactiveObject
return; return;
} }
//check //check
var lstFiles = FileUtils.GetFilesFromZip(fileName); var lstFiles = FileManager.GetFilesFromZip(fileName);
if (lstFiles is null || !lstFiles.Any(t => t.Contains(_guiConfigs))) if (lstFiles is null || !lstFiles.Any(t => t.Contains(_guiConfigs)))
{ {
DisplayOperationMsg(ResUI.LocalRestoreInvalidZipTips); DisplayOperationMsg(ResUI.LocalRestoreInvalidZipTips);
@ -135,7 +135,7 @@ public class BackupAndRestoreViewModel : MyReactiveObject
await SQLiteHelper.Instance.DisposeDbConnectionAsync(); await SQLiteHelper.Instance.DisposeDbConnectionAsync();
var toPath = Utils.GetConfigPath(); var toPath = Utils.GetConfigPath();
FileUtils.ZipExtractToFile(fileName, toPath, ""); FileManager.ZipExtractToFile(fileName, toPath, "");
if (Utils.IsWindows()) if (Utils.IsWindows())
{ {
@ -167,8 +167,8 @@ public class BackupAndRestoreViewModel : MyReactiveObject
var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}"); var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}");
var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs); var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);
FileUtils.CopyDirectory(configDir, configDirTemp, false, true, ""); FileManager.CopyDirectory(configDir, configDirTemp, false, true, "");
var ret = FileUtils.CreateFromDirectory(configDirZipTemp, fileName); var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName);
Directory.Delete(configDirZipTemp, true); Directory.Delete(configDirZipTemp, true);
return await Task.FromResult(ret); return await Task.FromResult(ret);
} }

View file

@ -271,24 +271,24 @@ public class CheckUpdateViewModel : MyReactiveObject
if (fileName.Contains(".tar.gz")) if (fileName.Contains(".tar.gz"))
{ {
FileUtils.DecompressTarFile(fileName, toPath); FileManager.DecompressTarFile(fileName, toPath);
var dir = new DirectoryInfo(toPath); var dir = new DirectoryInfo(toPath);
if (dir.Exists) if (dir.Exists)
{ {
foreach (var subDir in dir.GetDirectories()) foreach (var subDir in dir.GetDirectories())
{ {
FileUtils.CopyDirectory(subDir.FullName, toPath, false, true); FileManager.CopyDirectory(subDir.FullName, toPath, false, true);
subDir.Delete(true); subDir.Delete(true);
} }
} }
} }
else if (fileName.Contains(".gz")) else if (fileName.Contains(".gz"))
{ {
FileUtils.DecompressFile(fileName, toPath, item.CoreType); FileManager.DecompressFile(fileName, toPath, item.CoreType);
} }
else else
{ {
FileUtils.ZipExtractToFile(fileName, toPath, "geo"); FileManager.ZipExtractToFile(fileName, toPath, "geo");
} }
if (Utils.IsNonWindows()) if (Utils.IsNonWindows())