diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..8c983563 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.cs text diff --git a/Netch.sln b/Netch.sln index b8e525f2..d6701206 100644 --- a/Netch.sln +++ b/Netch.sln @@ -1,25 +1,25 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29009.5 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.ActiveCfg = Debug|x64 - {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64 - {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64 - {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {6EC9B043-ACA5-4BB9-96DB-493A2EF6E43F} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29009.5 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.ActiveCfg = Debug|x64 + {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64 + {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64 + {4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6EC9B043-ACA5-4BB9-96DB-493A2EF6E43F} + EndGlobalSection +EndGlobal diff --git a/Netch/.gitignore b/Netch/.gitignore index aeb4af3c..a8b0b13e 100644 --- a/Netch/.gitignore +++ b/Netch/.gitignore @@ -1,3 +1,3 @@ -/bin -/obj -/*.csproj.user +/bin +/obj +/*.csproj.user diff --git a/Netch/Controllers/TUNController.cs b/Netch/Controllers/TUNController.cs index 9f57ec5b..9d61ecb3 100644 --- a/Netch/Controllers/TUNController.cs +++ b/Netch/Controllers/TUNController.cs @@ -232,18 +232,18 @@ namespace Netch.Controllers if (!TryParseIPNetwork(ipNetwork, out var ip, out var cidr)) return false; - IAdapter adapter = routeType switch - { - RouteType.Outbound => _outboundAdapter, - RouteType.TUNTAP => _tunAdapter, - _ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null) + IAdapter adapter = routeType switch + { + RouteType.Outbound => _outboundAdapter, + RouteType.TUNTAP => _tunAdapter, + _ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null) }; - List ipList = routeType switch - { - RouteType.Outbound => _directIPs, - RouteType.TUNTAP => _proxyIPs, - _ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null) + List ipList = routeType switch + { + RouteType.Outbound => _directIPs, + RouteType.TUNTAP => _proxyIPs, + _ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null) }; string gateway = adapter.Gateway.ToString(); diff --git a/Netch/Forms/MainForm.cs b/Netch/Forms/MainForm.cs index 4268aebf..e2f4ceb5 100644 --- a/Netch/Forms/MainForm.cs +++ b/Netch/Forms/MainForm.cs @@ -1106,13 +1106,13 @@ namespace Netch.Forms if (natType > 0 && natType < 5) { NatTypeStatusLightLabel.Visible = Flags.IsWindows10Upper; - var c = natType switch - { - 1 => Color.LimeGreen, - 2 => Color.Yellow, - 3 => Color.Red, - 4 => Color.Black, - _ => throw new ArgumentOutOfRangeException(nameof(natType), natType, null) + var c = natType switch + { + 1 => Color.LimeGreen, + 2 => Color.Yellow, + 3 => Color.Red, + 4 => Color.Black, + _ => throw new ArgumentOutOfRangeException(nameof(natType), natType, null) }; NatTypeStatusLightLabel.ForeColor = c; @@ -1400,38 +1400,38 @@ namespace Netch.Forms switch (cbx.Items[e.Index]) { - case Server item: - { - // 计算延迟底色 - var numBoxBackBrush = item.Delay switch { > 200 => Brushes.Red, > 80 => Brushes.Yellow, >= 0 => _greenBrush, _ => Brushes.Gray }; - - // 绘制延迟底色 - e.Graphics.FillRectangle(numBoxBackBrush, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height); - - // 绘制延迟字符串 - TextRenderer.DrawText(e.Graphics, - item.Delay.ToString(), - cbx.Font, - new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y), - Color.Black, - TextFormatFlags.Left); - - break; + case Server item: + { + // 计算延迟底色 + var numBoxBackBrush = item.Delay switch { > 200 => Brushes.Red, > 80 => Brushes.Yellow, >= 0 => _greenBrush, _ => Brushes.Gray }; + + // 绘制延迟底色 + e.Graphics.FillRectangle(numBoxBackBrush, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height); + + // 绘制延迟字符串 + TextRenderer.DrawText(e.Graphics, + item.Delay.ToString(), + cbx.Font, + new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y), + Color.Black, + TextFormatFlags.Left); + + break; } - case Models.Mode item: - { - // 绘制 模式Box 底色 - e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height); - - // 绘制 模式行数 字符串 - TextRenderer.DrawText(e.Graphics, - item.Rule.Count.ToString(), - cbx.Font, - new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y), - Color.Black, - TextFormatFlags.Left); - - break; + case Models.Mode item: + { + // 绘制 模式Box 底色 + e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height); + + // 绘制 模式行数 字符串 + TextRenderer.DrawText(e.Graphics, + item.Rule.Count.ToString(), + cbx.Font, + new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y), + Color.Black, + TextFormatFlags.Left); + + break; } } } diff --git a/Netch/Forms/MessageBoxX.cs b/Netch/Forms/MessageBoxX.cs index c9fa8ebf..cc865d64 100644 --- a/Netch/Forms/MessageBoxX.cs +++ b/Netch/Forms/MessageBoxX.cs @@ -22,20 +22,20 @@ namespace Netch.Forms { MessageBoxIcon msgIcon; if (string.IsNullOrWhiteSpace(title)) - title = level switch - { - LogLevel.INFO => "Information", - LogLevel.WARNING => "Warning", - LogLevel.ERROR => "Error", - _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) + title = level switch + { + LogLevel.INFO => "Information", + LogLevel.WARNING => "Warning", + LogLevel.ERROR => "Error", + _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) }; - msgIcon = level switch - { - LogLevel.INFO => MessageBoxIcon.Information, - LogLevel.WARNING => MessageBoxIcon.Warning, - LogLevel.ERROR => MessageBoxIcon.Exclamation, - _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) + msgIcon = level switch + { + LogLevel.INFO => MessageBoxIcon.Information, + LogLevel.WARNING => MessageBoxIcon.Warning, + LogLevel.ERROR => MessageBoxIcon.Exclamation, + _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) }; return MessageBox.Show(owner, text, i18N.Translate(title), confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK, msgIcon); diff --git a/Netch/NativeMethods.cs b/Netch/NativeMethods.cs index abdf9435..94133e17 100644 --- a/Netch/NativeMethods.cs +++ b/Netch/NativeMethods.cs @@ -1,4 +1,4 @@ -using System.Net.Sockets; +using System.Net.Sockets; using System.Runtime.InteropServices; namespace Netch @@ -8,22 +8,22 @@ namespace Netch [DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")] public static extern uint RefreshDNSCache(); - [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] - public static extern ulong ConvertLuidToIndex(ulong id); - - [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] - public static extern bool CreateIPv4(string address, string netmask, ulong index); - - [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] - public static extern bool CreateUnicastIP(AddressFamily inet, string address, byte cidr, ulong index); - - [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] - public static extern bool RefreshIPTable(AddressFamily inet, ulong index); - - [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] - public static extern bool CreateRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric); - - [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] + [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong ConvertLuidToIndex(ulong id); + + [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] + public static extern bool CreateIPv4(string address, string netmask, ulong index); + + [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] + public static extern bool CreateUnicastIP(AddressFamily inet, string address, byte cidr, ulong index); + + [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] + public static extern bool RefreshIPTable(AddressFamily inet, ulong index); + + [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] + public static extern bool CreateRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric); + + [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] public static extern bool DeleteRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric); } } diff --git a/Netch/Properties/AssemblyInfo.cs b/Netch/Properties/AssemblyInfo.cs index 4a839623..72b75921 100644 --- a/Netch/Properties/AssemblyInfo.cs +++ b/Netch/Properties/AssemblyInfo.cs @@ -35,5 +35,5 @@ using System.Runtime.InteropServices; //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //通过使用 "*",如下所示: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion(UpdateChecker.AssemblyVersion)] +[assembly: AssemblyVersion(UpdateChecker.AssemblyVersion)] // [assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/Netch/Servers/Shadowsocks/SSUtil.cs b/Netch/Servers/Shadowsocks/SSUtil.cs index 32b2f6fc..78ac24bf 100644 --- a/Netch/Servers/Shadowsocks/SSUtil.cs +++ b/Netch/Servers/Shadowsocks/SSUtil.cs @@ -78,17 +78,17 @@ namespace Netch.Servers.Shadowsocks { var json = JsonSerializer.Deserialize
(ShareLink.URLSafeBase64Decode(s.Substring(6)))!; - return json.servers.Select(server => new Shadowsocks - { - Remark = server.remarks, - Hostname = server.server, - Port = server.port != 0 ? server.port : json.port, - Password = server.password ?? json.password, - EncryptMethod = server.encryption ?? json.encryption, - Plugin = string.IsNullOrEmpty(json.plugin) ? string.IsNullOrEmpty(server.plugin) ? null : server.plugin : json.plugin, + return json.servers.Select(server => new Shadowsocks + { + Remark = server.remarks, + Hostname = server.server, + Port = server.port != 0 ? server.port : json.port, + Password = server.password ?? json.password, + EncryptMethod = server.encryption ?? json.encryption, + Plugin = string.IsNullOrEmpty(json.plugin) ? string.IsNullOrEmpty(server.plugin) ? null : server.plugin : json.plugin, PluginOption = string.IsNullOrEmpty(json.plugin_options) ? string.IsNullOrEmpty(server.plugin_options) ? null : server.plugin_options - : json.plugin_options + : json.plugin_options }) .Where(CheckServer); } diff --git a/Netch/Servers/V2ray/Utils/V2rayConfigUtils.cs b/Netch/Servers/V2ray/Utils/V2rayConfigUtils.cs index 3b5eff52..b019b9af 100644 --- a/Netch/Servers/V2ray/Utils/V2rayConfigUtils.cs +++ b/Netch/Servers/V2ray/Utils/V2rayConfigUtils.cs @@ -108,8 +108,8 @@ namespace Netch.Servers.V2ray.Utils switch (server) { - case Socks5.Socks5 socks5: - { + case Socks5.Socks5 socks5: + { outbound.settings.servers = new List { new() @@ -128,81 +128,81 @@ namespace Netch.Servers.V2ray.Utils address = server.AutoResolveHostname(), port = server.Port } - }; - - outbound.mux.enabled = false; - outbound.mux.concurrency = -1; - outbound.protocol = "socks"; - break; + }; + + outbound.mux.enabled = false; + outbound.mux.concurrency = -1; + outbound.protocol = "socks"; + break; } - case VLESS.VLESS vless: - { - var vnextItem = new VnextItem - { - users = new List(), - address = server.AutoResolveHostname(), - port = server.Port - }; - - outbound.settings.vnext = new List { vnextItem }; - - var usersItem = new UsersItem - { - id = vless.UserID, - alterId = 0, - flow = string.Empty, - encryption = vless.EncryptMethod - }; - - vnextItem.users.Add(usersItem); - - var streamSettings = outbound.streamSettings; - boundStreamSettings(vless, ref streamSettings); - - if (vless.TLSSecureType == "xtls") - { - usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow; - - outbound.mux.enabled = false; - outbound.mux.concurrency = -1; - } - else - { - outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux; - outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1; - } - - outbound.protocol = "vless"; - outbound.settings.servers = null; - break; + case VLESS.VLESS vless: + { + var vnextItem = new VnextItem + { + users = new List(), + address = server.AutoResolveHostname(), + port = server.Port + }; + + outbound.settings.vnext = new List { vnextItem }; + + var usersItem = new UsersItem + { + id = vless.UserID, + alterId = 0, + flow = string.Empty, + encryption = vless.EncryptMethod + }; + + vnextItem.users.Add(usersItem); + + var streamSettings = outbound.streamSettings; + boundStreamSettings(vless, ref streamSettings); + + if (vless.TLSSecureType == "xtls") + { + usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow; + + outbound.mux.enabled = false; + outbound.mux.concurrency = -1; + } + else + { + outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux; + outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1; + } + + outbound.protocol = "vless"; + outbound.settings.servers = null; + break; } - case VMess.VMess vmess: - { - var vnextItem = new VnextItem - { - users = new List(), - address = server.AutoResolveHostname(), - port = server.Port - }; - - outbound.settings.vnext = new List { vnextItem }; - - var usersItem = new UsersItem - { - id = vmess.UserID, - alterId = vmess.AlterID, - security = vmess.EncryptMethod - }; - - vnextItem.users.Add(usersItem); - - var streamSettings = outbound.streamSettings; - boundStreamSettings(vmess, ref streamSettings); - - outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux; - outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1; - outbound.protocol = "vmess"; - break; + case VMess.VMess vmess: + { + var vnextItem = new VnextItem + { + users = new List(), + address = server.AutoResolveHostname(), + port = server.Port + }; + + outbound.settings.vnext = new List { vnextItem }; + + var usersItem = new UsersItem + { + id = vmess.UserID, + alterId = vmess.AlterID, + security = vmess.EncryptMethod + }; + + vnextItem.users.Add(usersItem); + + var streamSettings = outbound.streamSettings; + boundStreamSettings(vmess, ref streamSettings); + + outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux; + outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1; + outbound.protocol = "vmess"; + break; } } diff --git a/Netch/Servers/VMess/VMessUtil.cs b/Netch/Servers/VMess/VMessUtil.cs index 33116df7..5ea788ef 100644 --- a/Netch/Servers/VMess/VMessUtil.cs +++ b/Netch/Servers/VMess/VMessUtil.cs @@ -42,19 +42,19 @@ namespace Netch.Servers.VMess { var server = (VMess)s; - var vmessJson = JsonSerializer.Serialize(new V2rayNSharing - { - v = 2, - ps = server.Remark, - add = server.Hostname, - port = server.Port, - id = server.UserID, - aid = server.AlterID, - net = server.TransferProtocol, - type = server.FakeType, - host = server.Host, - path = server.Path, - tls = server.TLSSecureType + var vmessJson = JsonSerializer.Serialize(new V2rayNSharing + { + v = 2, + ps = server.Remark, + add = server.Hostname, + port = server.Port, + id = server.UserID, + aid = server.AlterID, + net = server.TransferProtocol, + type = server.FakeType, + host = server.Host, + path = server.Path, + tls = server.TLSSecureType }, new JsonSerializerOptions { diff --git a/Netch/Utils/ModeHelper.cs b/Netch/Utils/ModeHelper.cs index 5a5fd41e..54edc5c3 100644 --- a/Netch/Utils/ModeHelper.cs +++ b/Netch/Utils/ModeHelper.cs @@ -112,11 +112,11 @@ namespace Netch.Utils switch (mode.Type) { case 0: - return server switch - { - Socks5 => true, - Shadowsocks shadowsocks when !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS => true, - _ => false + return server switch + { + Socks5 => true, + Shadowsocks shadowsocks when !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS => true, + _ => false }; case 1: case 2: diff --git a/download.ps1 b/download.ps1 index 6d6baa6d..39afedb1 100644 --- a/download.ps1 +++ b/download.ps1 @@ -1,77 +1,77 @@ -param( - [Parameter()] - [ValidateNotNullOrEmpty()] - [string] - $OutputPath = "release", - - [Parameter()] - [ValidateNotNullOrEmpty()] - [string] - $CachePath = "DataCache" -) - -function DownloadAndExtract { - param ( - - # NetchX - [Parameter(Mandatory = $True)] - [ValidateNotNullOrEmpty()] - [string] - $Owner, - - # NetchMode - [Parameter(Mandatory = $True)] - [string] - [ValidateNotNullOrEmpty()] - $Repo, - - [Parameter()] - [ValidateNotNullOrEmpty()] - [string] - $ref = "heads/master", - - [Parameter(Mandatory = $True)] - [ValidateNotNullOrEmpty()] - [string] - $CachePath, - - [Parameter()] - [ValidateNotNull()] - [string] - $ReleativePath = "", - - [Parameter(Mandatory = $True)] - [ValidateNotNullOrEmpty()] - [string] - $TargetPath - ) - $json = Invoke-RestMethod "https://api.github.com/repos/$Owner/$Repo/git/refs/$ref" - $sha = $json.object.sha - $archiveUrl = "https://github.com/$Owner/$Repo/archive/$sha.zip" - - $fileName = "$repo-$sha" - $filePath = "$CachePath\$fileName.zip" - $cacheExtractPath = "$CachePath\$fileName" - - if ( -Not (Test-Path $filePath) ) { - Remove-Item -Recurse -Force $CachePath\$Repo* | Out-Null - Invoke-WebRequest -Uri $archiveUrl -OutFile $filePath - } - - if ( -Not (Test-Path $cacheExtractPath) ) { - Expand-Archive -Force -Path $filePath -DestinationPath $CachePath - } - - New-Item -Force -ItemType Directory -Path $TargetPath | Out-Null - Copy-Item -Recurse -Force "$cacheExtractPath\$ReleativePath\*" $TargetPath -} - -New-Item -Force -ItemType Directory -Path $OutputPath, $CachePath | Out-Null - -DownloadAndExtract -Owner "NetchX" -Repo "NetchData" -CachePath $CachePath -TargetPath $OutputPath\bin -DownloadAndExtract -Owner "NetchX" -Repo "NetchMode" -CachePath $CachePath -ReleativePath "mode" -TargetPath $OutputPath\mode -DownloadAndExtract -Owner "NetchX" -Repo "NetchI18N" -CachePath $CachePath -ReleativePath "i18n" -TargetPath $OutputPath\i18n - -Get-Item $OutputPath - +param( + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] + $OutputPath = "release", + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] + $CachePath = "DataCache" +) + +function DownloadAndExtract { + param ( + + # NetchX + [Parameter(Mandatory = $True)] + [ValidateNotNullOrEmpty()] + [string] + $Owner, + + # NetchMode + [Parameter(Mandatory = $True)] + [string] + [ValidateNotNullOrEmpty()] + $Repo, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] + $ref = "heads/master", + + [Parameter(Mandatory = $True)] + [ValidateNotNullOrEmpty()] + [string] + $CachePath, + + [Parameter()] + [ValidateNotNull()] + [string] + $ReleativePath = "", + + [Parameter(Mandatory = $True)] + [ValidateNotNullOrEmpty()] + [string] + $TargetPath + ) + $json = Invoke-RestMethod "https://api.github.com/repos/$Owner/$Repo/git/refs/$ref" + $sha = $json.object.sha + $archiveUrl = "https://github.com/$Owner/$Repo/archive/$sha.zip" + + $fileName = "$repo-$sha" + $filePath = "$CachePath\$fileName.zip" + $cacheExtractPath = "$CachePath\$fileName" + + if ( -Not (Test-Path $filePath) ) { + Remove-Item -Recurse -Force $CachePath\$Repo* | Out-Null + Invoke-WebRequest -Uri $archiveUrl -OutFile $filePath + } + + if ( -Not (Test-Path $cacheExtractPath) ) { + Expand-Archive -Force -Path $filePath -DestinationPath $CachePath + } + + New-Item -Force -ItemType Directory -Path $TargetPath | Out-Null + Copy-Item -Recurse -Force "$cacheExtractPath\$ReleativePath\*" $TargetPath +} + +New-Item -Force -ItemType Directory -Path $OutputPath, $CachePath | Out-Null + +DownloadAndExtract -Owner "NetchX" -Repo "NetchData" -CachePath $CachePath -TargetPath $OutputPath\bin +DownloadAndExtract -Owner "NetchX" -Repo "NetchMode" -CachePath $CachePath -ReleativePath "mode" -TargetPath $OutputPath\mode +DownloadAndExtract -Owner "NetchX" -Repo "NetchI18N" -CachePath $CachePath -ReleativePath "i18n" -TargetPath $OutputPath\i18n + +Get-Item $OutputPath + exit 0; \ No newline at end of file