Skip to content

Instantly share code, notes, and snippets.

@SuperPaxxs
Last active May 16, 2023 22:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save SuperPaxxs/e4747ee336eb3920620a71202a6307e8 to your computer and use it in GitHub Desktop.
Save SuperPaxxs/e4747ee336eb3920620a71202a6307e8 to your computer and use it in GitHub Desktop.
#Requires -Version 5
#Requires -RunAsAdministrator
[CmdletBinding()]
param (
[Parameter()]
[ValidateSet("Minimal", "Basic", "Full")]
$Plevel
)
Write-Output "Level: $Plevel"
function Write-Error([string]$message) {
[System.Console]::ForegroundColor = 'red'
[System.Console]::Error.WriteLine("Error:" + $message)
[System.Console]::ResetColor()
}
function Write-Warn([string]$message) {
[Console]::ForegroundColor = 'yellow'
[Console]::Error.WriteLine("WARN: " + $message)
[Console]::ResetColor()
}
function Write-Verbose([string]$message) {
[Console]::ForegroundColor = 'DarkGreen'
[Console]::Error.WriteLine("Verbose: " + $message)
[Console]::ResetColor()
}
function StowFile {
param (
[string]$link,
[string]$target
)
$file = Get-Item $link -ErrorAction SilentlyContinue
$target = (Get-Item $target -ErrorAction SilentlyContinue).FullName
if ($file) {
if ($file.LinkType -ne "SymbolicLink") {
Write-Error "$($file.FullName) already exists and is not a symbolic link"
return
}
elseif ($file.Target -ne $target) {
Write-Error "$($file.FullName) already exists and points to '$($file.Target)', it should point to '$target'"
return
}
else {
Write-Verbose "$($file.FullName) already linked"
return
}
}
else {
$folder = Split-Path $link
if (-not (Test-Path $folder)) {
Write-Verbose "Creating folder $folder"
New-Item -Type Directory -Path $folder
}
Write-Verbose "Creating link $link to $target"
(New-Item -Path $link -ItemType SymbolicLink -Value $target -ErrorAction Continue).Target
}
}
function DownloadFile {
param (
[string]$url,
$target,
[string]$hash = $null
)
if (Test-Path $target) {
Write-Verbose "$target already downloaded."
$IsDownload = $true
}
else {
# download
$IsDownload = $false
try {
$wc = New-Object System.Net.WebClient
$wc.headers.add('Referer', (strip_filename $url))
$wc.Headers.Add('User-Agent', (Get-UserAgent))
$wc.DownloadFile($url, $target)
}
catch {
Write-Error $_
exit
}
}
if ($hash) {
$targethash = Get-FileHash $target -Algorithm "SHA256"
$diff = 0
Compare-Object -ReferenceObject $hash -DifferenceObject $targethash.Hash | ForEach-Object {
if ($_.SilentlyContinue -ne "==") {
$diff += 1
}
}
if ($diff -ne 0) {
if ($IsDownload) {
Write-Error "'$target' does not match expected hash!`nExpected: $hash`nActual: $($targethash.Hash)"
return
}
else {
Write-Error "Downloaded File '$target' from url '$url' does not match expected hash!`nExpected: $hash`nActual: $($targethash.Hash)"
return
}
}
}
if (!$IsDownload) {
Write-Verbose "$target download successful !"
}
}
function SetEnvVariable {
param (
[ValidateSet("Machine ", "Process ", "User")]
[string]$target,
[string]$name,
[string]$value
)
$existing = [System.Environment]::GetEnvironmentVariable($name, $target)
if ($existing) {
Write-Verbose "Environment variable $name already set to '$existing'"
}
else {
Write-Verbose "Adding the $name environment variable to '$value'"
# [System.Environment]::SetEnvironmentVariable($name,$value,$target)
}
}
function EnsureDir ($dir) {
if (!(Test-Path $dir)) {
# Write-Output "Create folder: $dir"
mkdir $dir | Out-Null
}
Resolve-Path $dir
}
function Write-Title ($msg) {
Write-Host ":: " -ForegroundColor DarkGreen -NoNewline
Write-Host $msg -ForegroundColor Yellow
}
function TimeoutPrompt {
param (
$prompt,
$seconds2Wait
)
Write-Host $prompt -NoNewline
$secondsCounter = 0
$subCounter = 0
$timeout = New-TimeSpan -Seconds $seconds2Wait
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
$Host.UI.RawUI.FlushInputBuffer()
while ($stopWatch.Elapsed -lt $timeout) {
Start-Sleep -Milliseconds 10
$subCounter += 10
if ($subCounter -eq 1000) {
$secondsCounter++
$subCounter = 0
Write-Host "." -NoNewline
}
if ($host.UI.RawUI.KeyAvailable) {
$keyPressed = $Host.UI.RawUI.ReadKey("NoEcho, IncludeKeyUp, IncludeKeyDown")
if ($keyPressed.KeyDown -eq $True) {
$Host.UI.RawUI.FlushInputBuffer()
Write-Host "`r`n"
return $true
}
}
}
Write-Host "`r`n"
return $false
}
# scoop
function AddScoopLog {
param (
$message,
[bool]$isAppend = $false,
[string]$file = "$($env:HOMEDRIVE)$($env:HOMEPATH)\scoop.log"
)
if ($isAppend) {
$message >> $file
}
else {
"`n" >> $file
Get-Date -Format 'yyyy/M/d hh:mm:s' >> $file
$message >> $file
}
}
function CheckScoopBucket {
param (
[string]$bucket,
[string]$bucket_url,
[int]$count
)
begin {
if (-not [string]::IsNullOrWhiteSpace($bucket_url)) {
Write-Output "==> $bucket_url"
}
$ins_suc = $true
$log = @()
}
process {
if ($_ -cmatch 'failed|Error|bucket not found|like a valid git|missing|fatal: |try again') {
$log += "ERROR: $_"
$ins_suc = $false
Write-Error $_
}
else {
$log += $_
Write-Output "...$_"
}
}
end {
if ($ins_suc) {
# Write-Host "成功:" -ForegroundColor Cyan -NoNewline
# Write-Host "数据库 $bucket 克隆成功" -BackgroundColor DarkGreen
Write-Verbose "Bucket $bucket added successfully!"
}
else {
# Write-Host "失败:" -ForegroundColor Red -NoNewline
# Write-Host "数据库 $bucket 克隆失败"
Write-Error "Bucket $bucket add failure."
Write-Verbose "Preparing to readd the bucket: $bucket [ $count ]"
Write-Output "==> scoop bucket rm $bucket"
scoop bucket rm $bucket
AddScoopBucket -bu_name $bucket -bu_url $bucket_url -count $count
AddScoopLog -message "Failed bucket:$bucket [ $count ]"
AddScoopLog -message $log -isAppend $true
}
}
}
function CheckScoopInstall {
param (
[string]$appName,
[int]$count,
[bool]$isCore = $false
)
begin {
Write-Output "`nInstall $appName"
$ins_suc = $true
$log = @()
}
process {
if ($_ -cmatch 'aborted|failed|Error|doesn''t exist|Couldn''t find') {
$log += "ERROR: $_"
$ins_suc = $false
Write-Error $_
}
else {
$log += $_
# Write-Host "...."$_
Write-Output "...$_"
}
}
end {
if ($ins_suc) {
# Write-Host "成功:" -ForegroundColor Green -NoNewline
# Write-Host "$appName 安装成功" -BackgroundColor DarkGreen
Write-Verbose "App $appName installed successful!"
}
else {
# Write-Host "失败:" -ForegroundColor Red -NoNewline
# Write-Host "$appName 安装失败"
Write-Error "App $appName install failure."
if (-not $isCore) {
if ($count -le 3) {
Write-Verbose "Preparing for reinstallation $appName [ $count ]"
Write-Output "==> scoop uninstall $appName"
scoop uninstall $appName
InsScoop -appsName $appName -count $count
}
else {
# Write-Host "失败:" -ForegroundColor Red -NoNewline
# Write-Host "安装 $appName 失败超过三次,不再尝试" -ForegroundColor DarkRed -BackgroundColor Yellow
Write-Error "App $appName install failure.(Fail more than three times)"
AddScoopLog -message "Failed Installation: $appName"
AddScoopLog -message $log -isAppend $true
}
}
else {
Write-Verbose "App $appName is core app and it being reinstalled [ $count ]"
scoop uninstall $appName
Write-Output "==> scoop uninstall $appName"
InsScoop -appsName $appName -count $count -isCore $true
}
}
}
}
function AddScoopBucket {
param (
[string]$bu_name,
[string]$bu_url,
[int]$count = 0
)
$count ++
if ([string]::IsNullOrWhiteSpace($bu_url)) {
#钦定
#Write-Host "钦定 $bu_name $count" -BackgroundColor Black
(cmd /c "scoop bucket add $bu_name") | CheckScoopBucket -bucket $bu_name -count $count
#Write-Host "钦定2 $bu_name $count" -BackgroundColor Black
}
else {
#Write-Host "苦逼" -BackgroundColor Black
(cmd /c "scoop bucket add $bu_name `'$bu_url`'") | CheckScoopBucket -bucket $bu_name -count $count -bucket_url $bu_url
}
#Write-Host "Add_Bucket 结束 $bu_name $count" -BackgroundColor Black
}
function InsScoop {
param (
[string]$appsName,
[int]$count = 0,
[bool]$isCore = $false
)
$count ++
(powershell.exe scoop install $appsName) | CheckScoopInstall -appName $appsName -count $count -isCore $isCore
}
# 参数
$LevelMinimal = 1
$LevelBasic = 10
$levelFull = 100
$level = 0
switch ($Plevel) {
"Minimal" { $level = $LevelMinimal }
"Basic" { $level = $LevelBasic }
"Full" { $level = $levelFull }
}
#region environment configuration
# - fw
# - $env:home
Write-Title "Checking the environment"
Write-Output "OS: $((Get-WmiObject Win32_OperatingSystem).osarchitecture)"
if (-not [environment]::Is64BitOperatingSystem) {
Write-Error "Not 64 bit Windows may issue some problems"
# exit
}
if (-not $env:HOME) {
$env:HOME = "$($env:HOMEDRIVE)$($env:HOMEPATH)"
}
#endregion
#region create dir and download dotfiles from github
# - create & tmp
# - unzip master.zip to tmp
# - copy powershell folder to dotfiles
# - remove tmp
Write-Title "Download Paxos` dotfiles"
Write-Output "Creating dotfiles folder..."
$dir = EnsureDir "$env:home\dotfiles"
# download dotfiles zip
$zip_url = "https://github.com/Paxxs/dotfiles-win/archive/master.zip"
$zip_file = "$dir\dotfiles.zip"
Write-Output "Downloading dotfiles in $zip_file"
DownloadFile -url $zip_url -target $zip_file
# Extract zip
Write-Output 'Extracting...'
Add-Type -AssemblyName "System.IO.Compression.FileSystem"
[IO.Compression.ZipFile]::ExtractToDirectory($zip_file, "$dir\_tmp")
Copy-Item "$dir\_tmp\*master\powershell" $dir -Recurse -Force
Remove-Item "$dir\_tmp", $zip_file -Recurse -Force
#endregion
#region powershell & install scoop
# - powershell profile
# - powershell module
# - install scoop and update first
if ($level -ge $LevelMinimal) {
Write-Title "Stow powershell legacy profile"
StowFile $Global:profile "$dir\powershell\Microsoft.PowerShell_profile.ps1"
Write-Title "Install scoop"
$customScoop = TimeoutPrompt "Press key to intervene in scoop installer" 5
if ($customScoop) {
$scoopDir = Read-Host "Where do u want to install (Enter: default)"
if ($scoopDir) {
[System.Environment]::setEnvironmentVariable('SCOOP', $scoopDir, 'User')
$env:SCOOP = $scoopDir # with this we don't need to close and reopen the console
}
$scoopGlobalDir = Read-Host "Set global installation to custom directory (Enter: default)"
if ($scoopGlobalDir) {
[System.Environment]::setEnvironmentVariable('SCOOP_GLOBAL', $scoopGlobalDir, 'Machine')
$env:SCOOP_GLOBAL = $scoopGlobalDir
}
}
Invoke-Expression (new-object net.webclient).downloadstring('https://get.scoop.sh')
Write-Output "configure scoop alias..."
scoop alias add S 'scoop install $args[0]' 'Install apps'
scoop alias add Su 'sudo scoop install $args[0]' 'Install apps (with sudo)'
scoop alias add Ss 'scoop search $args[0]' 'Search available apps'
scoop alias add Si 'scoop info $args[0]' 'Display information about an app'
scoop alias add Sy 'scoop update $args[0]' 'Update apps, or Scoop itself'
scoop alias add Syu 'sudo scoop update *' 'Updates all apps (with sudo)'
scoop alias add R 'scoop uninstall $args[0]' 'Uninstall an app'
scoop alias add Ru 'sudo scoop uninstall $args[0]' 'Uninstall an app (with sudo)'
scoop alias add Fs 'scoop prefix $args[0]' 'Returns the path to the specified app'
Write-Title "Install basic app..."
$app_list = @(
"git",
"7zip",
"aria2",
"fzf",
"sudo1"
# "curl",
# "sed",
# "less",
# "gpg",
# "busybox",
# "openssh"
) | ForEach-Object {
InsScoop -appsName $_
# InsScoop -appsName $_ -isCore $true
}
}
Write-Title "Clone scoop Bucket"
if ($level -ge $LevelMinimal) {
$bucket_list = @(
("Extras bucket for Scoop", "extras"),
("nonportable applications", "nonportable"),
("Cluttered bucket", "MorFans", "https://github.com/Paxxs/Cluttered-bucket.git")
)
$bucket_list | ForEach-Object {
Write-Output "Cloning bucket: "$_[0]
if ([string]::IsNullOrWhiteSpace($_[2])) {
# The official
AddScoopBucket -bu_name $_[1]
}
else {
AddScoopBucket -bu_name $_[1] -bu_url $_[2]
}
}
}
if ($level -ge $LevelBasic) {
$bucket_list = @(
("JAVA Bucket", "java"),
("PHP Bucket", "php"),
("Installing nerd fonts", "nerd-fonts"),
("h404bi`s bucket", "dorado", "https://github.com/h404bi/dorado.git"),
("Ash258 Personal bucket", "Ash258", "https://github.com/Ash258/scoop-Ash258.git"),
("Reverse engineering tools", "retools", "https://github.com/TheCjw/scoop-retools.git"),
("All Sysinternals tools separately", "Sysinternals", "https://github.com/Ash258/Scoop-Sysinternals.git")
)
$bucket_list | ForEach-Object {
Write-Output "Cloning bucket: $($_[0])"
if ([string]::IsNullOrWhiteSpace($_[2])) {
# The official
AddScoopBucket -bu_name $_[1]
}
else {
AddScoopBucket -bu_name $_[1] -bu_url $_[2]
}
}
if ($level -ge $levelFull) {
Write-Output "Cloning bucket: portableapps.com"
AddScoopBucket -bu_name "portableapps" -bu_url "https://github.com/nickbudi/scoop-bucket.git"
}
}
Write-Title "Update & sync scoop"
scoop update
Write-Title "Install PowerShell Module"
if ($level -ge $LevelMinimal) {
Write-Verbose "Install Module: posh-git"
Install-Module posh-git -Scope CurrentUser -Force
}
if ($level -ge $LevelBasic) {
Write-Verbose "Install Module: oh-my-posh"
Install-Module oh-my-posh -Scope CurrentUser -Force
# Administrator rights are required
Write-Verbose "Install Module: Get-ChildItemColor"
Install-Module -AllowClobber Get-ChildItemColor -Force
if(!(Get-Command z -ErrorAction SilentlyContinue)) {
Write-Verbose "Install Module: z"
Install-Module z -AllowClobber -Scope CurrentUser -Force
}
if(!(Get-Module PSFzf)) {
Write-Verbose "Install Module: PSFzf"
Install-Module -Name PSFzf -Force
}
}
#endregion
#region Install Software
# - mini: just core (linux)
# - basic:
# - adb apktool
#endregion
# StowFile -link .\789\666.txt -target ".\123\123.txt"
# DownloadFile "https://github.com/derekmcloughlin/gvimfullscreen_win32/raw/master/gvimfullscreen_64.dll" ".\123\gvimfullscreen_64.dll" "1C83747B67ED73C05D44C1AF8222A860BC5A48B56BF54CD6E21465A2DEB78456"
# Write-Host (Split-Path $MyInvocation.MyCommand.Path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment