The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

分享一組我在 Azure 建立 Windows VM 都會執行的初始設定腳本

由於我每次在 Azure 上建立 Windows Server 測試用 VM (虛擬機器) 的時候,都需要在開機後執行特定 PowerShell 腳本,這邊我特別分享出來,方便日後不斷維護與管理。想參考使用的人,請自行調整使用。如果有其他覺得推薦的設定,也麻煩留言分享。

首次安裝的 PowerShell 腳本命令

由於 Azure 在手動建立 VM 時,可以透過 Custom Script 自動化所有「系統層級」的安裝設定,所以只要跟「使用者」無關的系統設定、服務安裝、應用程式安裝等等,都可以在安裝的同時自動完成。

以下我直接列出完整 PowerShell 命令,請以系統管理員身份執行:

# 關閉 Internet Explorer 增強安全性設定 (Enhanced Security Configuration)
$AdminIEOff = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}"
Set-ItemProperty -Path $AdminIEOff -Name "IsInstalled" -Value 0
Stop-Process -Name Explorer

# 關閉開機自動啟動伺服器管理員 (Server Manager)
Get-ScheduledTask -TaskName ServerManager | Disable-ScheduledTask -Verbose

# 設定時區為台北標準時間 (Taipei Standard Time)
Set-TimeZone -Name "Taipei Standard Time"

# 調整 ExecutionPolicy 等級到 RemoteSigned
Set-ExecutionPolicy RemoteSigned -Force

# 安裝 PowerShellGet 所需的 NuGet 套件提供者,並設定信任 PSGallery
# https://learn.microsoft.com/en-us/powershell/scripting/gallery/installing-psget
Install-PackageProvider -Name NuGet -Force
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

# 建立 $PROFILE 所需的資料夾
[System.IO.Directory]::CreateDirectory([System.IO.Path]::GetDirectoryName($PROFILE))

# 設定 PowerShell 的 ProgressPreference, TLS 1.2 與 PSReadLine 快速鍵
# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables#progresspreference
@'
# 修正 PowerShell 關閉進度列提示
$ProgressPreference = 'SilentlyContinue'

# 使用 TLS 1.2 進行網路安全連線
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# 設定按下 Ctrl+d 可以退出 PowerShell 執行環境
Set-PSReadlineKeyHandler -Chord ctrl+d -Function ViExit

# 設定按下 Ctrl+w 可以刪除一個單字
Set-PSReadlineKeyHandler -Chord ctrl+w -Function BackwardDeleteWord

# 設定按下 Ctrl+e 可以移動游標到最後面(End)
Set-PSReadlineKeyHandler -Chord ctrl+e -Function EndOfLine

# 設定按下 Ctrl+a 可以移動游標到最前面(Begin)
Set-PSReadlineKeyHandler -Chord ctrl+a -Function BeginningOfLine

function hosts { notepad c:\windows\system32\drivers\etc\hosts }

# 移除內建的 curl 與 wget 命令別名
If (Test-Path Alias:curl) {Remove-Item Alias:curl}
If (Test-Path Alias:wget) {Remove-Item Alias:wget}
'@ | Out-File $PROFILE

# 變更系統語言設定並設定 zh-TW 為顯示語言
$UserLanguageList = New-WinUserLanguageList -Language "en-US"
$UserLanguageList.Add("zh-TW")
Set-WinUserLanguageList -LanguageList $UserLanguageList -Force
Set-WinUILanguageOverride -Language zh-TW

# 安裝 Chocolatey 套件管理器 ( https://chocolatey.org/install )
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

# 安装常用字型
choco install cascadiafonts -y

# 安裝 Microsoft YaHei Mono 字型
Install-Module -Name PSWinGlue -Force
$tmpFolder = New-TemporaryFile | %{ rm $_; mkdir $_ }
Invoke-WebRequest -Uri "https://github.com/doggy8088/MicrosoftYaHeiMono-CP950/blob/master/MicrosoftYaHeiMono-CP950.ttf?raw=true" -OutFile "$tmpFolder\MicrosoftYaHeiMono-CP950.ttf"
Install-Font -Scope System -Path $tmpFolder

# 安裝常用應用程式
choco install googlechrome 7zip notepad2 notepadplusplus git openssh powershell-core unxutils sysinternals wget curl jq vscode nodejs-lts -y

# 因為 Google Chrome 支援自動更新,所以安裝好之後就不用再透過 Chocolatey 進行升級管理
choco uninstall googlechrome -n --skip-autouninstaller

# 更改主機名稱並重開機 ( 假設要更名為 WILLSRV )
# Rename-Computer -NewName WILLSRV -LocalCredential Administrator -PassThru
# Restart-Computer

安裝 IIS + .NET Framework + ASP.NET 執行環境

# 安裝 IIS 服務
Install-WindowsFeature Web-Server,Web-Asp-Net45,NET-Framework-Features -IncludeManagementTools

# 安裝 Web Platform Installer (WebPI)
choco install webpi -y

安裝 ASP.NET Core 2.1 執行環境


# Install the .NET Core 2.1 SDK
Invoke-WebRequest https://download.visualstudio.microsoft.com/download/pr/0d291e03-45d3-441e-8368-9e4b9ab183b4/b93203d22edecfcb17b6b479b54491df/dotnet-sdk-2.1.816-win-x64.exe -outfile $env:temp\dotnet-sdk-2.1.816-win-x64.exe
Start-Process $env:temp\dotnet-sdk-2.1.816-win-x64.exe -ArgumentList '/quiet' -Wait

# Install the .NET Core 2.1 Windows Server Hosting bundle
Invoke-WebRequest https://download.visualstudio.microsoft.com/download/pr/50a47fa0-aff0-44d2-a4ef-0d7c608101e6/3bdef1208816793d6775b6d1912ab81f/dotnet-hosting-2.1.28-win.exe -outfile $env:temp\dotnet-hosting-2.1.28-win.exe
Start-Process $env:temp\dotnet-hosting-2.1.28-win.exe -ArgumentList '/quiet' -Wait

# Restart the web server so that system PATH updates take effect
net stop was /y
net start w3svc

查看安裝版本

dotnet --info

測試 ASP.NET Core 執行

$projectName = "api21"
New-Item -Path $projectName -ItemType Directory
cd $projectName

dotnet new globaljson --sdk-version 2.1.816
dotnet new webapi
dotnet publish -c Release -o C:\Inetpub\TestSite

$folder = Get-Item -Path "C:\Inetpub\TestSite"

Import-Module WebAdministration

# $appPool = New-WebAppPool -Name TestSite
# $appPool.managedRuntimeVersion = ""
# $appPool | Set-Item

New-WebAppPool -Name TestSite
$appPool = Get-Item IIS:\AppPools\TestSite
$appPool.managedPipelineMode="Integrated"
$appPool.managedRuntimeVersion=""
$appPool | set-item

New-Website -Name "TestSite" -HostHeader "testsite" -Port 80 -PhysicalPath $folder  -ApplicationPool "TestSite"
New-WebBinding -Name "TestSite" -HostHeader "localhost" -Port 80 -Protocol "http"

$result = curl.exe -s http://localhost/api/values/1

if ( $result -eq "value" ) {
  Write-Host "TestSite connnection successful!"
} else {
  Write-Warning "TestSite connection failed!!!";
}

Remove-WebSite -Name TestSite
Remove-WebAppPool -Name TestSite

Start-Sleep -Seconds 1
Remove-Item $folder -Recurse -Force -Confirm:$false

cd ..
Remove-Item -Path $projectName -Recurse -Force -Confirm:$false

安裝 ASP.NET Core 3.1 執行環境

# Install the .NET Core 3.1 SDK
Invoke-WebRequest https://download.visualstudio.microsoft.com/download/pr/d0a958a1-50e7-4887-ba3d-3b80e946d7a1/f247ffeae9d13f4ffcc731c7d7b3de45/dotnet-sdk-3.1.410-win-x64.exe -outfile $env:temp\dotnet-sdk-3.1.410-win-x64.exe
Start-Process $env:temp\dotnet-sdk-3.1.410-win-x64.exe -ArgumentList '/quiet' -Wait

# Install the .NET Core 3.1 Windows Server Hosting bundle
Invoke-WebRequest https://download.visualstudio.microsoft.com/download/pr/8bc07709-5179-4e00-97c1-7ba838a17896/e509eaa80062bb3cfc94d64a7bf70afb/dotnet-hosting-3.1.16-win.exe -outfile $env:temp\dotnet-hosting-3.1.16-win.exe
Start-Process $env:temp\dotnet-hosting-3.1.16-win.exe -ArgumentList '/quiet' -Wait

# Restart the web server so that system PATH updates take effect
net stop was /y
net start w3svc

查看安裝版本

dotnet --info

測試 ASP.NET Core 執行

$projectName = "api31"
New-Item -Path $projectName -ItemType Directory
cd $projectName

dotnet new globaljson --sdk-version 3.1.410
dotnet new webapi
dotnet publish -c Release -o C:\Inetpub\TestSite

$folder = Get-Item -Path "C:\Inetpub\TestSite"

Import-Module WebAdministration

# $appPool = New-WebAppPool -Name TestSite
# $appPool.managedRuntimeVersion = ""
# $appPool | Set-Item

New-WebAppPool -Name TestSite
$appPool = Get-Item IIS:\AppPools\TestSite
$appPool.managedPipelineMode="Integrated"
$appPool.managedRuntimeVersion=""
$appPool | set-item

New-Website -Name "TestSite" -HostHeader "testsite" -Port 80 -PhysicalPath $folder  -ApplicationPool "TestSite"
New-WebBinding -Name "TestSite" -HostHeader "localhost" -Port 80 -Protocol "http"

$result = curl.exe -s http://localhost/WeatherForecast

if ( $result -like "*temperatureC*" ) {
  Write-Host "TestSite connnection successful!"
} else {
  Write-Warning "TestSite connection failed!!!";
}

Remove-WebSite -Name TestSite
Remove-WebAppPool -Name TestSite

Start-Sleep -Seconds 1
Remove-Item $folder -Recurse -Force -Confirm:$false

cd ..
Remove-Item -Path $projectName -Recurse -Force -Confirm:$false

安裝 ASP.NET Core 5.0 執行環境

# Install the .NET Core 5.0 SDK
Invoke-WebRequest https://download.visualstudio.microsoft.com/download/pr/c1bfbb13-ad09-459c-99aa-8971582af86e/61553270dd9348d7ba29bacfbb4da7bd/dotnet-sdk-5.0.400-win-x64.exe -outfile $env:temp\dotnet-sdk-5.0.400-win-x64.exe
Start-Process $env:temp\dotnet-sdk-5.0.400-win-x64.exe -ArgumentList '/quiet' -Wait

# Install the .NET Core 5.0 Windows Server Hosting bundle
Invoke-WebRequest https://download.visualstudio.microsoft.com/download/pr/a0f49856-eec9-4962-8d81-b09af6be9435/1d5fc0083b7f7e10ebed181329ca88ae/dotnet-hosting-5.0.9-win.exe -outfile $env:temp\dotnet-hosting-5.0.9-win.exe
Start-Process $env:temp\dotnet-hosting-5.0.9-win.exe -ArgumentList '/quiet' -Wait

# Restart the web server so that system PATH updates take effect
net stop was /y
net start w3svc

查看安裝版本

dotnet --info

測試 ASP.NET Core 執行

$projectName = "api50"
New-Item -Path $projectName -ItemType Directory
cd $projectName

dotnet new globaljson --sdk-version 5.0.301
dotnet new webapi
dotnet publish -c Release -o C:\Inetpub\TestSite

$folder = Get-Item -Path "C:\Inetpub\TestSite"

Import-Module WebAdministration

# $appPool = New-WebAppPool -Name TestSite
# $appPool.managedRuntimeVersion = ""
# $appPool | Set-Item

New-WebAppPool -Name TestSite
$appPool = Get-Item IIS:\AppPools\TestSite
$appPool.managedPipelineMode="Integrated"
$appPool.managedRuntimeVersion=""
$appPool | set-item

New-Website -Name "TestSite" -HostHeader "testsite" -Port 80 -PhysicalPath $folder  -ApplicationPool "TestSite"
New-WebBinding -Name "TestSite" -HostHeader "localhost" -Port 80 -Protocol "http"

$result = curl.exe -s http://localhost/WeatherForecast

if ( $result -like "*temperatureC*" ) {
  Write-Host "TestSite connnection successful!"
} else {
  Write-Warning "TestSite connection failed!!!";
}

Remove-WebSite -Name TestSite
Remove-WebAppPool -Name TestSite

Start-Sleep -Seconds 1
Remove-Item $folder -Recurse -Force -Confirm:$false

cd ..
Remove-Item -Path $projectName -Recurse -Force -Confirm:$false

安裝 Java (Zulu 8 SDK) + Maven + Spring Boot 執行環境

# 先安裝 Zulu8 與 Maven
choco install zulu8 maven -y

# 設定 JAVA_HOME 環境變數
$env:JAVA_HOME = 'C:\Program Files\Zulu\zulu-8'
[System.Environment]::SetEnvironmentVariable('JAVA_HOME','C:\Program Files\Zulu\zulu-8',[System.EnvironmentVariableTarget]::Machine)

通常 Spring Boot 在用 Maven 發行 JAR 檔的時候,已經內建了 Tomcat,所以不太需要特別安裝 Tomcat 服務,如果要手動安裝,可以使用以下命令安裝:

# 安裝 Apache Tomcat 9
choco install tomcat -y

# 啟動 Apache Tomcat 9 服務
Start-Service -Name Tomcat9

# 設定 Tomcat 為開機自動啟動
Set-Service -Name Tomcat9 -StartupType Automatic

安裝 Java 開發環境 (VSCode)

# 安裝 Java 與 Spring Boot 相關擴充套件
code --install-extension vscjava.vscode-java-pack
code --install-extension Pivotal.vscode-boot-dev-pack
code --install-extension redhat.fabric8-analytics
code --install-extension GabrielBB.vscode-lombok
code --install-extension sonarsource.sonarlint-vscode

安裝 Angular 開發環境 (VSCode)

# 安裝 Angular CLI 12 工具
npm i -g @angular/cli@12
ng analytics off

# 安裝 Angular 相關擴充套件
code --install-extension doggy8088.angular-extension-pack
code --install-extension msjsdiag.debugger-for-chrome
code --install-extension esbenp.prettier-vscode

# Angular 12 之後預設已經不用 TSLint 了,所以不一定要裝 TSLint 擴充套件
#code --install-extension ms-vscode.vscode-typescript-tslint-plugin

安裝 .NET 開發環境 (VSCode)

# 安裝 .NET Core Extension Pack 擴充套件
code --install-extension doggy8088.netcore-extension-pack

# 安裝 .NET Interactive Notebooks 擴充套件
code --install-extension ms-dotnettools.dotnet-interactive-vscode

# 安裝 Markdown Extension Pack 擴充套件
code --install-extension doggy8088.markdown-extension-pack

安裝 Hyper-V 相關服務

  1. 安裝相關服務與管理工具

    Add-WindowsFeature Hyper-V,Hyper-V-Tools,Hyper-V-PowerShell -IncludeManagementTools
    
  2. 重開機

    Restart-Computer -Force
    

安裝 Windows Containers 相關服務

注意:安裝 Windows Containers 之前必須先安裝好 Hyper-V 服務。

  1. 安裝 DockerMsftProvider 的過程會提示你要不要安裝 NuGet Provider,這裡必須手動按下 Y 之後繼續。

    Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
    
  2. 使用 PackageManagement PowerShell 模組安裝最新版 Docker。

    Install-Package -Name docker -ProviderName DockerMsftProvider -Force
    
  3. 重開機

    Restart-Computer -Force
    

安裝 Web Deployment Tool 3.6 遠端代理程式

  1. 安裝 IIS 的 Management Service 管理服務 (Remote Administration for IIS Manager)

    # 安裝管理服務
    Install-WindowsFeature Web-Mgmt-Service
    
    # 啟用遠端連線
    Set-Itemproperty -path 'HKLM:\Software\Microsoft\WebManagement\Server' -Name 'EnableRemoteManagement' -value '1'
    
    # 設定自動啟動服務
    Set-Service -Name WMSvc -StartupType Automatic
    Start-Service -Name WMSvc
    
  2. 安裝 Web Deployment Tool 3.6 遠端代理程式

    English (x64)

    Invoke-WebRequest https://download.microsoft.com/download/0/1/D/01DC28EA-638C-4A22-A57B-4CEF97755C6C/WebDeploy_amd64_en-US.msi -outfile $env:temp\WebDeploy_amd64_en-US.msi
    Start-Process $env:temp\WebDeploy_amd64_en-US.msi -ArgumentList 'ADDLOCAL=ALL /qn /norestart LicenseAccepted="0"' -Wait
    

    Chinese (Traditional) (x64)

    Invoke-WebRequest https://download.microsoft.com/download/5/4/4/5441215F-78DB-4686-AD05-3FAD23C406D1/WebDeploy_amd64_zh-TW.msi -outfile $env:temp\WebDeploy_amd64_zh-TW.msi
    Start-Process $env:temp\WebDeploy_amd64_zh-TW.msi -ArgumentList 'ADDLOCAL=ALL /qn /norestart LicenseAccepted="0"' -Wait
    

首次登入的 PowerShell 腳本命令

# 安裝 clink 強化命令提示字元操作
choco install clink -y

# 直接設定 Git 預設 user.name 與 user.email
git config --global user.email "you@example.com"
git config --global user.name "Your Name"

# 設定預設 Git Alias
git config --global alias.ci   commit
git config --global alias.cm   "commit --amend -C HEAD"
git config --global alias.co   checkout
git config --global alias.st   status
git config --global alias.sts  "status -s"
git config --global alias.br   branch
git config --global alias.re   remote
git config --global alias.di   diff
git config --global alias.type "cat-file -t"
git config --global alias.dump "cat-file -p"
git config --global alias.lo   "log --oneline"
git config --global alias.ls   "log --show-signature"
git config --global alias.ll   "log --pretty=format:'%h %ad | %s%d [%Cgreen%an%Creset]' --graph --date=short"
git config --global alias.lg   "log --graph --pretty=format:'%Cred%h%Creset %ad |%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset [%Cgreen%an%Creset]' --abbrev-commit --date=short"
git config --global alias.alias "config --get-regexp ^alias\."
git config --global alias.ignore "!gi() { curl -sL https://www.gitignore.io/api/\$@ ;}; gi"
git config --global alias.iac  "!giac() { git init && git add . && git commit -m 'Initial commit' ;}; giac"
git config --global alias.rc  "!grc() { git reset --hard && git clean -fdx ;}; read -p 'Do you want to run the <<< git reset --hard && git clean -fdx >>> command? (Y/N) ' answer && [[ $answer == [Yy] ]] && grc"

# 設定 git 預設編輯器為 notepad
git config --global core.editor "notepad"

# 設定 git 預設編輯器為 Visual Studio Code
# git config --global core.editor "code --wait"

# 安裝 TortoiseGit 與設定 git tlog 開啟 Tortoise Show log 視窗
choco install tortoisegit winmerge -y
git config --global alias.tlog "!start 'C:\PROGRA~1\TortoiseGit\bin\TortoiseGitProc.exe' /command:log /path:."

# 設定 git status 若有中文不會顯示亂碼
git config --global core.quotepath false

# 設定 git log 若有中文不會顯示亂碼
SETX LC_ALL C.UTF-8 /M

# 安裝 VSCode 繁體中文語言包
code --install-extension MS-CEINTL.vscode-language-pack-zh-hant

相關連結

留言評論