From 04ef9b65a5b588ba98b8be738bc554c9b31af758 Mon Sep 17 00:00:00 2001 From: Sidney Zhang Date: Mon, 22 Jun 2026 15:42:44 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E9=87=8D=E6=9E=84=20README=20=E6=96=B0?= =?UTF-8?q?=E6=89=8B=E4=BD=BF=E7=94=A8=E8=AF=B4=E6=98=8E=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=B8=80=E9=94=AE=E5=AE=89=E8=A3=85=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 133 +++++++++++++++++++--- setup.bat | 24 ++++ setup.ps1 | 281 +++++++++++++++++++++++++++++++++++++++++++++++ uv-installer.ps1 | 161 ++++++++++++++++++--------- 4 files changed, 529 insertions(+), 70 deletions(-) create mode 100644 setup.bat create mode 100644 setup.ps1 diff --git a/README.md b/README.md index 640fb51..ad37630 100644 --- a/README.md +++ b/README.md @@ -17,26 +17,94 @@ ## 新手使用说明 -如果你是第一次使用命令行工具,请按以下步骤操作。 +如果你是第一次使用命令行工具,请按以下步骤操作。我们提供了一键安装脚本,尽量让你少输入命令。 -### 准备工作 +### 安装前准备 - **PowerPoint**:需要安装 Microsoft PowerPoint(Office 2016 或更新版本) - **网络连接**:安装过程中需要下载工具 -- **理解命令行工具**:你需要理解命令行的基本操作,包括文件路径、参数传递等。 +- **解压项目**:把下载的 `pptopic.zip` 解压到任意位置,例如桌面 -### PowerShell的基本知识 +### 一键安装(推荐) -PowerShell在Windows中是自带的,所以一般情况下无需额外安装。如果你不知道如何打开,可以在开始菜单搜索 "PowerShell",通常就能看见,点击后即可打开。 +项目根目录下有一个 `setup.bat`,它会自动完成: -在PowerShell中跳转目录,只需要输入 `cd` 加上目录路径即可。目录路径可以从资源管理器中在地址栏中复制。如果你的目录路径中包含空格,需要在路径中添加引号。 +1. 安装 `uv`(Python 包管理器) +2. 安装 Python 3.13 +3. 安装 `pngquant`(图片压缩工具,强烈推荐) +4. 安装 `pptopic` +5. 验证安装结果 + +#### 方法 A:双击运行(最简单) + +1. 打开解压后的 `pptopic` 文件夹 +2. 找到 `setup.bat` 文件 +3. **双击** `setup.bat` +4. 等待安装完成,窗口会显示版本信息 + +> 如果 Windows 提示“Windows 已保护你的电脑”,请点击“更多信息” → “仍要运行”。 + +#### 方法 B:右键在 PowerShell 中运行 + +如果双击运行被系统拦截,可以按以下步骤: + +1. 打开解压后的 `pptopic` 文件夹 +2. 在文件夹**空白处**按住 `Shift` 键,同时点击**鼠标右键** +3. 选择“在此处打开 PowerShell 窗口”(Windows 11 可能显示为“在终端中打开”) +4. 在弹出的蓝色窗口中输入以下命令,然后按回车: ```powershell -# 这是一个例子 -cd "C:\Users\User SomeX\Desktop\OneFolder" +.\setup.bat ``` -### 第一步:安装 uv +等待安装完成即可。 + +#### 安装完成后 + +如果看到类似下面的输出,说明安装成功: + +``` +--- uv 版本 --- +uv 0.11.20 + +--- pngquant 版本 --- +2.17.0 + +--- pptopic 版本 --- +pptopic 0.3.2 +``` + +然后你可以直接在当前窗口使用 pptopic: + +```powershell +# 导出 PPTX 为长图 +pptopic export presentation.pptx + +# 工作中常用命令:导出 PPTX 为长图并优化图片 +# 其中,29999 是微信接受的最大高度 +pptopic export presentation.pptx --optimize --max-height 29999 -o result.png +``` + +### 一键安装脚本的参数(可选) + +如果你不想安装 pngquant,可以使用以下方式运行: + +```powershell +# 在 PowerShell 中直接运行 setup.ps1,跳过 pngquant +powershell -ExecutionPolicy Bypass -File .\setup.ps1 -SkipPngquant +``` + +其他可用参数: + +- `-SkipPngquant`:跳过 pngquant 安装 +- `-Force`:强制重新安装 uv 和 pngquant +- `-SkipPptopicInstall`:只安装环境,不安装 pptopic + +### 手动安装(备用) + +如果一键安装脚本在你的电脑上无法运行,可以按以下步骤手动安装。 + +#### 第一步:安装 uv `uv` 是一个 Python 包管理器,用来安装 pptopic 及其依赖。 @@ -46,7 +114,7 @@ cd "C:\Users\User SomeX\Desktop\OneFolder" cd "<你的解压目录>\pptopic" ``` -赋予PowerShell执行权限: +赋予 PowerShell 执行权限: ```powershell Set-ExecutionPolicy Bypass -Scope CurrentUser @@ -70,7 +138,7 @@ uv --version > - 如果你已安装 [scoop](https://scoop.sh/),也可以直接 `scoop install uv`。 > - 如果想安装特定版本的 uv,可以在运行脚本前设置环境变量:`$env:UV_INSTALLER_VERSION = "0.11.20"` -### 第二步:安装 Python +#### 第二步:安装 Python 使用 uv 安装 Python 3.13 或更新版本: @@ -78,9 +146,9 @@ uv --version uv python install 3.13 ``` -### 第三步(可选):安装 pngquant 图片优化工具 +#### 第三步(可选):安装 pngquant 图片优化工具 -虽然是可选安装,但我超级建议你安装,因为ppt导出后,图片通常较大,不进行图片无损压缩,会导致文件大小过大。 +虽然是可选安装,但我超级建议你安装,因为 ppt 导出后,图片通常较大,不进行图片无损压缩,会导致文件大小过大。 如果你需要对导出的图片进行压缩优化,运行: @@ -101,13 +169,13 @@ pngquant --version > - 自定义安装目录:`.\install-pngquant.ps1 -InstallDir "D:\Tools\pngquant"` > - 强制重新安装:`.\install-pngquant.ps1 -Force` -### 第四步:安装pptopic +#### 第四步:安装 pptopic ```powershell uv tool install -e . ``` -### 第五步:开始使用 +#### 第五步:开始使用 ```powershell # 导出 PPTX 为长图 @@ -117,11 +185,11 @@ pptopic export presentation.pptx pptopic optimize image.png # 工作中常用命令:导出 PPTX 为长图并优化图片 -# 其中,29999是微信接受的最大高度 +# 其中,29999 是微信接受的最大高度 pptopic export presentation.pptx --optimize --max-height 29999 -o result.png ``` -至此安装完成。如果任何步骤遇到问题,请参考下方详细说明。 +至此安装完成。 ## 一般安装说明 @@ -222,6 +290,37 @@ scoop install pngquant 或从 [pngquant.org](https://pngquant.org/) 下载 Windows 版本手动配置。 +## 常见问题 + +### 运行 `setup.bat` 时提示“无法加载文件,因为在此系统上禁止运行脚本” + +这说明当前电脑通过组策略严格限制了脚本执行。`setup.bat` 已经尝试用 `-ExecutionPolicy Bypass` 绕过,但仍可能被拦截。 + +解决方法:使用 **方法 B**,在 PowerShell 窗口中手动运行: + +```powershell +powershell -ExecutionPolicy Bypass -File .\setup.ps1 +``` + +不需要以管理员身份运行,本安装脚本只修改当前用户的环境变量。 + +### 安装完成后关闭窗口,新窗口中找不到 `pptopic` 命令 + +请重新运行一次 `setup.bat`。如果问题依旧,请检查系统环境变量中的 PATH 是否包含以下目录: + +- `%USERPROFILE%\.local\bin`(uv 和 pptopic 的位置) +- `%APPDATA%\pngquant`(pngquant 的位置) + +### 不想安装 pngquant 怎么办? + +可以运行: + +```powershell +powershell -ExecutionPolicy Bypass -File .\setup.ps1 -SkipPngquant +``` + +但强烈建议安装,否则导出的长图文件会比较大。 + ## License MIT License diff --git a/setup.bat b/setup.bat new file mode 100644 index 0000000..674e403 --- /dev/null +++ b/setup.bat @@ -0,0 +1,24 @@ +@echo off +chcp 65001 >nul +echo. +echo ======================================== +echo pptopic 一键安装程序 +echo ======================================== +echo. +echo 即将自动安装:uv、Python 3.13、pngquant 和 pptopic +echo 安装过程中请勿关闭此窗口... +echo. + +powershell -ExecutionPolicy Bypass -File "%~dp0setup.ps1" %* + +if %errorlevel% neq 0 ( + echo. + echo 安装过程中出现错误,请查看上方提示。 + echo. + pause + exit /b %errorlevel% +) + +echo. +echo 按任意键关闭此窗口... +pause >nul diff --git a/setup.ps1 b/setup.ps1 new file mode 100644 index 0000000..e9de12e --- /dev/null +++ b/setup.ps1 @@ -0,0 +1,281 @@ +#Requires -Version 5.1 + +<# +.SYNOPSIS + pptopic 一键安装脚本 + +.DESCRIPTION + 自动完成以下安装步骤: + 1. 安装 uv(Python 包管理器) + 2. 安装 Python 3.13 + 3. 安装 pngquant(可选但推荐) + 4. 安装 pptopic + 5. 验证安装结果 + + 本脚本会自动处理 PowerShell 执行策略和当前会话 PATH 刷新, + 安装完成后无需手动重启 PowerShell。 + +.PARAMETER SkipPngquant + 跳过 pngquant 安装。 + +.PARAMETER Force + 强制重新安装 uv 和 pngquant。 + +.PARAMETER SkipPptopicInstall + 只安装环境,不安装 pptopic(调试用)。 + +.EXAMPLE + .\setup.ps1 + +.EXAMPLE + .\setup.ps1 -SkipPngquant +#> + +param( + [switch]$SkipPngquant, + [switch]$Force, + [switch]$SkipPptopicInstall +) + +$ErrorActionPreference = "Stop" +$InformationPreference = "Continue" + +$ProjectRoot = $PSScriptRoot +if ([string]::IsNullOrWhiteSpace($ProjectRoot)) { + $ProjectRoot = (Get-Location).Path +} + +# ============================================================ +# 工具函数 +# ============================================================ + +function Test-CommandExists { + param([string]$Name) + try { + $cmd = Get-Command $Name -ErrorAction Stop + return $cmd.Source + } catch { + return $null + } +} + +function Add-ToCurrentPath { + param([string]$LiteralPath) + + if ([string]::IsNullOrWhiteSpace($LiteralPath)) { + return + } + + $currentPaths = $env:Path -split ';' | ForEach-Object { $_.TrimEnd('\') } + $normalizedPath = $LiteralPath.TrimEnd('\') + + if ($normalizedPath -in $currentPaths) { + return + } + + if (-not (Test-Path $LiteralPath)) { + return + } + + $env:Path = "$LiteralPath;$env:Path" + Write-Information "已临时将 $LiteralPath 加入当前会话 PATH" +} + +function Get-UvInstallDir { + # uv-installer.ps1 的安装位置优先级 + $candidates = @() + if ($env:XDG_BIN_HOME) { + $candidates += $env:XDG_BIN_HOME + } + if ($env:XDG_DATA_HOME) { + $candidates += (Join-Path $env:XDG_DATA_HOME "../bin") + } + $candidates += (Join-Path $HOME ".local\bin") + + foreach ($candidate in $candidates) { + $resolved = $null + try { + $resolved = (Resolve-Path $candidate -ErrorAction SilentlyContinue).Path + } catch { + $resolved = $candidate + } + if ($resolved -and (Test-Path $resolved)) { + return $resolved + } + } + + # 默认返回最后一个候选 + return Join-Path $HOME ".local\bin" +} + +function Invoke-Step { + param( + [Parameter(Mandatory)][string]$Title, + [Parameter(Mandatory)][scriptblock]$Action + ) + + Write-Information "" + Write-Information "========================================" + Write-Information " $Title" + Write-Information "========================================" + + try { + & $Action + } catch { + Write-Information "" + Write-Information "失败:$_" + throw + } +} + +# ============================================================ +# 主流程 +# ============================================================ + +Write-Information "" +Write-Information "========================================" +Write-Information " pptopic 一键安装程序" +Write-Information "========================================" +Write-Information "" +Write-Information "项目目录:$ProjectRoot" + +if ($SkipPngquant) { + Write-Information "已指定 -SkipPngquant,将跳过 pngquant 安装。" +} +if ($Force) { + Write-Information "已指定 -Force,将强制重新安装 uv / pngquant。" +} + +# 第一步:安装 uv +Invoke-Step -Title "步骤 1/5:安装 uv" -Action { + $uvPath = Test-CommandExists -Name "uv" + + if ($uvPath -and -not $Force) { + Write-Information "uv 已存在:$uvPath" + } else { + $installer = Join-Path $ProjectRoot "uv-installer.ps1" + if (-not (Test-Path $installer)) { + throw "找不到 uv 安装脚本:$installer" + } + + Write-Information "正在运行 uv-installer.ps1..." + & $installer + } + + # uv-installer.ps1 会修改注册表 PATH,但当前会话不会立即生效,需要手动加入 + $uvInstallDir = Get-UvInstallDir + Add-ToCurrentPath -LiteralPath $uvInstallDir + + # 再次验证 + $uvPath = Test-CommandExists -Name "uv" + if (-not $uvPath) { + throw "uv 安装后仍无法在当前会话中找到,请尝试重启终端后重试。" + } + + Write-Information "uv 路径:$uvPath" +} + +# 第二步:安装 Python 3.13 +Invoke-Step -Title "步骤 2/5:安装 Python 3.13" -Action { + Write-Information "正在使用 uv 安装 Python 3.13..." + uv python install 3.13 + Write-Information "Python 安装完成。" +} + +# 第三步:安装 pngquant +if (-not $SkipPngquant) { + Invoke-Step -Title "步骤 3/5:安装 pngquant" -Action { + $pngquantPath = Test-CommandExists -Name "pngquant" + + if ($pngquantPath -and -not $Force) { + Write-Information "pngquant 已存在:$pngquantPath" + } else { + $installer = Join-Path $ProjectRoot "install-pngquant.ps1" + if (-not (Test-Path $installer)) { + throw "找不到 pngquant 安装脚本:$installer" + } + + if ($Force) { + Write-Information "正在运行 install-pngquant.ps1 -Force..." + & $installer -Force + } else { + Write-Information "正在运行 install-pngquant.ps1..." + & $installer + } + } + + # install-pngquant.ps1 内部已刷新当前会话 PATH,这里再做一次保险 + Add-ToCurrentPath -LiteralPath "$env:APPDATA\pngquant" + + $pngquantPath = Test-CommandExists -Name "pngquant" + if (-not $pngquantPath) { + throw "pngquant 安装后仍无法在当前会话中找到,请尝试重启终端后重试。" + } + + Write-Information "pngquant 路径:$pngquantPath" + } +} else { + Write-Information "" + Write-Information "========================================" + Write-Information " 步骤 3/5:跳过 pngquant 安装" + Write-Information "========================================" +} + +# 第四步:安装 pptopic +if (-not $SkipPptopicInstall) { + Invoke-Step -Title "步骤 4/5:安装 pptopic" -Action { + $pyproject = Join-Path $ProjectRoot "pyproject.toml" + if (-not (Test-Path $pyproject)) { + throw "找不到 pyproject.toml:$pyproject" + } + + Write-Information "正在使用 uv tool install -e $ProjectRoot 安装 pptopic..." + uv tool install -e $ProjectRoot + Write-Information "pptopic 安装完成。" + } +} else { + Write-Information "" + Write-Information "========================================" + Write-Information " 步骤 4/5:跳过 pptopic 安装" + Write-Information "========================================" +} + +# 第五步:验证 +Invoke-Step -Title "步骤 5/5:验证安装" -Action { + Write-Information "" + Write-Information "--- uv 版本 ---" + uv --version + + if (-not $SkipPngquant) { + Write-Information "" + Write-Information "--- pngquant 版本 ---" + pngquant --version + } + + if (-not $SkipPptopicInstall) { + Write-Information "" + Write-Information "--- pptopic 版本 ---" + pptopic version + } +} + +# ============================================================ +# 完成 +# ============================================================ + +Write-Information "" +Write-Information "========================================" +Write-Information " pptopic 一键安装完成!" +Write-Information "========================================" +Write-Information "" + +if (-not $SkipPptopicInstall) { + Write-Information "你可以立即在当前窗口使用以下命令:" + Write-Information " pptopic export 你的文件.pptx" + Write-Information " pptopic export 你的文件.pptx --optimize --max-height 29999 -o result.png" +} + +Write-Information "" +Write-Information "提示:本脚本已自动刷新当前 PowerShell 会话的 PATH,无需重启终端。" +Write-Information "如果关闭此窗口后在新窗口中找不到命令,请重新运行一次 setup.bat。" +Write-Information "" diff --git a/uv-installer.ps1 b/uv-installer.ps1 index 180f7f1..7e6c9a4 100644 --- a/uv-installer.ps1 +++ b/uv-installer.ps1 @@ -33,6 +33,90 @@ param ( [Parameter(HelpMessage = "Print Help")] [switch]$Help ) +function WebProxyFromUrl { + param([string]$ProxyUrl) + + if ([string]::IsNullOrWhiteSpace($ProxyUrl)) { + return $null + } + + try { + # Parse the proxy URL + $uri = [System.Uri]$ProxyUrl + + # Create WebProxy instance + $webProxy = New-Object System.Net.WebProxy($uri) + + # Set credentials if provided in URL + if (-not [string]::IsNullOrEmpty($uri.UserInfo)) { + $userInfo = $uri.UserInfo.Split(':') + $username = [System.Uri]::UnescapeDataString($userInfo[0]) + $password = if ($null -eq $userInfo[1]) { "" } else { [System.Uri]::UnescapeDataString($userInfo[1]) } + $webProxy.Credentials = New-Object System.Net.NetworkCredential($username, $password) + } + + return $webProxy + } + catch { + Write-Verbose("Failed to parse proxy URL '$ProxyUrl': $($_.Exception.Message)") + return $null + } +} + +function WebProxyFromEnvironment { + $httpsProxy = [System.Environment]::GetEnvironmentVariable("HTTPS_PROXY") + $allProxy = [System.Environment]::GetEnvironmentVariable("ALL_PROXY") + $proxyUrl = if (-not [string]::IsNullOrWhiteSpace($httpsProxy)) { $httpsProxy } else { $allProxy } + $webProxy = WebProxyFromUrl -ProxyUrl $proxyUrl + return $webProxy +} + +# Downloads a URL to a local file using HttpClient with: +# * a configurable per-request timeout (WebClient has none) +# * proxy support from HTTPS_PROXY / ALL_PROXY +# * bearer auth, attached ONLY when the target host is a trusted first-party +# (github.com / astral.sh). This prevents leaking UV_GITHUB_TOKEN to +# third-party mirrors configured in $ArtifactDownloadUrls. +function Invoke-HttpDownload { + param( + [Parameter(Mandatory = $true)][string]$Url, + [Parameter(Mandatory = $true)][string]$Destination, + [int]$TimeoutSec = 30, + [switch]$IncludeAuth + ) + + $handler = New-Object System.Net.Http.HttpClientHandler + $proxy = WebProxyFromEnvironment + if ($null -ne $proxy) { + $handler.Proxy = $proxy + $handler.UseProxy = $true + } + + $client = New-Object System.Net.Http.HttpClient($handler) + $client.Timeout = [TimeSpan]::FromSeconds($TimeoutSec) + $client.DefaultRequestHeaders.Add("User-Agent", "PowerShell/uv-installer") + + if ($IncludeAuth -and $auth_token -and ($Url -match 'github\.com|astral\.sh')) { + $client.DefaultRequestHeaders.Add("Authorization", "Bearer $auth_token") + } + + try { + $response = $client.GetAsync($Url, [System.Net.Http.HttpCompletionOption]::ResponseHeadersRead).Result + if (-not $response.IsSuccessStatusCode) { + throw "HTTP $([int]$response.StatusCode) downloading $Url" + } + $stream = $response.Content.ReadAsStreamAsync().Result + $fileStream = [System.IO.File]::Create($Destination) + try { + $stream.CopyTo($fileStream) + } finally { + $fileStream.Dispose() + } + } finally { + $client.Dispose() + } +} + function Get-LatestVersion { if ($env:UV_INSTALLER_VERSION) { return $env:UV_INSTALLER_VERSION @@ -41,10 +125,22 @@ function Get-LatestVersion { $fallback_version = "0.11.20" try { - $http = New-Object System.Net.Http.HttpClient - $http.Timeout = [TimeSpan]::FromSeconds(5) + $handler = New-Object System.Net.Http.HttpClientHandler + $proxy = WebProxyFromEnvironment + if ($null -ne $proxy) { + $handler.Proxy = $proxy + $handler.UseProxy = $true + } + + $http = New-Object System.Net.Http.HttpClient($handler) + # Bumped from 5s -> 10s. The API call is small but in proxy/restricted + # networks 5s was almost always too tight and forced the fallback version. + $http.Timeout = [TimeSpan]::FromSeconds(10) $http.DefaultRequestHeaders.Add("User-Agent", "PowerShell/uv-installer") $http.DefaultRequestHeaders.Add("Accept", "application/vnd.github+json") + if ($auth_token) { + $http.DefaultRequestHeaders.Add("Authorization", "Bearer $auth_token") + } $response = $http.GetStringAsync("https://api.github.com/repos/astral-sh/uv/releases/latest").Result $json = $response | ConvertFrom-Json $version = $json.tag_name @@ -60,6 +156,9 @@ function Get-LatestVersion { } $app_name = 'uv' +# NOTE: $auth_token must be defined *before* Get-LatestVersion / Invoke-HttpDownload +# are invoked, since both reference it. +$auth_token = $env:UV_GITHUB_TOKEN $app_version = Get-LatestVersion if ($env:UV_DOWNLOAD_URL) { $ArtifactDownloadUrls = @($env:UV_DOWNLOAD_URL) @@ -72,6 +171,10 @@ if ($env:UV_DOWNLOAD_URL) { $installer_base_url = $env:UV_INSTALLER_GITHUB_BASE_URL $ArtifactDownloadUrls = @("$installer_base_url/astral-sh/uv/releases/download/$app_version") } else { + # Default download sources, ordered by priority. + # Mirror entries exist to work around GitHub connectivity issues in mainland China. + # If you are outside China or these mirrors become unavailable, you can safely + # delete the two mirror lines and rely on the official URLs (first + last). $ArtifactDownloadUrls = @( "https://releases.astral.sh/github/uv/releases/download/$app_version", "https://mirror.ghproxy.com/https://github.com/astral-sh/uv/releases/download/$app_version", @@ -80,8 +183,6 @@ if ($env:UV_DOWNLOAD_URL) { ) } -$auth_token = $env:UV_GITHUB_TOKEN - $receipt = @" {"binaries":["CARGO_DIST_BINS"],"binary_aliases":{},"cdylibs":["CARGO_DIST_DYLIBS"],"cstaticlibs":["CARGO_DIST_STATICLIBS"],"install_layout":"unspecified","install_prefix":"AXO_INSTALL_PREFIX","modify_path":true,"provider":{"source":"cargo-dist","version":"0.31.0"},"source":{"app_name":"uv","name":"uv","owner":"astral-sh","release_type":"github"},"version":"$app_version"} "@ @@ -269,44 +370,6 @@ function Get-Arch() { } } -function WebProxyFromUrl { - param([string]$ProxyUrl) - - if ([string]::IsNullOrWhiteSpace($ProxyUrl)) { - return $null - } - - try { - # Parse the proxy URL - $uri = [System.Uri]$ProxyUrl - - # Create WebProxy instance - $webProxy = New-Object System.Net.WebProxy($uri) - - # Set credentials if provided in URL - if (-not [string]::IsNullOrEmpty($uri.UserInfo)) { - $userInfo = $uri.UserInfo.Split(':') - $username = [System.Uri]::UnescapeDataString($userInfo[0]) - $password = if ($null -eq $userInfo[1]) { "" } else { [System.Uri]::UnescapeDataString($userInfo[1]) } - $webProxy.Credentials = New-Object System.Net.NetworkCredential($username, $password) - } - - return $webProxy - } - catch { - Write-Verbose("Failed to parse proxy URL '$ProxyUrl': $($_.Exception.Message)") - return $null - } -} - -function WebProxyFromEnvironment { - $httpsProxy = [System.Environment]::GetEnvironmentVariable("HTTPS_PROXY") - $allProxy = [System.Environment]::GetEnvironmentVariable("ALL_PROXY") - $proxyUrl = if (-not [string]::IsNullOrWhiteSpace($httpsProxy)) { $httpsProxy } else { $allProxy } - $webProxy = WebProxyFromUrl -ProxyUrl $proxyUrl - return $webProxy -} - function Download($download_url, $platforms, $arch) { # Lookup what we expect this platform to look like $info = $platforms[$arch] @@ -324,15 +387,7 @@ function Download($download_url, $platforms, $arch) { $url = "$download_url/$artifact_name" Write-Verbose " from $url" Write-Verbose " to $dir_path" - $wc = New-Object Net.Webclient - $proxy = WebProxyFromEnvironment - if ($null -ne $proxy) { - $wc.Proxy = $proxy - } - if ($auth_token) { - $wc.Headers["Authorization"] = "Bearer $auth_token" - } - $wc.downloadFile($url, $dir_path) + Invoke-HttpDownload -Url $url -Destination $dir_path -TimeoutSec 30 -IncludeAuth Write-Verbose "Unpacking to $tmp" @@ -377,7 +432,7 @@ function Download($download_url, $platforms, $arch) { $updater_url = "$download_url/$updater_id" $out_name = "$tmp\uv-update.exe" - $wc.downloadFile($updater_url, $out_name) + Invoke-HttpDownload -Url $updater_url -Destination $out_name -TimeoutSec 30 -IncludeAuth $bin_paths += $out_name } @@ -549,7 +604,7 @@ function Invoke-Installer($artifacts, $platforms) { # .NET's APIs which actually do what you tell them (also apparently utf8NoBOM is the # default in newer .NETs but I'd rather not rely on that at this point). $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False - [IO.File]::WriteAllLines("$receipt_home/uv-receipt.json", "$receipt", $Utf8NoBomEncoding) + [IO.File]::WriteAllLines("$receipt_home\uv-receipt.json", "$receipt", $Utf8NoBomEncoding) } # Respect the environment, but CLI takes precedence