Skip to content

Instantly share code, notes, and snippets.

@ilovejs
Created October 26, 2025 06:24
Show Gist options
  • Save ilovejs/005f913dd3dc8eb5a4e8fc4c399f84f1 to your computer and use it in GitHub Desktop.
Save ilovejs/005f913dd3dc8eb5a4e8fc4c399f84f1 to your computer and use it in GitHub Desktop.
alist manager install on windows 10, english version
# 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