Created
October 26, 2025 06:24
-
-
Save ilovejs/005f913dd3dc8eb5a4e8fc4c399f84f1 to your computer and use it in GitHub Desktop.
alist manager install on windows 10, english version
This file contains hidden or 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
| # Alist Manager Script for Windows | |
| # Version: 3.57.0 (Random password only after first installation) | |
| # Run with below command in Windows, open with Powershell with admin permission or Open in ISE editor | |
| # Executing should set-executionpolicy unrestricted | |
| # This allow u to run unsigned ps script. | |
| # | |
| # Powershell -executionpolicy bypass -File alist-manager.ps1 | |
| # ----------------------------- | |
| # Check for administrator privileges and elevate if needed | |
| function Test-Administrator { | |
| $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent() | |
| $principal = New-Object Security.Principal.WindowsPrincipal($currentUser) | |
| return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) | |
| } | |
| if (-not (Test-Administrator)) { | |
| Write-Host "This script requires administrator privileges. Attempting to elevate..." -ForegroundColor Yellow | |
| $arguments = "-ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`"" | |
| Start-Process powershell -ArgumentList $arguments -Verb RunAs | |
| exit | |
| } | |
| # ----------------------------- | |
| # Auto-detect PowerShell version and set output encoding | |
| $psVersion = $PSVersionTable.PSVersion.Major | |
| if ($psVersion -ge 7) { | |
| chcp 65001 > $null | |
| [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 | |
| $EncName = "UTF-8" | |
| } else { | |
| chcp 936 > $null | |
| [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding(936) | |
| $EncName = "GBK" | |
| } | |
| Write-Host "Current terminal encoding: $EncName" -ForegroundColor Yellow | |
| # ----------------------------- | |
| param($Action, $InstallPath) | |
| if (-not $Action) { $Action = "menu" } | |
| if (-not $InstallPath) { $InstallPath = "C:\alist" } | |
| # ----------------------------- | |
| # Colors and constants | |
| $Green = "Green" | |
| $Red = "Red" | |
| $Yellow = "Yellow" | |
| $White = "White" | |
| $ServiceName = "AlistService" | |
| $nssmPath = "$InstallPath\nssm.exe" | |
| # ----------------------------- | |
| function Write-Info($msg, $color="White") { | |
| $validColors = @("Black","DarkBlue","DarkGreen","DarkCyan","DarkRed", | |
| "DarkMagenta","DarkYellow","Gray","DarkGray","Blue", | |
| "Green","Cyan","Red","Magenta","Yellow","White") | |
| if ($validColors -contains $color) { | |
| [Console]::ForegroundColor = $color | |
| [Console]::WriteLine($msg) | |
| [Console]::ResetColor() | |
| } else { | |
| [Console]::WriteLine($msg) | |
| } | |
| } | |
| function Download-File($url, $output) { | |
| Try { | |
| Invoke-WebRequest -Uri $url -OutFile $output -UseBasicParsing -TimeoutSec 30 | |
| return $true | |
| } Catch { | |
| Write-Info "Download failed: $url" $Red | |
| return $false | |
| } | |
| } | |
| function Get-LatestVersion { | |
| $apiUrl = "https://api.github.com/repos/alist-org/alist/releases/latest" | |
| Try { | |
| $json = Invoke-RestMethod -Uri $apiUrl -Headers @{ "User-Agent" = "PowerShell" } -TimeoutSec 10 | |
| return $json.tag_name.TrimStart("v") | |
| } Catch { | |
| Write-Info "Failed to get version info, using default version 3.52.0" $Yellow | |
| return "3.52.0" | |
| } | |
| } | |
| # ----------------------------- | |
| # Get real physical network card IPv4 | |
| function Get-LocalIP { | |
| $realNICs = Get-NetIPAddress -AddressFamily IPv4 | Where-Object { | |
| $_.IPAddress -ne "127.0.0.1" -and | |
| $_.IPAddress -notlike "169.*" -and | |
| $_.InterfaceAlias -notmatch "vEthernet|Virtual|VMware|Loopback|WSL|Hyper-V" -and | |
| $_.ValidLifetime -ne "Infinite" | |
| } | |
| $ip = $realNICs | Sort-Object InterfaceMetric | Select-Object -First 1 -ExpandProperty IPAddress | |
| if (-not $ip) { $ip = "127.0.0.1" } | |
| return $ip | |
| } | |
| # ----------------------------- | |
| function Install-NSSM { | |
| if (-Not (Test-Path $nssmPath)) { | |
| $tmpZip = "$env:TEMP\nssm.zip" | |
| $tmpDir = "$env:TEMP\nssm" | |
| Write-Info "Downloading nssm ..." $Green | |
| if (-Not (Download-File "https://nssm.cc/release/nssm-2.24.zip" $tmpZip)) { | |
| Write-Info "nssm download failed, please manually download nssm-2.24.zip and place it in $InstallPath" $Red | |
| exit 1 | |
| } | |
| if (Test-Path $tmpDir) { Remove-Item $tmpDir -Recurse -Force } | |
| Expand-Archive $tmpZip -DestinationPath $tmpDir -Force | |
| $nssmExeSrc = Get-ChildItem -Path $tmpDir -Recurse -Filter "nssm.exe" | Where-Object { $_.FullName -match "win64" } | Select-Object -First 1 | |
| if (-Not $nssmExeSrc) { | |
| Write-Info "nssm.exe not found" $Red | |
| exit 1 | |
| } | |
| Copy-Item $nssmExeSrc.FullName $InstallPath -Force | |
| Remove-Item $tmpZip -Force | |
| Remove-Item $tmpDir -Recurse -Force | |
| Write-Info "nssm installation completed" $Green | |
| } | |
| # Verify nssm is working | |
| if (Test-Path $nssmPath) { | |
| try { | |
| $nssmTest = & $nssmPath version 2>&1 | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Info "nssm version: $nssmTest" $Green | |
| } else { | |
| Write-Info "nssm version check failed: $nssmTest" $Yellow | |
| } | |
| } catch { | |
| Write-Info "nssm verification failed: $($_.Exception.Message)" $Yellow | |
| } | |
| } | |
| } | |
| function Get-Arch { | |
| switch ($env:PROCESSOR_ARCHITECTURE) { | |
| "AMD64" { return "amd64" } | |
| "ARM64" { return "arm64" } | |
| default { return "386" } | |
| } | |
| } | |
| function Install-Alist { | |
| if (-Not (Test-Path $InstallPath)) { New-Item -ItemType Directory -Path $InstallPath | Out-Null } | |
| $arch = Get-Arch | |
| Write-Info "Detected CPU architecture: $arch" $Green | |
| $version = Get-LatestVersion | |
| Write-Info "Latest version: $version" $Green | |
| # Official mirror download URL (based on CPU architecture) | |
| $filename = "alist-windows-$arch.zip" | |
| $officialUrl = "https://alistgo.com/download/Alist/v$version/$filename" | |
| $tmpZip = "$env:TEMP\alist.zip" | |
| Write-Info "Attempting to download from official mirror: $officialUrl" $Green | |
| $success = Download-File $officialUrl $tmpZip | |
| if (-not $success) { | |
| Write-Info "Official mirror download failed!" $Yellow | |
| # Prompt user to choose GitHub download | |
| Write-Info "Use GitHub source for download?" $Green | |
| Write-Info "1. Use GitHub default address" $Green | |
| Write-Info "2. Use GitHub proxy" $Green | |
| $choice = Read-Host "Please select [1-2] (default 1)" | |
| if ($choice -eq "2") { | |
| $proxyInput = Read-Host "Please enter proxy address (starts with https://, ends with /)" | |
| if ($proxyInput) { | |
| $ghProxy = $proxyInput | |
| $downloadBase = "${ghProxy}https://github.com/alist-org/alist/releases/latest/download" | |
| } else { | |
| $downloadBase = "https://github.com/alist-org/alist/releases/latest/download" | |
| } | |
| } else { | |
| $downloadBase = "https://github.com/alist-org/alist/releases/download/v$version" | |
| } | |
| $url = "$downloadBase/$filename" | |
| Write-Info "Starting download from GitHub: $url" $Green | |
| if (-Not (Download-File $url $tmpZip)) { | |
| Write-Info "GitHub download failed! Please check network or proxy" $Red | |
| exit 1 | |
| } | |
| } | |
| # Extract | |
| Expand-Archive -Path $tmpZip -DestinationPath $InstallPath -Force | |
| Remove-Item $tmpZip -Force | |
| Write-Info "Alist has been installed to $InstallPath" $Green | |
| } | |
| # ----------------------------- | |
| function Invoke-AlistAdminRandom { | |
| if (-Not (Test-Path "$InstallPath\alist.exe")) { | |
| throw "alist.exe not found at $InstallPath, please install Alist first." | |
| } | |
| Push-Location $InstallPath | |
| try { | |
| $output = & "$InstallPath\alist.exe" admin random 2>&1 | |
| } finally { | |
| Pop-Location | |
| } | |
| $uMatch = ($output | Select-String -Pattern 'username:\s*(\S+)' -AllMatches).Matches | Select-Object -First 1 | |
| $pMatch = ($output | Select-String -Pattern 'password:\s*(\S+)' -AllMatches).Matches | Select-Object -First 1 | |
| if (-not $uMatch -or -not $pMatch) { | |
| throw "Failed to parse random username/password. Command output:`n$output" | |
| } | |
| $username = $uMatch.Groups[1].Value | |
| $password = $pMatch.Groups[1].Value | |
| return @{ Username = $username; Password = $password; Raw = $output } | |
| } | |
| # ----------------------------- | |
| function Service-InstallAndStart { | |
| if (-Not (Test-Path "$InstallPath\alist.exe")) { | |
| Write-Info "Please install Alist before registering service" $Red | |
| exit 1 | |
| } | |
| # Check if service already exists | |
| $existingService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue | |
| if ($existingService) { | |
| Write-Info "Service '$ServiceName' already exists. Please remove it first or use the existing service." $Yellow | |
| Write-Info "Current service status: $($existingService.Status)" $Green | |
| return | |
| } | |
| Install-NSSM | |
| Write-Info "Registering Windows service $ServiceName ..." $Green | |
| try { | |
| $output = & $nssmPath install $ServiceName "$InstallPath\alist.exe" "server" 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Info "Failed to install service" $Red | |
| if ($output) { | |
| Write-Info "Error details: $output" $Red | |
| # Check for common error patterns | |
| if ($output -match "Access is denied|拒绝访问") { | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } elseif ($output -match "already exists") { | |
| Write-Info "Service already exists. Use option 5 to remove it first." $Yellow | |
| } elseif ($output -match "CreateService") { | |
| Write-Info "Service creation failed. This may be due to insufficient permissions or service name conflicts." $Yellow | |
| } | |
| } | |
| return | |
| } | |
| & $nssmPath set $ServiceName Start SERVICE_AUTO_START | |
| Write-Info "Starting service $ServiceName ..." $Green | |
| $startOutput = & $nssmPath start $ServiceName 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Info "Failed to start service" $Red | |
| if ($startOutput) { | |
| Write-Info "Error details: $startOutput" $Red | |
| if ($startOutput -match "Access is denied|拒绝访问") { | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| } | |
| return | |
| } | |
| Write-Info "First installation, generating random admin username/password..." $Green | |
| try { | |
| $creds = Invoke-AlistAdminRandom | |
| Write-Info "Username: $($creds.Username)" $Green | |
| Write-Info "Password: $($creds.Password)" $Green | |
| } catch { | |
| Write-Info $_.Exception.Message $Red | |
| Write-Info "Random generation failed (service already started). To retry, manually execute: alist.exe admin random" $Yellow | |
| } | |
| Write-Info "Login address: http://$(Get-LocalIP):5244" $Yellow | |
| } catch { | |
| Write-Info "Error during service installation: $($_.Exception.Message)" $Red | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| } | |
| function Service-Start { | |
| Install-NSSM | |
| Write-Info "Starting service $ServiceName ..." $Green | |
| try { | |
| $output = & $nssmPath start $ServiceName 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Info "Failed to start service: $output" $Red | |
| if ($output -match "Access is denied" -or $output -match "拒绝访问") { | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| return | |
| } | |
| Write-Info "Started. Password will not be automatically changed later; to reset manually execute: alist.exe admin random" $Yellow | |
| Write-Info "Login address: http://$(Get-LocalIP):5244" $Yellow | |
| } catch { | |
| Write-Info "Error starting service: $($_.Exception.Message)" $Red | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| } | |
| function Service-Stop { | |
| Install-NSSM | |
| try { | |
| $output = & $nssmPath stop $ServiceName 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Info "Failed to stop service: $output" $Red | |
| if ($output -match "Access is denied" -or $output -match "拒绝访问") { | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| } | |
| } catch { | |
| Write-Info "Error stopping service: $($_.Exception.Message)" $Red | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| } | |
| function Service-Restart { Service-Stop; Start-Sleep -Seconds 2; Service-Start } | |
| function Service-Remove { | |
| Install-NSSM | |
| Write-Info "Deleting Windows service $ServiceName ..." $Yellow | |
| try { | |
| & $nssmPath stop $ServiceName | Out-Null | |
| $output = & $nssmPath remove $ServiceName confirm 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Info "Failed to remove service: $output" $Red | |
| if ($output -match "Access is denied" -or $output -match "拒绝访问") { | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| return | |
| } | |
| Write-Info "Service has been deleted" $Green | |
| } catch { | |
| Write-Info "Error removing service: $($_.Exception.Message)" $Red | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| } | |
| function Service-Status { | |
| Install-NSSM | |
| try { | |
| $output = & $nssmPath status $ServiceName 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Info "Failed to get service status: $output" $Red | |
| if ($output -match "Access is denied" -or $output -match "拒绝访问") { | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| } else { | |
| Write-Info "Service status: $output" $Green | |
| } | |
| } catch { | |
| Write-Info "Error getting service status: $($_.Exception.Message)" $Red | |
| Write-Info "Please run this script as administrator to manage services" $Yellow | |
| } | |
| } | |
| # ----------------------------- | |
| function Show-Menu { | |
| while ($true) { | |
| Clear-Host | |
| Write-Info "`n=== Alist Windows Management Script ===`n" $Green | |
| Write-Info "1. Install Alist" $White | |
| Write-Info "2. Update Alist" $White | |
| Write-Info "3. Uninstall Alist" $White | |
| Write-Info "-------------------------" $White | |
| Write-Info "4. Register and start service (random once after first installation)" $White | |
| Write-Info "5. Delete Windows service" $White | |
| Write-Info "6. Start service (no password change)" $White | |
| Write-Info "7. Stop service" $White | |
| Write-Info "8. Restart service (no password change)" $White | |
| Write-Info "9. View service status" $White | |
| Write-Info "-------------------------" $White | |
| Write-Info "0. Exit" $White | |
| $choice = Read-Host "Please enter option" | |
| switch ($choice) { | |
| "1" { Install-Alist; Pause } | |
| "2" { Install-Alist; Pause } | |
| "3" { Remove-Item -Recurse -Force $InstallPath; Write-Info "Uninstalled"; Pause } | |
| "4" { Service-InstallAndStart; Pause } | |
| "5" { Service-Remove; Pause } | |
| "6" { Service-Start; Pause } | |
| "7" { Service-Stop; Pause } | |
| "8" { Service-Restart; Pause } | |
| "9" { Service-Status; Pause } | |
| "0" { exit 0 } | |
| default { Write-Info "Invalid choice" $Red; Pause } | |
| } | |
| } | |
| } | |
| # ----------------------------- | |
| switch ($Action) { | |
| "install" { Install-Alist } | |
| "update" { Install-Alist } | |
| "uninstall" { Remove-Item -Recurse -Force $InstallPath; Write-Info "Uninstalled" } | |
| "service-install" { Service-InstallAndStart } | |
| "service-remove" { Service-Remove } | |
| "start" { Service-Start } | |
| "stop" { Service-Stop } | |
| "restart" { Service-Restart } | |
| "status" { Service-Status } | |
| "menu" { Show-Menu } | |
| default { Show-Menu } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment