Initial commit

This commit is contained in:
2026-04-24 17:41:53 +08:00
commit 7105e8b165
94 changed files with 8141 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Windows 啟用腳本"
Write-Host ""
# 檢查管理員權限
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "[!] 需要管理員權限才能執行此腳本" -ForegroundColor Red
exit 1
}
# 檢查目前啟用狀態
Write-Host "[*] 檢查目前啟用狀態"
$license = Get-CimInstance -ClassName SoftwareLicensingProduct | Where-Object {$_.PartialProductKey}
$currentStatus = $license | Select-Object Name, LicenseStatus, Description, GracePeriodRemaining
Write-Host "目前狀態:$($currentStatus.Name)"
Write-Host "授權狀態:$($currentStatus.LicenseStatus) ($($currentStatus.Description))"
Write-Host "剩餘期間:$($currentStatus.GracePeriodRemaining) 分鐘"
Write-Host ""
if ($currentStatus.LicenseStatus -eq 1) {
Write-Host "[OK] Windows 已經啟用,無需執行啟用程序" -ForegroundColor Green
exit 0
}
# 偵測 Windows 版本並設定對應的 GVLK
Write-Host "[*] 偵測 Windows 版本"
$osInfo = Get-ComputerInfo
$windowsEdition = $osInfo.WindowsProductName
Write-Host "Windows 版本:$windowsEdition"
# 常見 Windows 版本的 GVLK (Generic Volume License Keys)
$gvlkKeys = @{
'Windows 10 Pro' = 'W269N-WFGWX-YVC9B-4J6C9-T83GX'
'Windows 10 Professional' = 'W269N-WFGWX-YVC9B-4J6C9-T83GX'
'Windows 10 Home' = 'TX9XD-98N7V-6WMQ6-BX7FG-H8Q99'
'Windows 10 Enterprise' = 'NPPR9-FWDCX-D2C8J-H872K-2YT43'
'Windows 11 Pro' = 'W269N-WFGWX-YVC9B-4J6C9-T83GX'
'Windows 11 Professional' = 'W269N-WFGWX-YVC9B-4J6C9-T83GX'
'Windows 11 Home' = 'TX9XD-98N7V-6WMQ6-BX7FG-H8Q99'
'Windows 11 Enterprise' = 'NPPR9-FWDCX-D2C8J-H872K-2YT43'
}
$productKey = $null
foreach ($edition in $gvlkKeys.Keys) {
if ($windowsEdition -like "*$edition*") {
$productKey = $gvlkKeys[$edition]
break
}
}
if (-not $productKey) {
# 預設使用 Pro 版本的金鑰
$productKey = 'W269N-WFGWX-YVC9B-4J6C9-T83GX'
Write-Host "[*] 無法偵測到確切版本,使用 Pro 版本金鑰" -ForegroundColor Yellow
}
Write-Host "使用產品金鑰:$productKey"
Write-Host ""
# KMS 伺服器清單
$kmsServers = @(
'kms.digiboy.ir',
'kms8.msguides.com',
'kms.03k.org',
'kms.chinancce.com'
)
Write-Host "[*] 開始啟用程序"
# 1. 安裝產品金鑰
Write-Host "[1/3] 安裝產品金鑰"
try {
& slmgr /ipk $productKey
Start-Sleep -Seconds 3
Write-Host " 產品金鑰安裝成功"
} catch {
Write-Host " [!] 產品金鑰安裝失敗: $($_.Exception.Message)" -ForegroundColor Red
}
# 2. 嘗試 KMS 伺服器
Write-Host "[2/3] 設定 KMS 伺服器並啟用"
$activated = $false
foreach ($kmsServer in $kmsServers) {
Write-Host " 嘗試 KMS 伺服器:$kmsServer"
try {
# 設定 KMS 伺服器
& slmgr /skms $kmsServer
Start-Sleep -Seconds 2
# 執行啟用
& slmgr /ato
Start-Sleep -Seconds 5
# 檢查啟用結果
$newStatus = Get-CimInstance -ClassName SoftwareLicensingProduct | Where-Object {$_.PartialProductKey}
if ($newStatus.LicenseStatus -eq 1) {
$activated = $true
Write-Host " [OK] 啟用成功!" -ForegroundColor Green
break
} else {
Write-Host " 啟用未成功,嘗試下一個伺服器"
}
} catch {
Write-Host " KMS 伺服器連線失敗: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
# 3. 驗證啟用結果
Write-Host "[3/3] 驗證啟用結果"
$finalStatus = Get-CimInstance -ClassName SoftwareLicensingProduct | Where-Object {$_.PartialProductKey}
Write-Host ""
Write-Host "=== 啟用結果 ==="
Write-Host "版本:$($finalStatus.Name)"
Write-Host "狀態:$($finalStatus.LicenseStatus) ($($finalStatus.Description))"
Write-Host "剩餘期間:$($finalStatus.GracePeriodRemaining) 分鐘 (約 $([math]::Round($finalStatus.GracePeriodRemaining / 1440, 1)) 天)"
if ($finalStatus.LicenseStatus -eq 1) {
Write-Host ""
Write-Host "[OK] Windows 啟用成功!" -ForegroundColor Green
Write-Host "KMS 啟用有效期約 180 天,會自動續期。"
exit 0
} else {
Write-Host ""
Write-Host "[!] Windows 啟用失敗" -ForegroundColor Red
Write-Host "請檢查網路連線或嘗試其他啟用方法。"
exit 1
}

View File

@@ -0,0 +1,127 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
param(
[string]$TargetUser = 'User'
)
Write-Host "[*] Adding desktop icons for user: $TargetUser"
# Icon GUIDs
$computerGUID = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" # This PC / Computer
$controlPanelGUID = "{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}" # Control Panel
$recycleGUID = "{645FF040-5081-101B-9F08-00AA002F954E}" # Recycle Bin
# Check if user exists
$userProfile = "C:\Users\$TargetUser"
if (-not (Test-Path $userProfile)) {
Write-Host "[!] User profile not found: $userProfile" -ForegroundColor Red
exit 1
}
Write-Host "[*] Target user profile: $userProfile"
# Check if user is currently logged in (hive already loaded)
$hivePath = "HKU:\${TargetUser}_Classes"
$userSID = $null
try {
# Get user SID
$user = New-Object System.Security.Principal.NTAccount($TargetUser)
$userSID = $user.Translate([System.Security.Principal.SecurityIdentifier]).Value
Write-Host "[*] User SID: $userSID"
} catch {
Write-Host "[!] Could not get user SID: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
# Check if user hive is already loaded
$hiveLoaded = $false
$userHivePath = "HKU:\$userSID"
if (Test-Path $userHivePath) {
Write-Host "[*] User hive already loaded"
$hiveLoaded = $true
} else {
Write-Host "[*] Loading user hive"
$ntUserPath = "$userProfile\NTUSER.DAT"
if (-not (Test-Path $ntUserPath)) {
Write-Host "[!] NTUSER.DAT not found: $ntUserPath" -ForegroundColor Red
exit 1
}
try {
& reg load "HKU\$TargetUser" "$ntUserPath"
if ($LASTEXITCODE -eq 0) {
Write-Host " User hive loaded successfully"
$userHivePath = "HKU:\$TargetUser"
} else {
Write-Host "[!] Failed to load user hive" -ForegroundColor Red
exit 1
}
} catch {
Write-Host "[!] Error loading user hive: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
}
# Desktop icons registry paths
$desktopIconsPath = "$userHivePath\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"
$classicIconsPath = "$userHivePath\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu"
Write-Host "[*] Setting up desktop icons"
# Ensure registry paths exist
foreach ($path in @($desktopIconsPath, $classicIconsPath)) {
if (-not (Test-Path $path)) {
New-Item -Path $path -Force | Out-Null
Write-Host " Created registry path: $path"
}
}
# Enable icons (0 = show, 1 = hide)
$iconsToEnable = @{
"Computer (This PC)" = $computerGUID
"Control Panel" = $controlPanelGUID
"Recycle Bin" = $recycleGUID
}
foreach ($iconName in $iconsToEnable.Keys) {
$guid = $iconsToEnable[$iconName]
# Set for both NewStartPanel and ClassicStartMenu
Set-ItemProperty -Path $desktopIconsPath -Name $guid -Value 0 -Type DWord
Set-ItemProperty -Path $classicIconsPath -Name $guid -Value 0 -Type DWord
Write-Host " Enabled: $iconName"
}
# Unload user hive if we loaded it
if (-not $hiveLoaded) {
Write-Host "[*] Unloading user hive"
try {
& reg unload "HKU\$TargetUser"
if ($LASTEXITCODE -eq 0) {
Write-Host " User hive unloaded successfully"
} else {
Write-Host "[!] Warning: Failed to unload user hive cleanly"
}
} catch {
Write-Host "[!] Warning: Error unloading user hive: $($_.Exception.Message)"
}
}
Write-Host ""
Write-Host "[OK] Desktop icons configured for user: $TargetUser"
Write-Host ""
Write-Host "The following icons will appear on $TargetUser's desktop:"
Write-Host "- This PC (Computer)"
Write-Host "- Control Panel"
Write-Host "- Recycle Bin"
Write-Host ""
Write-Host "Changes will take effect when $TargetUser logs in next time."
Write-Host "If $TargetUser is currently logged in, they may need to:"
Write-Host "1. Log out and log back in"
Write-Host "2. Or restart the computer"
Write-Host "3. Or right-click desktop > Refresh"

View File

@@ -0,0 +1,100 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Adding Computer and Control Panel icons to desktop"
# Registry paths for desktop icons
$desktopIconsPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"
$classicIconsPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu"
# Icon GUIDs
$computerGUID = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" # This PC / Computer
$controlPanelGUID = "{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}" # Control Panel
$recycleGUID = "{645FF040-5081-101B-9F08-00AA002F954E}" # Recycle Bin
$userFilesGUID = "{59031a47-3f72-44a7-89c5-5595fe6b30ee}" # User Files
$networkGUID = "{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}" # Network
Write-Host "[*] Ensuring registry paths exist"
# Ensure registry paths exist
if (-not (Test-Path $desktopIconsPath)) {
New-Item -Path $desktopIconsPath -Force | Out-Null
Write-Host " Created registry path: NewStartPanel"
}
if (-not (Test-Path $classicIconsPath)) {
New-Item -Path $classicIconsPath -Force | Out-Null
Write-Host " Created registry path: ClassicStartMenu"
}
Write-Host "[*] Current desktop icon status"
# Check current status
$currentIcons = @{
"Computer" = $computerGUID
"Control Panel" = $controlPanelGUID
"Recycle Bin" = $recycleGUID
"User Files" = $userFilesGUID
"Network" = $networkGUID
}
foreach ($iconName in $currentIcons.Keys) {
$guid = $currentIcons[$iconName]
$value = Get-ItemProperty -Path $desktopIconsPath -Name $guid -ErrorAction SilentlyContinue
if ($value) {
$status = if ($value.$guid -eq 0) { "Visible" } else { "Hidden" }
} else {
$status = "Default (Hidden)"
}
Write-Host " $iconName : $status"
}
Write-Host "[*] Enabling Computer and Control Panel icons"
# Enable Computer icon (This PC)
Set-ItemProperty -Path $desktopIconsPath -Name $computerGUID -Value 0
Set-ItemProperty -Path $classicIconsPath -Name $computerGUID -Value 0
Write-Host " Computer (This PC) icon enabled"
# Enable Control Panel icon
Set-ItemProperty -Path $desktopIconsPath -Name $controlPanelGUID -Value 0
Set-ItemProperty -Path $classicIconsPath -Name $controlPanelGUID -Value 0
Write-Host " Control Panel icon enabled"
# Keep Recycle Bin enabled (it's probably already enabled)
Set-ItemProperty -Path $desktopIconsPath -Name $recycleGUID -Value 0
Set-ItemProperty -Path $classicIconsPath -Name $recycleGUID -Value 0
Write-Host " Recycle Bin icon ensured enabled"
Write-Host "[*] Refreshing desktop"
# Refresh the desktop to apply changes
try {
# Method 1: Use rundll32 to refresh
& rundll32.exe user32.dll,UpdatePerUserSystemParameters
# Method 2: Refresh explorer (more reliable)
$explorerProcesses = Get-Process explorer -ErrorAction SilentlyContinue
if ($explorerProcesses) {
Write-Host " Restarting Explorer to apply changes..."
Stop-Process -Name explorer -Force
Start-Sleep -Seconds 2
Start-Process explorer
Write-Host " Explorer restarted"
}
} catch {
Write-Host " [!] Could not restart Explorer: $($_.Exception.Message)"
Write-Host " Please restart Explorer manually or reboot to see changes"
}
Write-Host ""
Write-Host "[OK] Desktop icons setup complete!"
Write-Host ""
Write-Host "Enabled icons:"
Write-Host "- This PC (Computer)"
Write-Host "- Control Panel"
Write-Host "- Recycle Bin"
Write-Host ""
Write-Host "If icons don't appear immediately:"
Write-Host "1. Right-click desktop > Refresh"
Write-Host "2. Or restart the computer"

View File

@@ -0,0 +1,77 @@
param(
[string]$TargetUser = 'user'
)
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
# Resolve target user's SID
try {
$sid = (New-Object System.Security.Principal.NTAccount($TargetUser)).Translate([System.Security.Principal.SecurityIdentifier]).Value
} catch {
throw "Unable to resolve SID for user '$TargetUser': $_"
}
$ntuserDat = "C:\Users\$TargetUser\NTUSER.DAT"
$hivePath = "HKEY_USERS\$sid"
$regBase = "Registry::$hivePath"
$hiveLoaded = Test-Path $regBase
$weLoaded = $false
if (-not $hiveLoaded) {
if (-not (Test-Path $ntuserDat)) { throw "NTUSER.DAT not found: $ntuserDat" }
Write-Host "[*] User hive not loaded. Loading $ntuserDat as $hivePath"
& reg.exe load $hivePath $ntuserDat | Out-Null
if ($LASTEXITCODE -ne 0) { throw "reg load failed ($LASTEXITCODE). Is the user logged in?" }
$weLoaded = $true
} else {
Write-Host "[*] User hive already loaded at $hivePath (user may be logged in)"
}
function Set-UV {
param([string]$SubPath, [string]$Name, $Value, [string]$Type = 'DWord')
$full = "$regBase\$SubPath"
if (-not (Test-Path $full)) { New-Item -Path $full -Force | Out-Null }
New-ItemProperty -Path $full -Name $Name -Value $Value -PropertyType $Type -Force | Out-Null
Write-Host (" {0}\{1} = {2}" -f $SubPath, $Name, $Value)
}
try {
Write-Host "[*] Applying Explorer / Taskbar / Theme settings"
Set-UV 'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' 'HideFileExt' 0
Set-UV 'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' 'Hidden' 1
Set-UV 'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' 'TaskbarAl' 0
Set-UV 'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' 'ShowTaskViewButton' 0
Set-UV 'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' 'LaunchTo' 1
Set-UV 'Software\Microsoft\Windows\CurrentVersion\Themes\Personalize' 'AppsUseLightTheme' 0
Set-UV 'Software\Microsoft\Windows\CurrentVersion\Themes\Personalize' 'SystemUsesLightTheme' 0
Write-Host "[*] Applying search / Bing / highlights settings"
Set-UV 'Software\Policies\Microsoft\Windows\Explorer' 'DisableSearchBoxSuggestions' 1
Set-UV 'Software\Microsoft\Windows\CurrentVersion\SearchSettings' 'IsDynamicSearchBoxEnabled' 0
Write-Host "[*] Applying Spotlight settings"
Set-UV 'Software\Policies\Microsoft\Windows\CloudContent' 'DisableSpotlightCollectionOnDesktop' 1
Set-UV 'Software\Policies\Microsoft\Windows\CloudContent' 'DisableWindowsSpotlightFeatures' 1
Write-Host ""
Write-Host "[OK] UI settings written to $hivePath"
}
finally {
if ($weLoaded) {
# Release any handles we might be holding on to
[GC]::Collect(); [GC]::WaitForPendingFinalizers()
[GC]::Collect(); [GC]::WaitForPendingFinalizers()
Start-Sleep -Milliseconds 500
& reg.exe unload $hivePath 2>&1 | Out-Null
if ($LASTEXITCODE -eq 0) {
Write-Host "[*] Unloaded $hivePath"
} else {
Write-Host "[!] reg unload returned $LASTEXITCODE — hive may still be held. Check with: reg query HKU\$sid"
}
}
}
Write-Host ""
Write-Host "Note: changes take effect when '$TargetUser' next logs in, or after explorer.exe restart if already logged in."

View File

@@ -0,0 +1,145 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'SilentlyContinue'
function Section($title) {
Write-Host ''
Write-Host ('=' * 8) $title ('=' * 8) -ForegroundColor Green
}
function StatusCheck($description, $condition, $recommendation = "") {
$status = if ($condition) { "✅ OK" } else { "❌ NOT OK" }
Write-Host "$description`: $status" -ForegroundColor $(if ($condition) { "Green" } else { "Red" })
if (-not $condition -and $recommendation) {
Write-Host " 💡 $recommendation" -ForegroundColor Yellow
}
}
Section "WinRM Service Status"
$winrmService = Get-Service -Name WinRM -ErrorAction SilentlyContinue
if ($winrmService) {
StatusCheck "WinRM Service Exists" $true
StatusCheck "WinRM Service Running" ($winrmService.Status -eq "Running") "Run: Start-Service WinRM"
StatusCheck "WinRM Service Startup" ($winrmService.StartType -eq "Automatic") "Run: Set-Service WinRM -StartupType Automatic"
} else {
StatusCheck "WinRM Service Exists" $false "WinRM service not found - this is unusual for Windows 10/11"
}
Section "WinRM Configuration"
try {
$winrmConfig = winrm get winrm/config 2>$null
StatusCheck "WinRM Config Accessible" ($winrmConfig -ne $null) "Run: winrm quickconfig -quiet"
if ($winrmConfig) {
# Parse basic config
$allowUnencrypted = ($winrmConfig | Select-String "AllowUnencrypted = true") -ne $null
$basicAuth = ($winrmConfig | Select-String "Basic = true") -ne $null
StatusCheck "Allow Unencrypted" $allowUnencrypted "For testing: winrm set winrm/config/service @{AllowUnencrypted=`"true`"}"
StatusCheck "Basic Auth Enabled" $basicAuth "Run: winrm set winrm/config/service/auth @{Basic=`"true`"}"
}
} catch {
StatusCheck "WinRM Config Accessible" $false "Run: winrm quickconfig -quiet"
}
Section "WinRM Listeners"
try {
$listeners = winrm enumerate winrm/config/listener 2>$null
$httpListener = ($listeners | Select-String "Transport = HTTP") -ne $null
$httpsListener = ($listeners | Select-String "Transport = HTTPS") -ne $null
StatusCheck "HTTP Listener (Port 5985)" $httpListener "Run: winrm create winrm/config/listener?Address=*+Transport=HTTP"
StatusCheck "HTTPS Listener (Port 5986)" $httpsListener "Optional: Create HTTPS listener for secure connection"
if ($listeners) {
Write-Host "`nListener Details:"
Write-Host $listeners
}
} catch {
StatusCheck "WinRM Listeners Available" $false "Run: winrm quickconfig -quiet"
}
Section "PowerShell Remoting"
try {
$psSessionConfig = Get-PSSessionConfiguration -Name Microsoft.PowerShell -ErrorAction SilentlyContinue
StatusCheck "PowerShell Remoting Enabled" ($psSessionConfig -ne $null) "Run: Enable-PSRemoting -Force"
if ($psSessionConfig) {
StatusCheck "PS Remoting Not Disabled" ($psSessionConfig.Permission -notmatch "AccessDenied") "Check session configuration permissions"
}
} catch {
StatusCheck "PowerShell Remoting Accessible" $false "Run: Enable-PSRemoting -Force"
}
Section "Firewall Rules"
$firewallRules = Get-NetFirewallRule -DisplayGroup "*Remote Management*" -ErrorAction SilentlyContinue
$winrmHttpRule = $firewallRules | Where-Object { $_.DisplayName -match "Windows Remote Management.*HTTP" -and $_.Enabled -eq $true }
$winrmHttpsRule = $firewallRules | Where-Object { $_.DisplayName -match "Windows Remote Management.*HTTPS" -and $_.Enabled -eq $true }
StatusCheck "WinRM HTTP Firewall Rule" ($winrmHttpRule -ne $null) "Run: Enable-NetFirewallRule -DisplayGroup 'Windows Remote Management'"
StatusCheck "WinRM HTTPS Firewall Rule" ($winrmHttpsRule -ne $null) "Optional for HTTPS"
# Show current firewall rules
if ($firewallRules) {
Write-Host "`nCurrent WinRM Firewall Rules:"
$firewallRules | Select-Object DisplayName, Enabled, Direction, Action | Format-Table -AutoSize
}
Section "Network Connectivity Test"
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$computerName = $env:COMPUTERNAME
$ipAddresses = Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notmatch 'Loopback' } | Select-Object -ExpandProperty IPAddress
Write-Host "Current User: $currentUser"
Write-Host "Computer Name: $computerName"
Write-Host "IP Addresses: $($ipAddresses -join ', ')"
# Test local WinRM connectivity
try {
$testSession = New-PSSession -ComputerName localhost -ErrorAction Stop
Remove-PSSession $testSession -ErrorAction SilentlyContinue
StatusCheck "Local WinRM Test" $true
} catch {
StatusCheck "Local WinRM Test" $false "Local connection failed: $($_.Exception.Message)"
}
Section "Authentication Methods"
try {
$authConfig = winrm get winrm/config/service/auth 2>$null
if ($authConfig) {
Write-Host "Available Authentication Methods:"
Write-Host $authConfig
}
} catch {
Write-Host "Could not retrieve authentication configuration"
}
Section "Recommended Actions"
Write-Host "If WinRM is not properly configured, run these commands as Administrator:" -ForegroundColor Cyan
Write-Host ""
Write-Host "# Enable PowerShell Remoting and WinRM" -ForegroundColor Yellow
Write-Host "Enable-PSRemoting -Force"
Write-Host "winrm quickconfig -quiet"
Write-Host ""
Write-Host "# Configure basic authentication (for testing)" -ForegroundColor Yellow
Write-Host "winrm set winrm/config/service/auth '@{Basic=`"true`"}'"
Write-Host "winrm set winrm/config/service '@{AllowUnencrypted=`"true`"}'"
Write-Host ""
Write-Host "# Enable firewall rules" -ForegroundColor Yellow
Write-Host "Enable-NetFirewallRule -DisplayGroup 'Windows Remote Management'"
Write-Host ""
Write-Host "# Test from remote machine:" -ForegroundColor Yellow
Write-Host "Test-WSMan -ComputerName $($ipAddresses[0]) -Authentication Basic"
Section "Current Status Summary"
$winrmRunning = $winrmService -and ($winrmService.Status -eq "Running")
$configExists = try { winrm get winrm/config >$null 2>&1; $true } catch { $false }
$listenersExist = try { winrm enumerate winrm/config/listener >$null 2>&1; $true } catch { $false }
$firewallEnabled = ($winrmHttpRule -ne $null)
if ($winrmRunning -and $configExists -and $listenersExist -and $firewallEnabled) {
Write-Host "🎉 WinRM appears to be ready for remote connections!" -ForegroundColor Green
} elseif ($winrmRunning -and $configExists) {
Write-Host "⚠️ WinRM is partially configured - may need firewall or listener setup" -ForegroundColor Yellow
} else {
Write-Host "❌ WinRM requires configuration before remote access will work" -ForegroundColor Red
}

View File

@@ -0,0 +1,119 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Cleaning up download shortcuts and fixing winget"
# Remove download shortcuts
$desktopPath = "C:\Users\User\Desktop"
$shortcutsToRemove = @(
"Download-Chrome.url",
"Download-7-Zip.url",
"Download-AnyDesk.url",
"Download-LINE.url",
"Download-Adobe-Reader.url",
"Installation-Instructions.txt"
)
Write-Host "[1] Removing download shortcuts..."
foreach ($shortcut in $shortcutsToRemove) {
$filePath = Join-Path $desktopPath $shortcut
if (Test-Path $filePath) {
Remove-Item $filePath -Force
Write-Host " Removed: $shortcut"
}
}
Write-Host "[2] Checking winget status..."
# Check if winget is available
try {
$wingetVersion = & winget --version 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] winget is available: $wingetVersion"
} else {
Write-Host " [!] winget command failed"
throw "winget not working"
}
} catch {
Write-Host " [!] winget not found or not working"
Write-Host "[3] Installing/Updating winget..."
# Method 1: Try to install App Installer (contains winget)
try {
Write-Host " Attempting to install Microsoft App Installer..."
# Download and install App Installer
$appInstallerUrl = "https://github.com/microsoft/winget-cli/releases/latest/download/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
$downloadPath = "$env:TEMP\AppInstaller.msixbundle"
Invoke-WebRequest -Uri $appInstallerUrl -OutFile $downloadPath -UseBasicParsing
# Install the package
Add-AppxPackage -Path $downloadPath
Write-Host " [OK] App Installer installed"
# Clean up
Remove-Item $downloadPath -Force -ErrorAction SilentlyContinue
} catch {
Write-Host " [!] Failed to install App Installer: $($_.Exception.Message)"
# Method 2: Try alternative approach
Write-Host " Trying alternative winget installation..."
try {
# Check Windows version and suggest manual installation
$osVersion = [System.Environment]::OSVersion.Version
Write-Host " Windows Version: $osVersion"
if ($osVersion.Major -ge 10 -and $osVersion.Build -ge 17763) {
Write-Host " [INFO] Windows version supports winget"
Write-Host " [ACTION] Manual steps required:"
Write-Host " 1. Open Microsoft Store"
Write-Host " 2. Search for 'App Installer'"
Write-Host " 3. Install/Update App Installer"
Write-Host " 4. Restart PowerShell session"
} else {
Write-Host " [!] Windows version may not support winget"
Write-Host " Consider updating Windows or using manual installation"
}
} catch {
Write-Host " [!] Could not determine Windows version"
}
}
}
Write-Host "[4] Final winget verification..."
# Wait a moment and test again
Start-Sleep -Seconds 3
try {
$wingetTest = & winget list --source winget 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] winget is working properly"
Write-Host " [INFO] Ready for application installation"
# Test a simple winget operation
Write-Host "[5] Testing winget functionality..."
$testResult = & winget search "7zip.7zip" 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] winget search working"
} else {
Write-Host " [!] winget search failed, may need source configuration"
}
} else {
Write-Host " [!] winget still not working properly"
Write-Host " Output: $wingetTest"
}
} catch {
Write-Host " [!] winget verification failed: $($_.Exception.Message)"
}
Write-Host ""
Write-Host "Cleanup and winget setup completed!"
Write-Host "If winget is working, we can proceed with automated installation."

View File

@@ -0,0 +1,112 @@
param(
[string]$TargetUser = 'User'
)
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
# Resolve target user SID
$sid = (New-Object System.Security.Principal.NTAccount($TargetUser)).Translate([System.Security.Principal.SecurityIdentifier]).Value
$hivePath = "HKEY_USERS\$sid"
$regBase = "Registry::$hivePath"
$ntuserDat = "C:\Users\$TargetUser\NTUSER.DAT"
$weLoaded = $false
if (-not (Test-Path $regBase)) {
if (-not (Test-Path $ntuserDat)) {
# Try alternate casing (NTFS is case-insensitive but PS sees the literal case)
$alt = Get-Item "C:\Users\*" | Where-Object { $_.Name -ieq $TargetUser } | Select-Object -First 1
if ($alt) { $ntuserDat = Join-Path $alt.FullName 'NTUSER.DAT' }
}
if (-not (Test-Path $ntuserDat)) { throw "NTUSER.DAT not found for $TargetUser" }
Write-Host "[*] Loading $ntuserDat"
& reg.exe load $hivePath $ntuserDat | Out-Null
if ($LASTEXITCODE -ne 0) { throw "reg load failed" }
$weLoaded = $true
}
try {
# ---------- 1. Add en-US to language list as FIRST language (default) ----------
# This targets the CURRENT user running this script. For the target user, we
# write the preload keys directly into their hive.
Write-Host "[*] Setting target user's keyboard preload (en-US first, zh-TW second)"
$preloadPath = "$regBase\Keyboard Layout\Preload"
if (-not (Test-Path $preloadPath)) { New-Item -Path $preloadPath -Force | Out-Null }
# 00000409 = English (US); 00000404 = Chinese (Traditional, Taiwan)
New-ItemProperty -Path $preloadPath -Name '1' -Value '00000409' -PropertyType String -Force | Out-Null
New-ItemProperty -Path $preloadPath -Name '2' -Value '00000404' -PropertyType String -Force | Out-Null
$substitutesPath = "$regBase\Keyboard Layout\Substitutes"
if (Test-Path $substitutesPath) {
Remove-Item $substitutesPath -Recurse -Force
}
# ---------- 2. Set Chinese IME to default to English (alphanumeric) mode ----------
Write-Host "[*] Setting Microsoft Bopomofo to default English mode"
$chtPath = "$regBase\Software\Microsoft\InputMethod\Settings\CHT"
if (-not (Test-Path $chtPath)) { New-Item -Path $chtPath -Force | Out-Null }
# 0 = default English mode, 1 = default Chinese mode
New-ItemProperty -Path $chtPath -Name 'Enable Default Input Mode' -Value 0 -PropertyType DWord -Force | Out-Null
# ---------- 3. Set Bopomofo's Chinese/English switch hotkey to Ctrl+Space ----------
# Microsoft Bopomofo exposes this option in its Settings UI:
# Shift (default) | Ctrl + Space | Caps Lock
# The registry value is 'Enable Ctrl Space Switch Chinese English' (boolean-ish).
Write-Host "[*] Setting Ctrl+Space as Chinese/English switch for MS Bopomofo"
New-ItemProperty -Path $chtPath -Name 'Enable Ctrl Space Switch Chinese English' -Value 1 -PropertyType DWord -Force | Out-Null
# Also disable Shift as the switch (optional, prevents confusion)
New-ItemProperty -Path $chtPath -Name 'Enable Shift Chinese English' -Value 0 -PropertyType DWord -Force | Out-Null
# ---------- 4. Disable OS-level Ctrl+Shift / Alt+Shift language toggle ----------
# So Ctrl+Space is the only thing that triggers language switching.
Write-Host "[*] Disabling OS-level Language/Layout hotkeys"
$togglePath = "$regBase\Keyboard Layout\Toggle"
if (-not (Test-Path $togglePath)) { New-Item -Path $togglePath -Force | Out-Null }
# Values: 1 = Ctrl+Shift, 2 = Left Alt+Shift, 3 = Grave Accent, 4 = Not assigned
New-ItemProperty -Path $togglePath -Name 'Hotkey' -Value '3' -PropertyType String -Force | Out-Null
New-ItemProperty -Path $togglePath -Name 'Language Hotkey' -Value '3' -PropertyType String -Force | Out-Null
New-ItemProperty -Path $togglePath -Name 'Layout Hotkey' -Value '3' -PropertyType String -Force | Out-Null
# ---------- 5. Tell the language subsystem en-US is the default ----------
# Remove user-profile language forcing so that Preload order is respected
$userProfileLangPath = "$regBase\Control Panel\International\User Profile"
if (Test-Path $userProfileLangPath) {
$langs = (Get-ItemProperty $userProfileLangPath).Languages
if ($langs) {
# Prepend en-US to the language list
$newLangs = @('en-US') + ($langs | Where-Object { $_ -ne 'en-US' })
New-ItemProperty -Path $userProfileLangPath -Name 'Languages' -Value $newLangs -PropertyType MultiString -Force | Out-Null
Write-Host "[*] Updated user-profile language list: $($newLangs -join ', ')"
}
}
# Ensure per-language subkeys exist
$enUSPath = "$userProfileLangPath\en-US"
if (-not (Test-Path $enUSPath)) { New-Item -Path $enUSPath -Force | Out-Null }
# CachedLanguageName is cosmetic but prevents re-detection flakiness
New-ItemProperty -Path $enUSPath -Name '0409:00000409' -Value 1 -PropertyType DWord -Force | Out-Null
Write-Host ""
Write-Host "[OK] IME configured for '$TargetUser'"
Write-Host "Summary:"
Write-Host " - Default input: English (US) keyboard"
Write-Host " - Microsoft Bopomofo: starts in English (alphanumeric) mode"
Write-Host " - Ctrl+Space: toggles between English / Chinese within Bopomofo"
Write-Host " - OS-level language hotkeys (Ctrl+Shift / Alt+Shift): disabled"
}
finally {
if ($weLoaded) {
[GC]::Collect(); [GC]::WaitForPendingFinalizers()
[GC]::Collect(); [GC]::WaitForPendingFinalizers()
Start-Sleep -Milliseconds 500
& reg.exe unload $hivePath 2>&1 | Out-Null
if ($LASTEXITCODE -eq 0) { Write-Host "[*] Unloaded $hivePath" }
else { Write-Host "[!] reg unload returned $LASTEXITCODE" }
}
}
Write-Host ""
Write-Host "Note: Settings apply on '$TargetUser' next login. If Bopomofo doesn't pick up"
Write-Host "Ctrl+Space automatically, open 'Microsoft Bopomofo settings' -> 'Keys' and"
Write-Host "confirm 'Chinese/English switch' = Ctrl+Space (this registry write should do it)."

View File

@@ -0,0 +1,94 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
Write-Host "[*] Creating download shortcuts for essential applications"
$desktopPath = "C:\Users\User\Desktop"
# Application download links
$apps = @(
@{
Name = "Google Chrome"
Url = "https://dl.google.com/chrome/install/GoogleChromeStandaloneEnterprise64.msi"
FileName = "Download-Chrome.url"
},
@{
Name = "7-Zip"
Url = "https://www.7-zip.org/download.html"
FileName = "Download-7-Zip.url"
},
@{
Name = "AnyDesk"
Url = "https://anydesk.com/download"
FileName = "Download-AnyDesk.url"
},
@{
Name = "LINE"
Url = "https://line.me/download"
FileName = "Download-LINE.url"
},
@{
Name = "Adobe Reader"
Url = "https://get.adobe.com/reader/"
FileName = "Download-Adobe-Reader.url"
}
)
Write-Host "Creating download shortcuts on User desktop..."
foreach ($app in $apps) {
$shortcutContent = @"
[InternetShortcut]
URL=$($app.Url)
IconIndex=0
"@
$filePath = Join-Path $desktopPath $app.FileName
$shortcutContent | Out-File $filePath -Encoding ASCII
Write-Host " Created: $($app.FileName)"
}
# Create installation instructions
$instructions = @"
=== Application Installation Instructions ===
1. Google Chrome:
- Double-click Download-Chrome.url
- Download the .msi file
- Run the installer (silent install)
2. 7-Zip:
- Double-click Download-7-Zip.url
- Download the x64 .msi version
- Run installer
3. AnyDesk:
- Double-click Download-AnyDesk.url
- Download AnyDesk
- Run installer
4. LINE:
- Double-click Download-LINE.url
- Download LINE for Windows
- Run installer
5. Adobe Reader:
- Double-click Download-Adobe-Reader.url
- Download Adobe Acrobat Reader
- Run installer
All applications will be installed for all users.
"@
$instructionsPath = Join-Path $desktopPath "Installation-Instructions.txt"
$instructions | Out-File $instructionsPath -Encoding UTF8
Write-Host ""
Write-Host "[OK] Download shortcuts created on User desktop:"
Write-Host " - Download-Chrome.url"
Write-Host " - Download-7-Zip.url"
Write-Host " - Download-AnyDesk.url"
Write-Host " - Download-LINE.url"
Write-Host " - Download-Adobe-Reader.url"
Write-Host " - Installation-Instructions.txt"
Write-Host ""
Write-Host "User can now easily download and install applications manually."

View File

@@ -0,0 +1,86 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'SilentlyContinue'
function Section($title) {
Write-Host ''
Write-Host ('=' * 8) $title ('=' * 8) -ForegroundColor Green
}
Section "WinRM Network Diagnostics"
# Check if WinRM is running
$winrmService = Get-Service WinRM
Write-Host "WinRM Service Status: $($winrmService.Status)" -ForegroundColor $(if($winrmService.Status -eq 'Running') {'Green'} else {'Red'})
# Check WinRM listeners
Section "WinRM Listeners"
try {
$listeners = winrm enumerate winrm/config/listener
Write-Host $listeners
} catch {
Write-Host "Failed to enumerate listeners: $_" -ForegroundColor Red
}
# Check firewall rules specifically for WinRM
Section "Firewall Rules for WinRM"
$winrmRules = Get-NetFirewallRule | Where-Object { $_.DisplayName -like "*WinRM*" -or $_.DisplayName -like "*Windows Remote Management*" }
foreach ($rule in $winrmRules) {
$ruleDetails = Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule -ErrorAction SilentlyContinue
$color = if ($rule.Enabled) { 'Green' } else { 'Red' }
Write-Host "$($rule.DisplayName): $($rule.Enabled) [$($rule.Direction)] Port: $($ruleDetails.LocalPort)" -ForegroundColor $color
}
# Check network connections on port 5985
Section "Network Connections on Port 5985"
$connections = Get-NetTCPConnection -LocalPort 5985 -ErrorAction SilentlyContinue
if ($connections) {
$connections | Select-Object LocalAddress, LocalPort, State, OwningProcess | Format-Table -AutoSize
} else {
Write-Host "No connections found on port 5985" -ForegroundColor Red
}
# Check listening ports
Section "Listening Ports (including 5985)"
Get-NetTCPConnection -State Listen | Where-Object { $_.LocalPort -in @(22, 5985, 5986) } |
Select-Object LocalAddress, LocalPort, State, OwningProcess | Format-Table -AutoSize
# Get detailed WinRM configuration
Section "Detailed WinRM Configuration"
try {
Write-Host "Service Configuration:" -ForegroundColor Yellow
winrm get winrm/config/service
Write-Host "`nListener Configuration:" -ForegroundColor Yellow
winrm get winrm/config/listener?Address=*+Transport=HTTP
} catch {
Write-Host "Failed to get WinRM config: $_" -ForegroundColor Red
}
# Test local WinRM connection
Section "Local WinRM Connection Test"
try {
$testResult = Test-WSMan -ComputerName localhost -ErrorAction Stop
Write-Host "✅ Local WinRM test successful" -ForegroundColor Green
} catch {
Write-Host "❌ Local WinRM test failed: $_" -ForegroundColor Red
}
# Network interface information
Section "Network Interfaces"
Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notmatch 'Loopback' } |
Select-Object InterfaceAlias, IPAddress, PrefixLength | Format-Table -AutoSize
# Proposed fixes
Section "Recommended Fixes"
Write-Host "1. Enable WinRM firewall rules:" -ForegroundColor Yellow
Write-Host " Enable-NetFirewallRule -DisplayName 'Windows Remote Management (HTTP-In)'" -ForegroundColor White
Write-Host "`n2. Set AllowUnencrypted to true:" -ForegroundColor Yellow
Write-Host " winrm set winrm/config/service '@{AllowUnencrypted=`"true`"}'" -ForegroundColor White
Write-Host "`n3. Ensure listener is on all interfaces:" -ForegroundColor Yellow
Write-Host " winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Enabled=`"true`"}'" -ForegroundColor White
Write-Host "`n4. Test from remote after fixes:" -ForegroundColor Yellow
Write-Host " Test-WSMan -ComputerName 192.168.88.108 -UseSSL:`$false" -ForegroundColor White

View File

@@ -0,0 +1,83 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Diagnosing winget configuration and connectivity"
Write-Host ""
Write-Host "[1] Checking winget version and status..."
try {
$wingetVersion = & winget --version
Write-Host " winget version: $wingetVersion"
} catch {
Write-Host " [!] winget command failed"
}
Write-Host ""
Write-Host "[2] Checking winget sources..."
try {
$sources = & winget source list
Write-Host " winget sources:"
Write-Host "$sources"
} catch {
Write-Host " [!] Failed to list winget sources"
}
Write-Host ""
Write-Host "[3] Testing network connectivity..."
$testUrls = @(
"github.com",
"cdn.winget.microsoft.com",
"storeedgefd.dsx.mp.microsoft.com"
)
foreach ($url in $testUrls) {
try {
$testResult = Test-NetConnection -ComputerName $url -Port 443 -WarningAction SilentlyContinue
if ($testResult.TcpTestSucceeded) {
Write-Host " [OK] $url - Accessible"
} else {
Write-Host " [!] $url - Not accessible"
}
} catch {
Write-Host " [!] $url - Test failed"
}
}
Write-Host ""
Write-Host "[4] Testing simple winget search..."
try {
Write-Host " Searching for Chrome..."
$searchResult = & winget search "Google.Chrome" --exact
Write-Host " Search result: $searchResult"
} catch {
Write-Host " [!] winget search failed"
}
Write-Host ""
Write-Host "[5] Checking Windows version compatibility..."
$windowsVersion = Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, WindowsBuildLabEx
Write-Host " OS: $($windowsVersion.WindowsProductName)"
Write-Host " Version: $($windowsVersion.WindowsVersion)"
Write-Host " Build: $($windowsVersion.WindowsBuildLabEx)"
Write-Host ""
Write-Host "[6] Testing manual installation with verbose output..."
Write-Host " Attempting to install 7-Zip with verbose logging..."
try {
$installTest = & winget install 7zip.7zip --accept-package-agreements --accept-source-agreements --verbose 2>&1
Write-Host " Install output:"
Write-Host "$installTest"
} catch {
Write-Host " [!] Manual install test failed: $($_.Exception.Message)"
}
Write-Host ""
Write-Host "Diagnosis completed!"
Write-Host ""
Write-Host "Possible solutions based on findings:"
Write-Host "1. If network connectivity issues: Configure proxy or firewall"
Write-Host "2. If source issues: Reset winget sources"
Write-Host "3. If permissions issues: Run as Administrator"
Write-Host "4. If Windows version issues: Update Windows or use manual installation"

View File

@@ -0,0 +1,155 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
function Section($title) {
Write-Host ''
Write-Host ('=' * 8) $title ('=' * 8) -ForegroundColor Green
}
function StatusUpdate($message) {
Write-Host "$message" -ForegroundColor Green
}
function WarningUpdate($message) {
Write-Host "⚠️ $message" -ForegroundColor Yellow
}
Write-Host "Starting WinRM Configuration..." -ForegroundColor Cyan
Write-Host "This script will configure WinRM for remote management." -ForegroundColor Cyan
Write-Host ""
# Check if running as Administrator
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Host "❌ ERROR: This script must be run as Administrator" -ForegroundColor Red
Write-Host "Please run PowerShell as Administrator and try again." -ForegroundColor Red
exit 1
}
StatusUpdate "Running as Administrator"
Section "Enable PowerShell Remoting"
try {
Enable-PSRemoting -Force -SkipNetworkProfileCheck | Out-Null
StatusUpdate "PowerShell Remoting enabled"
} catch {
WarningUpdate "PowerShell Remoting may already be enabled: $($_.Exception.Message)"
}
Section "Configure WinRM Service"
try {
# Ensure WinRM service is set to automatic startup
Set-Service -Name WinRM -StartupType Automatic
Start-Service -Name WinRM
StatusUpdate "WinRM service configured and started"
} catch {
WarningUpdate "WinRM service configuration: $($_.Exception.Message)"
}
Section "Run WinRM Quick Configuration"
try {
$quickConfigOutput = cmd /c "winrm quickconfig -quiet" 2>&1
StatusUpdate "WinRM quick configuration completed"
} catch {
WarningUpdate "WinRM quickconfig: $($_.Exception.Message)"
}
Section "Configure Authentication Methods"
try {
# Enable Basic authentication for simplicity (can be disabled later for production)
cmd /c 'winrm set winrm/config/service/auth @{Basic="true"}' | Out-Null
StatusUpdate "Basic authentication enabled"
# Allow unencrypted traffic for HTTP (can be disabled in production)
cmd /c 'winrm set winrm/config/service @{AllowUnencrypted="true"}' | Out-Null
StatusUpdate "Unencrypted communication allowed (for HTTP testing)"
} catch {
WarningUpdate "Authentication configuration: $($_.Exception.Message)"
}
Section "Configure Firewall Rules"
try {
# Enable Windows Remote Management firewall rules
Enable-NetFirewallRule -DisplayGroup "Windows Remote Management" -ErrorAction SilentlyContinue
StatusUpdate "Windows Remote Management firewall rules enabled"
} catch {
WarningUpdate "Firewall configuration: $($_.Exception.Message)"
}
Section "Create HTTP Listener (if needed)"
try {
# Check if HTTP listener exists
$httpListener = winrm enumerate winrm/config/listener | Select-String "Transport = HTTP"
if (-not $httpListener) {
winrm create winrm/config/listener?Address=*+Transport=HTTP | Out-Null
StatusUpdate "HTTP listener created on port 5985"
} else {
StatusUpdate "HTTP listener already exists"
}
} catch {
WarningUpdate "HTTP listener configuration: $($_.Exception.Message)"
}
Section "Test Local Connection"
try {
$testSession = New-PSSession -ComputerName localhost -ErrorAction Stop
Remove-PSSession $testSession -ErrorAction SilentlyContinue
StatusUpdate "Local WinRM connection test successful"
} catch {
WarningUpdate "Local connection test failed: $($_.Exception.Message)"
Write-Host " This may be normal if additional configuration is needed"
}
Section "Configuration Summary"
Write-Host ""
Write-Host "WinRM has been configured with the following settings:" -ForegroundColor Cyan
Write-Host ""
# Display current configuration
try {
Write-Host "Service Status:" -ForegroundColor Yellow
Get-Service WinRM | Select-Object Name, Status, StartType | Format-List
Write-Host "Listeners:" -ForegroundColor Yellow
winrm enumerate winrm/config/listener
Write-Host "Authentication Methods:" -ForegroundColor Yellow
winrm get winrm/config/service/auth
Write-Host "Firewall Rules:" -ForegroundColor Yellow
Get-NetFirewallRule -DisplayGroup "*Remote Management*" | Where-Object Enabled -eq $true |
Select-Object DisplayName, Direction, Action | Format-Table -AutoSize
} catch {
Write-Host "Could not retrieve full configuration details"
}
Section "Connection Information"
$ipAddresses = Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notmatch 'Loopback' } | Select-Object -ExpandProperty IPAddress
$computerName = $env:COMPUTERNAME
Write-Host "Computer Name: $computerName" -ForegroundColor Cyan
Write-Host "IP Addresses: $($ipAddresses -join ', ')" -ForegroundColor Cyan
Write-Host ""
Write-Host "To test from a remote machine, use:" -ForegroundColor Yellow
Write-Host "Test-WSMan -ComputerName $($ipAddresses[0])" -ForegroundColor White
Write-Host " or"
Write-Host "Test-WSMan -ComputerName $computerName" -ForegroundColor White
Write-Host ""
Write-Host "For PowerShell remoting:" -ForegroundColor Yellow
Write-Host "`$session = New-PSSession -ComputerName $($ipAddresses[0]) -Credential (Get-Credential)" -ForegroundColor White
Section "Security Notes"
Write-Host "⚠️ SECURITY CONSIDERATIONS:" -ForegroundColor Yellow
Write-Host ""
Write-Host "1. Basic authentication and unencrypted communication are enabled for testing" -ForegroundColor Yellow
Write-Host "2. For production use, consider:" -ForegroundColor Yellow
Write-Host " - Disabling Basic auth: winrm set winrm/config/service/auth @{Basic=`"false`"}" -ForegroundColor White
Write-Host " - Disabling unencrypted: winrm set winrm/config/service @{AllowUnencrypted=`"false`"}" -ForegroundColor White
Write-Host " - Setting up HTTPS listener with proper certificates" -ForegroundColor White
Write-Host " - Using Kerberos authentication in domain environments" -ForegroundColor White
Write-Host ""
Write-Host "🎉 WinRM configuration completed!" -ForegroundColor Green

View File

@@ -0,0 +1,36 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
$ruleName = 'SSH TCP 22 (Allow Inbound)'
# Idempotent: remove any existing rule with the same display name, then recreate.
Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue | Remove-NetFirewallRule
New-NetFirewallRule `
-DisplayName $ruleName `
-Description 'Allow inbound SSH on TCP 22 for all firewall profiles (Domain, Private, Public)' `
-Direction Inbound `
-Protocol TCP `
-LocalPort 22 `
-Action Allow `
-Profile Any `
-Enabled True | Out-Null
Write-Host "[*] Re-enabling firewall profiles (Domain, Private, Public)"
Set-NetFirewallProfile -Profile Domain,Private,Public -Enabled True
Write-Host ""
Write-Host "=== Rule ==="
Get-NetFirewallRule -DisplayName $ruleName |
Select-Object DisplayName,Enabled,Direction,Action,Profile |
Format-List
Write-Host "=== Port filter ==="
Get-NetFirewallRule -DisplayName $ruleName | Get-NetFirewallPortFilter |
Format-List Protocol,LocalPort
Write-Host "=== Profile state ==="
Get-NetFirewallProfile | Select-Object Name,Enabled,DefaultInboundAction,DefaultOutboundAction |
Format-Table -AutoSize
Write-Host "[OK] SSH 22 is now permanently allowed across all profiles."

View File

@@ -0,0 +1,62 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
function Section($title) {
Write-Host ''
Write-Host ('=' * 8) $title ('=' * 8) -ForegroundColor Green
}
function StatusUpdate($message) {
Write-Host "$message" -ForegroundColor Green
}
function WarningUpdate($message) {
Write-Host "⚠️ $message" -ForegroundColor Yellow
}
Write-Host "Fixing remaining WinRM configuration issues..." -ForegroundColor Cyan
Section "Fix Allow Unencrypted Setting"
try {
cmd /c 'winrm set winrm/config/service @{AllowUnencrypted="true"}' | Out-Null
StatusUpdate "Allow unencrypted communication enabled"
} catch {
WarningUpdate "Failed to set AllowUnencrypted: $($_.Exception.Message)"
}
Section "Enable WinRM Firewall Rules"
try {
Enable-NetFirewallRule -DisplayGroup "Windows Remote Management" -ErrorAction SilentlyContinue
StatusUpdate "WinRM firewall rules enabled"
# Show enabled WinRM rules
$winrmRules = Get-NetFirewallRule -DisplayGroup "*Remote Management*" | Where-Object Enabled -eq $true
Write-Host "Enabled WinRM firewall rules:" -ForegroundColor Yellow
$winrmRules | Select-Object DisplayName, Direction, Action | Format-Table -AutoSize
} catch {
WarningUpdate "Firewall rule configuration: $($_.Exception.Message)"
}
Section "Verify Settings"
try {
Write-Host "Current WinRM Service Configuration:" -ForegroundColor Yellow
winrm get winrm/config/service
Write-Host "`nCurrent Authentication Settings:" -ForegroundColor Yellow
winrm get winrm/config/service/auth
} catch {
WarningUpdate "Could not retrieve configuration: $($_.Exception.Message)"
}
Section "Final Connection Test"
try {
$testSession = New-PSSession -ComputerName localhost -ErrorAction Stop
Remove-PSSession $testSession -ErrorAction SilentlyContinue
StatusUpdate "Final local WinRM test successful"
} catch {
WarningUpdate "Final test failed: $($_.Exception.Message)"
}
Write-Host "`n🎉 WinRM configuration fixes completed!" -ForegroundColor Green

View File

@@ -0,0 +1,122 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Installing applications via direct download"
Write-Host ""
$downloadFolder = "$env:TEMP\AppDownloads"
New-Item -ItemType Directory -Force -Path $downloadFolder | Out-Null
function Install-App {
param(
[string]$Name,
[string]$Url,
[string]$FileName,
[string]$InstallArgs
)
Write-Host "Installing $Name..."
Write-Host " URL: $Url"
$downloadPath = Join-Path $downloadFolder $FileName
try {
Write-Host " Downloading..."
Invoke-WebRequest -Uri $Url -OutFile $downloadPath -UseBasicParsing
Write-Host " Installing..."
if ($FileName.EndsWith(".msi")) {
& msiexec /i $downloadPath $InstallArgs
} else {
& $downloadPath $InstallArgs
}
Write-Host " [OK] $Name installation completed"
return $true
} catch {
Write-Host " [ERROR] Failed to install $Name"
Write-Host " Error: $($_.Exception.Message)"
return $false
}
}
# Application definitions
$apps = @(
@{
Name = "Google Chrome"
Url = "https://dl.google.com/chrome/install/GoogleChromeStandaloneEnterprise64.msi"
FileName = "ChromeSetup.msi"
InstallArgs = "/quiet /norestart"
},
@{
Name = "7-Zip"
Url = "https://www.7-zip.org/a/7z2301-x64.msi"
FileName = "7zip-setup.msi"
InstallArgs = "/quiet /norestart"
},
@{
Name = "AnyDesk"
Url = "https://download.anydesk.com/AnyDesk.msi"
FileName = "AnyDesk.msi"
InstallArgs = "/quiet /norestart"
}
)
$successCount = 0
foreach ($app in $apps) {
if (Install-App -Name $app.Name -Url $app.Url -FileName $app.FileName -InstallArgs $app.InstallArgs) {
$successCount++
}
Write-Host ""
Start-Sleep -Seconds 2
}
# Manual instructions for apps that need special handling
Write-Host "=== Manual Downloads Required ==="
Write-Host ""
Write-Host "LINE:"
Write-Host " Please download from: https://line.me/download"
Write-Host " Or direct: https://desktop.line-scdn.net/win/new/LineInst.exe"
Write-Host ""
Write-Host "Adobe Reader:"
Write-Host " Please download from: https://get.adobe.com/reader/"
Write-Host " Select version for Windows and download"
Write-Host ""
Write-Host "=== Installation Summary ==="
Write-Host "Automatically installed: $successCount / 3 applications"
Write-Host "Manual download required: 2 applications (LINE, Adobe Reader)"
Write-Host ""
# Create desktop shortcuts for manual downloads
$desktopPath = "C:\Users\User\Desktop"
# Create LINE download shortcut
$lineShortcut = @"
[InternetShortcut]
URL=https://line.me/download
IconIndex=0
"@
$lineShortcut | Out-File "$desktopPath\Download-LINE.url" -Encoding ASCII
# Create Adobe Reader download shortcut
$adobeShortcut = @"
[InternetShortcut]
URL=https://get.adobe.com/reader/
IconIndex=0
"@
$adobeShortcut | Out-File "$desktopPath\Download-Adobe-Reader.url" -Encoding ASCII
Write-Host "Created download shortcuts on User desktop:"
Write-Host " - Download-LINE.url"
Write-Host " - Download-Adobe-Reader.url"
# Clean up
Remove-Item $downloadFolder -Recurse -Force -ErrorAction SilentlyContinue
Write-Host ""
Write-Host "Installation process completed!"

View File

@@ -0,0 +1,103 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Installing applications using winget (fixed sources)"
Write-Host ""
# Applications to install with explicit winget source
$apps = @(
@{Name="Google Chrome"; Id="Google.Chrome"},
@{Name="7-Zip"; Id="7zip.7zip"},
@{Name="AnyDesk"; Id="AnyDeskSoftwareGmbH.AnyDesk"},
@{Name="LINE"; Id="LINE.LINE"},
@{Name="Adobe Reader"; Id="Adobe.Acrobat.Reader.64-bit"}
)
$installedCount = 0
$totalApps = $apps.Count
Write-Host "Installing $totalApps applications using winget source..."
Write-Host ""
foreach ($app in $apps) {
Write-Host "[$($installedCount + 1)/$totalApps] Installing $($app.Name)..."
try {
# Install using explicit winget source to avoid msstore certificate issues
Write-Host " Downloading and installing from winget source..."
$installResult = & winget install $app.Id --source winget --accept-package-agreements --accept-source-agreements --silent
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] $($app.Name) installed successfully"
$installedCount++
} else {
Write-Host " [!] Installation exit code: $LASTEXITCODE"
# Try to verify if it was actually installed despite exit code
Start-Sleep -Seconds 3
$verifyResult = & winget list $app.Id --source winget 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] $($app.Name) appears to be installed"
$installedCount++
} else {
Write-Host " [ERROR] $($app.Name) installation failed"
# Try alternative approach for some apps
if ($app.Name -eq "Google Chrome") {
Write-Host " Trying Chrome enterprise installer..."
try {
$chromeUrl = "https://dl.google.com/chrome/install/GoogleChromeStandaloneEnterprise64.msi"
$chromePath = "$env:TEMP\ChromeSetup.msi"
Invoke-WebRequest -Uri $chromeUrl -OutFile $chromePath -UseBasicParsing
& msiexec /i $chromePath /quiet /norestart
Start-Sleep -Seconds 5
Remove-Item $chromePath -Force -ErrorAction SilentlyContinue
Write-Host " [OK] Chrome installed via direct MSI"
$installedCount++
} catch {
Write-Host " [!] Chrome direct install failed"
}
}
}
}
} catch {
Write-Host " [ERROR] Exception: $($_.Exception.Message)"
}
Write-Host ""
Start-Sleep -Seconds 2
}
Write-Host "=== Installation Summary ==="
Write-Host "Successfully installed: $installedCount / $totalApps applications"
Write-Host ""
# Final verification
Write-Host "Final verification:"
$verificationChecks = @(
@{Name="Chrome"; Paths=@("C:\Program Files\Google\Chrome\Application\chrome.exe", "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe")},
@{Name="7-Zip"; Paths=@("C:\Program Files\7-Zip\7z.exe")},
@{Name="AnyDesk"; Paths=@("C:\Program Files (x86)\AnyDesk\AnyDesk.exe", "C:\Program Files\AnyDesk\AnyDesk.exe")},
@{Name="Adobe Reader"; Paths=@("C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe", "C:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe")},
@{Name="LINE"; Paths=@("C:\Users\$env:USERNAME\AppData\Local\LINE\bin\LineLauncher.exe", "C:\Program Files\LINE\bin\LineLauncher.exe")}
)
foreach ($check in $verificationChecks) {
$found = $false
foreach ($path in $check.Paths) {
if (Test-Path $path) {
Write-Host " [OK] $($check.Name) - Found at $path"
$found = $true
break
}
}
if (-not $found) {
Write-Host " [!] $($check.Name) - Not found"
}
}
Write-Host ""
Write-Host "Installation process completed!"
Write-Host "Note: Some applications may require restart to appear in Start Menu"

View File

@@ -0,0 +1,99 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Installing applications using winget"
Write-Host ""
# Applications to install
$apps = @(
@{Name="Google Chrome"; Id="Google.Chrome"},
@{Name="7-Zip"; Id="7zip.7zip"},
@{Name="AnyDesk"; Id="AnyDeskSoftwareGmbH.AnyDesk"},
@{Name="LINE"; Id="LINE.LINE"},
@{Name="Adobe Reader"; Id="Adobe.Acrobat.Reader.64-bit"}
)
$installedCount = 0
$totalApps = $apps.Count
Write-Host "Installing $totalApps applications..."
Write-Host ""
foreach ($app in $apps) {
Write-Host "[$($installedCount + 1)/$totalApps] Installing $($app.Name)..."
try {
# First check if already installed
$checkResult = & winget list $app.Id 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host " [SKIP] $($app.Name) already installed"
$installedCount++
continue
}
# Install the application
Write-Host " Downloading and installing..."
$installResult = & winget install $app.Id --accept-package-agreements --accept-source-agreements --silent
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] $($app.Name) installed successfully"
$installedCount++
} else {
Write-Host " [!] $($app.Name) installation may have failed"
Write-Host " Checking if it was actually installed..."
# Double-check installation
Start-Sleep -Seconds 2
$verifyResult = & winget list $app.Id 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] $($app.Name) verified as installed"
$installedCount++
} else {
Write-Host " [ERROR] $($app.Name) installation failed"
}
}
} catch {
Write-Host " [ERROR] Exception installing $($app.Name): $($_.Exception.Message)"
}
Write-Host ""
Start-Sleep -Seconds 1
}
Write-Host "=== Installation Summary ==="
Write-Host "Successfully processed: $installedCount / $totalApps applications"
Write-Host ""
# Verification
Write-Host "Verification check:"
$verificationPaths = @(
@{Name="Chrome"; Path="C:\Program Files\Google\Chrome\Application\chrome.exe"},
@{Name="7-Zip"; Path="C:\Program Files\7-Zip\7z.exe"},
@{Name="AnyDesk"; Path="C:\Program Files (x86)\AnyDesk\AnyDesk.exe"},
@{Name="Adobe Reader"; Path="C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"}
)
foreach ($check in $verificationPaths) {
if (Test-Path $check.Path) {
Write-Host " [OK] $($check.Name) - Found"
} else {
Write-Host " [?] $($check.Name) - Not found at expected location"
}
}
# LINE has a different installation path (per-user)
$lineUserPath = "C:\Users\$env:USERNAME\AppData\Local\LINE\bin\LineLauncher.exe"
$lineSystemPath = "C:\Program Files\LINE\bin\LineLauncher.exe"
if ((Test-Path $lineUserPath) -or (Test-Path $lineSystemPath)) {
Write-Host " [OK] LINE - Found"
} else {
Write-Host " [?] LINE - Not found"
}
Write-Host ""
Write-Host "Installation completed!"
Write-Host "Applications may take a few moments to appear in Start Menu."
Write-Host "Some applications may require a system restart to function properly."

View File

@@ -0,0 +1,163 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Installing essential applications for User"
Write-Host "Applications: AnyDesk, LINE, Chrome, 7zip, Adobe Reader"
Write-Host ""
# Function to test if an app is already installed
function Test-AppInstalled {
param([string]$AppName, [string]$ProcessName)
# Check via Get-WmiObject for installed programs
$installed = Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -like "*$AppName*" }
if ($installed) {
Write-Host " $AppName is already installed: $($installed.Name)"
return $true
}
# Check via registry (more reliable for some apps)
$regPaths = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
)
foreach ($path in $regPaths) {
$apps = Get-ItemProperty $path -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*$AppName*" }
if ($apps) {
Write-Host " $AppName is already installed: $($apps[0].DisplayName)"
return $true
}
}
return $false
}
# Function to install via winget
function Install-ViaWinget {
param([string]$AppId, [string]$AppName)
Write-Host " Trying winget install $AppId"
try {
$result = & winget install $AppId --accept-package-agreements --accept-source-agreements --silent
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] $AppName installed via winget"
return $true
} else {
Write-Host " Winget install failed for $AppName"
return $false
}
} catch {
Write-Host " Winget not available or failed: $($_.Exception.Message)"
return $false
}
}
# Function to download and install manually
function Install-Manual {
param([string]$Url, [string]$FileName, [string]$Args, [string]$AppName)
Write-Host " Downloading $AppName from $Url"
$downloadPath = Join-Path $env:TEMP $FileName
try {
Invoke-WebRequest -Uri $Url -OutFile $downloadPath -UseBasicParsing
Write-Host " Downloaded to $downloadPath"
Write-Host " Installing $AppName..."
if ($Args) {
& $downloadPath $Args.Split(' ')
} else {
& $downloadPath
}
Start-Sleep -Seconds 3
# Clean up
Remove-Item $downloadPath -Force -ErrorAction SilentlyContinue
Write-Host " [OK] $AppName installation completed"
return $true
} catch {
Write-Host " [!] Manual install failed for $AppName: $($_.Exception.Message)"
return $false
}
}
Write-Host "[1/5] Installing AnyDesk"
if (-not (Test-AppInstalled -AppName "AnyDesk" -ProcessName "AnyDesk")) {
if (-not (Install-ViaWinget -AppId "AnyDeskSoftwareGmbH.AnyDesk" -AppName "AnyDesk")) {
Install-Manual -Url "https://download.anydesk.com/AnyDesk.exe" -FileName "AnyDesk.exe" -Args "--install --start-with-win --silent" -AppName "AnyDesk"
}
} else {
Write-Host " [SKIP] AnyDesk already installed"
}
Write-Host ""
Write-Host "[2/5] Installing LINE"
if (-not (Test-AppInstalled -AppName "LINE" -ProcessName "LINE")) {
if (-not (Install-ViaWinget -AppId "LINE.LINE" -AppName "LINE")) {
Install-Manual -Url "https://desktop.line-scdn.net/win/new/LineInst.exe" -FileName "LineInst.exe" -Args "/S" -AppName "LINE"
}
} else {
Write-Host " [SKIP] LINE already installed"
}
Write-Host ""
Write-Host "[3/5] Installing Google Chrome"
if (-not (Test-AppInstalled -AppName "Chrome" -ProcessName "chrome")) {
if (-not (Install-ViaWinget -AppId "Google.Chrome" -AppName "Chrome")) {
Install-Manual -Url "https://dl.google.com/chrome/install/GoogleChromeStandaloneEnterprise64.msi" -FileName "ChromeSetup.msi" -Args "/quiet /norestart" -AppName "Chrome"
}
} else {
Write-Host " [SKIP] Chrome already installed"
}
Write-Host ""
Write-Host "[4/5] Installing 7-Zip"
if (-not (Test-AppInstalled -AppName "7-Zip" -ProcessName "7zFM")) {
if (-not (Install-ViaWinget -AppId "7zip.7zip" -AppName "7-Zip")) {
Install-Manual -Url "https://7-zip.org/a/7z2301-x64.msi" -FileName "7zip-setup.msi" -Args "/quiet /norestart" -AppName "7-Zip"
}
} else {
Write-Host " [SKIP] 7-Zip already installed"
}
Write-Host ""
Write-Host "[5/5] Installing Adobe Reader"
if (-not (Test-AppInstalled -AppName "Adobe" -ProcessName "AcroRd32")) {
if (-not (Install-ViaWinget -AppId "Adobe.Acrobat.Reader.64-bit" -AppName "Adobe Reader")) {
# Adobe Reader requires more complex download, try alternative
Write-Host " [!] Adobe Reader requires manual download from Adobe website"
Write-Host " Please visit: https://get.adobe.com/reader/"
Write-Host " Or try: winget install Adobe.Acrobat.Reader.64-bit"
}
} else {
Write-Host " [SKIP] Adobe Reader already installed"
}
Write-Host ""
Write-Host "=== Installation Summary ==="
# Final verification
$apps = @(
@{Name="AnyDesk"; Process="AnyDesk"}
@{Name="LINE"; Process="LINE"}
@{Name="Chrome"; Process="chrome"}
@{Name="7-Zip"; Process="7zFM"}
@{Name="Adobe"; Process="AcroRd32"}
)
foreach ($app in $apps) {
$installed = Test-AppInstalled -AppName $app.Name -ProcessName $app.Process
if ($installed) {
Write-Host "[OK] $($app.Name) - Installed"
} else {
Write-Host "[!] $($app.Name) - Not detected (may need manual verification)"
}
}
Write-Host ""
Write-Host "[*] Application installation process completed"
Write-Host "Note: Some applications may require restart to appear in Start Menu"
Write-Host "All applications will be available to all users on this computer"

View File

@@ -0,0 +1,66 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
$url = 'https://www.nirsoft.net/utils/cports-x64.zip'
$installDir = 'C:\Program Files\NirSoft\CurrPorts'
$exeName = 'cports.exe'
$exePath = Join-Path $installDir $exeName
# Idempotent
if (Test-Path $exePath) {
$ver = (Get-Item $exePath).VersionInfo.ProductVersion
Write-Host "[=] CurrPorts already installed: $exePath (v$ver)"
} else {
$tmpZip = Join-Path $env:TEMP 'cports-x64.zip'
$tmpDir = Join-Path $env:TEMP 'cports-extract'
if (Test-Path $tmpDir) { Remove-Item $tmpDir -Recurse -Force }
New-Item -ItemType Directory -Path $tmpDir | Out-Null
Write-Host "[*] Downloading $url"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $url -OutFile $tmpZip -UseBasicParsing
if ((Get-Item $tmpZip).Length -lt 50KB) { throw "Downloaded zip too small" }
Expand-Archive -Path $tmpZip -DestinationPath $tmpDir -Force
if (-not (Test-Path (Join-Path $tmpDir $exeName))) {
throw "$exeName not found in archive"
}
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
Copy-Item -Path (Join-Path $tmpDir '*') -Destination $installDir -Recurse -Force
Remove-Item $tmpZip -Force -ErrorAction SilentlyContinue
Remove-Item $tmpDir -Recurse -Force -ErrorAction SilentlyContinue
$ver = (Get-Item $exePath).VersionInfo.ProductVersion
Write-Host "[OK] Installed: $exePath (v$ver)"
}
# Start Menu shortcut for all users (Common Start Menu)
$commonStart = 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs'
$lnkCommon = Join-Path $commonStart 'CurrPorts.lnk'
$wsh = New-Object -ComObject WScript.Shell
$lnk = $wsh.CreateShortcut($lnkCommon)
$lnk.TargetPath = $exePath
$lnk.WorkingDirectory = $installDir
$lnk.IconLocation = "$exePath,0"
$lnk.Description = 'NirSoft CurrPorts - list open TCP/UDP ports'
$lnk.Save()
Write-Host "[*] Start Menu (All Users) shortcut: $lnkCommon"
# Also desktop shortcut for the 'User' account (main daily-use account)
$userDesktop = 'C:\Users\user\Desktop'
if (Test-Path $userDesktop) {
$lnkUser = Join-Path $userDesktop 'CurrPorts.lnk'
$lnk2 = $wsh.CreateShortcut($lnkUser)
$lnk2.TargetPath = $exePath
$lnk2.WorkingDirectory = $installDir
$lnk2.IconLocation = "$exePath,0"
$lnk2.Save()
& icacls $lnkUser /grant 'User:F' /Q | Out-Null
Write-Host "[*] Desktop shortcut for User: $lnkUser"
}
Write-Host ""
Write-Host "Launch from Start menu, or run directly:"
Write-Host " `"$exePath`""

View File

@@ -0,0 +1,104 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Installing essential applications"
Write-Host "Apps: AnyDesk, LINE, Chrome, 7zip, Adobe Reader"
Write-Host ""
# Install via winget (preferred method)
$apps = @(
@{Name="AnyDesk"; WingetId="AnyDeskSoftwareGmbH.AnyDesk"}
@{Name="LINE"; WingetId="LINE.LINE"}
@{Name="Google Chrome"; WingetId="Google.Chrome"}
@{Name="7-Zip"; WingetId="7zip.7zip"}
@{Name="Adobe Reader"; WingetId="Adobe.Acrobat.Reader.64-bit"}
)
$successCount = 0
$totalApps = $apps.Count
foreach ($app in $apps) {
Write-Host "Installing $($app.Name)..."
try {
$result = & winget install $app.WingetId --accept-package-agreements --accept-source-agreements --silent 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] $($app.Name) installed successfully"
$successCount++
} else {
Write-Host " [SKIP] $($app.Name) may already be installed or failed"
# Check if already installed
$checkResult = & winget list $app.WingetId 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " [INFO] $($app.Name) appears to be already installed"
$successCount++
}
}
} catch {
Write-Host " [ERROR] Failed to install $($app.Name)"
# Try alternative download for critical apps
if ($app.Name -eq "Google Chrome") {
Write-Host " Trying alternative Chrome download..."
try {
$chromeUrl = "https://dl.google.com/chrome/install/GoogleChromeStandaloneEnterprise64.msi"
$chromePath = "$env:TEMP\ChromeSetup.msi"
Invoke-WebRequest -Uri $chromeUrl -OutFile $chromePath -UseBasicParsing
& msiexec /i $chromePath /quiet /norestart
Write-Host " [OK] Chrome installed via direct download"
$successCount++
} catch {
Write-Host " [ERROR] Chrome alternative install failed"
}
}
}
Write-Host ""
}
Write-Host "=== Installation Summary ==="
Write-Host "Successfully installed: $successCount / $totalApps applications"
Write-Host ""
# Verify installations by checking common install locations
Write-Host "Verification:"
$verifyApps = @(
@{Name="AnyDesk"; Path="C:\Program Files (x86)\AnyDesk\AnyDesk.exe"}
@{Name="LINE"; Path="C:\Users\$env:USERNAME\AppData\Local\LINE\bin\LineLauncher.exe"}
@{Name="Chrome"; Path="C:\Program Files\Google\Chrome\Application\chrome.exe"}
@{Name="7-Zip"; Path="C:\Program Files\7-Zip\7z.exe"}
@{Name="Adobe Reader"; Path="C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"}
)
foreach ($app in $verifyApps) {
if (Test-Path $app.Path) {
Write-Host " [OK] $($app.Name) - Found at expected location"
} else {
# Try to find in registry
$found = $false
$regPaths = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
)
foreach ($regPath in $regPaths) {
$installed = Get-ItemProperty $regPath -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like "*$($app.Name.Split(' ')[0])*" }
if ($installed) {
Write-Host " [OK] $($app.Name) - Found in registry"
$found = $true
break
}
}
if (-not $found) {
Write-Host " [!] $($app.Name) - Not detected"
}
}
}
Write-Host ""
Write-Host "Installation completed!"
Write-Host "Note: Applications may require restart to appear in Start Menu"

View File

@@ -0,0 +1,102 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
$configPath = Join-Path $PSScriptRoot 'nirsoft-config.json'
$cfg = Get-Content $configPath -Raw -Encoding UTF8 | ConvertFrom-Json
$installRoot = $cfg.InstallRoot
$shortcutRoot = $cfg.ShortcutRoot
New-Item -ItemType Directory -Force -Path $installRoot | Out-Null
New-Item -ItemType Directory -Force -Path $shortcutRoot | Out-Null
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$wsh = New-Object -ComObject WScript.Shell
function Install-OneTool {
param($tool)
$toolDir = Join-Path $installRoot $tool.Name
$exePath = Join-Path $toolDir $tool.Exe
if (Test-Path $exePath) {
$ver = (Get-Item $exePath).VersionInfo.ProductVersion
Write-Host "[=] $($tool.Name) already installed (v$ver)"
} else {
Write-Host "[*] $($tool.Name) downloading $($tool.Url)"
$tmpZip = Join-Path $env:TEMP "$($tool.Name).zip"
$tmpDir = Join-Path $env:TEMP "$($tool.Name)-extract"
if (Test-Path $tmpDir) { Remove-Item $tmpDir -Recurse -Force }
New-Item -ItemType Directory -Path $tmpDir | Out-Null
try {
Invoke-WebRequest -Uri $tool.Url -OutFile $tmpZip -UseBasicParsing
if ((Get-Item $tmpZip).Length -lt 20KB) { throw "download too small" }
Expand-Archive -Path $tmpZip -DestinationPath $tmpDir -Force
if (-not (Test-Path (Join-Path $tmpDir $tool.Exe))) {
# Some NirSoft archives nest the exe; search
$found = Get-ChildItem $tmpDir -Recurse -Filter $tool.Exe -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $found) { throw "$($tool.Exe) not found in archive" }
Copy-Item -Path (Split-Path $found.FullName) -Destination $toolDir -Recurse -Force
} else {
New-Item -ItemType Directory -Force -Path $toolDir | Out-Null
Copy-Item -Path (Join-Path $tmpDir '*') -Destination $toolDir -Recurse -Force
}
$ver = (Get-Item $exePath).VersionInfo.ProductVersion
Write-Host "[OK] $($tool.Name) v$ver -> $toolDir"
} finally {
Remove-Item $tmpZip -Force -ErrorAction SilentlyContinue
Remove-Item $tmpDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
# Admin-only Start Menu shortcut under NirSoft\
$lnk = $wsh.CreateShortcut((Join-Path $shortcutRoot "$($tool.Name).lnk"))
$lnk.TargetPath = $exePath
$lnk.WorkingDirectory = $toolDir
$lnk.IconLocation = "$exePath,0"
$lnk.Save()
}
# --- Install all tools ---
foreach ($t in $cfg.Tools) {
try { Install-OneTool -tool $t }
catch { Write-Host "[!] $($t.Name) failed: $($_.Exception.Message)" }
}
# --- Reorganize existing CurrPorts shortcuts (hide from User) ---
Write-Host ""
Write-Host "[*] Reorganizing CurrPorts shortcuts (hide from User)"
$cpExe = Join-Path $installRoot 'CurrPorts\cports.exe'
if (Test-Path $cpExe) {
# Create in Admin's NirSoft folder
$lnk = $wsh.CreateShortcut((Join-Path $shortcutRoot 'CurrPorts.lnk'))
$lnk.TargetPath = $cpExe
$lnk.WorkingDirectory = Split-Path $cpExe
$lnk.IconLocation = "$cpExe,0"
$lnk.Save()
Write-Host " - added to Admin's NirSoft Start Menu"
}
# Remove visible CurrPorts shortcuts that the User would see
$visibleShortcuts = @(
'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\CurrPorts.lnk',
'C:\Users\user\Desktop\CurrPorts.lnk',
'C:\Users\User\Desktop\CurrPorts.lnk'
)
foreach ($s in $visibleShortcuts) {
if (Test-Path $s) {
Remove-Item $s -Force -ErrorAction SilentlyContinue
Write-Host " - removed $s"
}
}
Write-Host ""
Write-Host "===== Summary ====="
Write-Host "Installed to: $installRoot"
Write-Host "Shortcuts: $shortcutRoot (Admin's Start Menu only, not visible to 'User')"
Write-Host ""
Write-Host "All tools support CSV/text output via /scomma /stext /shtml /sxml flags, e.g.:"
Write-Host " cports.exe /scomma ports.csv"
Write-Host " InstalledAppsView.exe /scomma apps.csv"
Write-Host " LastActivityView.exe /scomma activity.csv"

View File

@@ -0,0 +1,187 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Installing remaining applications with Windows Defender bypass"
Write-Host "Apps: AnyDesk, LINE, Adobe Reader"
Write-Host ""
# Check if running as administrator
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Host "[!] ERROR: This script must be run as Administrator"
exit 1
}
$downloadFolder = "$env:TEMP\DirectAppInstalls"
New-Item -ItemType Directory -Force -Path $downloadFolder | Out-Null
# Function to temporarily disable Windows Defender
function Disable-WindowsDefender {
Write-Host "[*] Temporarily disabling Windows Defender real-time protection..."
try {
Set-MpPreference -DisableRealtimeMonitoring $true
Write-Host " [OK] Windows Defender real-time protection disabled"
return $true
} catch {
Write-Host " [!] Failed to disable Windows Defender: $($_.Exception.Message)"
Write-Host " Continuing with installation anyway..."
return $false
}
}
# Function to re-enable Windows Defender
function Enable-WindowsDefender {
Write-Host "[*] Re-enabling Windows Defender real-time protection..."
try {
Set-MpPreference -DisableRealtimeMonitoring $false
Write-Host " [OK] Windows Defender real-time protection re-enabled"
} catch {
Write-Host " [!] Failed to re-enable Windows Defender: $($_.Exception.Message)"
}
}
# Function to install application
function Install-DirectApp {
param(
[string]$Name,
[string]$Url,
[string]$FileName,
[string]$InstallArgs,
[int]$TimeoutMinutes = 5
)
Write-Host "Installing $Name..."
Write-Host " URL: $Url"
$downloadPath = Join-Path $downloadFolder $FileName
$success = $false
try {
# Download
Write-Host " Downloading..."
Invoke-WebRequest -Uri $Url -OutFile $downloadPath -UseBasicParsing -TimeoutSec 120
if (Test-Path $downloadPath) {
$fileSize = (Get-Item $downloadPath).Length / 1MB
Write-Host " Downloaded: $([math]::Round($fileSize, 2)) MB"
# Install
Write-Host " Installing with args: $InstallArgs"
if ($FileName.EndsWith(".msi")) {
$process = Start-Process -FilePath "msiexec" -ArgumentList "/i", $downloadPath, $InstallArgs -Wait -PassThru
} else {
$argList = $InstallArgs.Split(' ') + $downloadPath
$process = Start-Process -FilePath $downloadPath -ArgumentList $InstallArgs -Wait -PassThru -WindowStyle Hidden
}
Write-Host " Process exit code: $($process.ExitCode)"
if ($process.ExitCode -eq 0 -or $process.ExitCode -eq 3010) {
Write-Host " [OK] $Name installation completed successfully"
$success = $true
} else {
Write-Host " [!] $Name installation may have failed (exit code: $($process.ExitCode))"
# Some installers return non-zero codes even on success, so we'll verify later
}
} else {
Write-Host " [!] Download failed - file not found"
}
} catch {
Write-Host " [ERROR] $Name installation failed: $($_.Exception.Message)"
} finally {
# Clean up download
if (Test-Path $downloadPath) {
Remove-Item $downloadPath -Force -ErrorAction SilentlyContinue
}
}
return $success
}
# Applications to install
$apps = @(
@{
Name = "AnyDesk"
Url = "https://download.anydesk.com/AnyDesk.msi"
FileName = "AnyDesk.msi"
InstallArgs = "/quiet /norestart"
},
@{
Name = "LINE"
Url = "https://desktop.line-scdn.net/win/new/LineInst.exe"
FileName = "LineInst.exe"
InstallArgs = "/S"
},
@{
Name = "Adobe Reader"
Url = "https://ardownload2.adobe.com/pub/adobe/reader/win/AcrobatDC/2300820555/AcroRdrDC2300820555_en_US.exe"
FileName = "AdobeReader.exe"
InstallArgs = "/sAll /rs /msi EULA_ACCEPT=YES"
}
)
Write-Host "=== Starting Installation Process ==="
Write-Host ""
# Disable Windows Defender
$defenderDisabled = Disable-WindowsDefender
$installedCount = 0
$totalApps = $apps.Count
try {
foreach ($app in $apps) {
Write-Host "[$($installedCount + 1)/$totalApps] $($app.Name)"
if (Install-DirectApp -Name $app.Name -Url $app.Url -FileName $app.FileName -InstallArgs $app.InstallArgs) {
$installedCount++
}
Write-Host ""
Start-Sleep -Seconds 3
}
} finally {
# Always re-enable Windows Defender
if ($defenderDisabled) {
Enable-WindowsDefender
}
}
# Clean up download folder
Remove-Item $downloadFolder -Recurse -Force -ErrorAction SilentlyContinue
Write-Host "=== Installation Summary ==="
Write-Host "Successfully installed: $installedCount / $totalApps applications"
Write-Host ""
# Final verification
Write-Host "=== Verification ==="
$verificationPaths = @(
@{Name="AnyDesk"; Paths=@("C:\Program Files (x86)\AnyDesk\AnyDesk.exe", "C:\Program Files\AnyDesk\AnyDesk.exe")},
@{Name="LINE"; Paths=@("C:\Users\$env:USERNAME\AppData\Local\LINE\bin\LineLauncher.exe", "C:\Program Files\LINE\bin\LineLauncher.exe")},
@{Name="Adobe Reader"; Paths=@("C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe", "C:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe")}
)
foreach ($check in $verificationPaths) {
$found = $false
foreach ($path in $check.Paths) {
if (Test-Path $path) {
Write-Host "[OK] $($check.Name) - Found at $path"
$found = $true
break
}
}
if (-not $found) {
Write-Host "[!] $($check.Name) - Not found (may need restart or manual verification)"
}
}
Write-Host ""
Write-Host "Installation completed!"
Write-Host "Note: Some applications may require restart to appear in Start Menu"
Write-Host "Windows Defender real-time protection has been restored"

View File

@@ -0,0 +1,102 @@
param(
[string]$TargetUser = 'user'
)
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
$targetProfile = "C:\Users\$TargetUser"
if (-not (Test-Path $targetProfile)) { throw "Windows user '$TargetUser' not found ($targetProfile missing)" }
$installDir = Join-Path $targetProfile 'AppData\Roaming\Telegram Desktop'
$startMenuDir = Join-Path $targetProfile 'AppData\Roaming\Microsoft\Windows\Start Menu\Programs'
$desktopDir = Join-Path $targetProfile 'Desktop'
function Get-TelegramVersion($dir) {
$exe = Join-Path $dir 'Telegram.exe'
if (Test-Path $exe) { return (Get-Item $exe).VersionInfo.ProductVersion }
return $null
}
# Already installed at target?
$existingVer = Get-TelegramVersion $installDir
if ($existingVer) {
Write-Host "[=] Already installed for '$TargetUser': Telegram $existingVer at $installDir"
exit 0
}
# Clean up any stray Admin-scoped install that we may have created earlier
$adminDir = 'C:\Users\Admin\AppData\Roaming\Telegram Desktop'
$adminUninst = Join-Path $adminDir 'unins000.exe'
if ((Test-Path $adminUninst) -and ($TargetUser -ne 'Admin')) {
Write-Host "[*] Removing stray Admin-scoped install at $adminDir"
Get-Process Telegram,Updater -ErrorAction SilentlyContinue | Stop-Process -Force
$p = Start-Process -FilePath $adminUninst -ArgumentList '/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART' -Wait -PassThru
if ($p.ExitCode -ne 0) { Write-Host "[!] Uninstall exited $($p.ExitCode), continuing anyway" }
# Remove Admin's HKCU uninstall key (best-effort)
Get-Item 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue |
Where-Object { (Get-ItemProperty $_.PSPath).DisplayName -match 'Telegram' } |
ForEach-Object { Remove-Item $_.PSPath -Force -Recurse -ErrorAction SilentlyContinue }
# Remove Admin's start menu shortcut
$adminLnk = 'C:\Users\Admin\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Telegram.lnk'
Remove-Item $adminLnk -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
}
# Download installer
$url = 'https://telegram.org/dl/desktop/win64'
$dst = Join-Path $env:TEMP 'telegram-setup.exe'
Write-Host "[*] Downloading installer -> $dst"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $url -OutFile $dst -UseBasicParsing
if (-not (Test-Path $dst) -or (Get-Item $dst).Length -lt 10MB) {
throw "Downloaded file looks wrong (< 10 MB)"
}
# Install into target user's AppData. /NOICONS = no shortcuts (we'll create them in target's profile).
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
$argStr = '/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /NOICONS /NOLAUNCH /DIR="' + $installDir + '"'
Write-Host "[*] Installing to $installDir"
$p = Start-Process -FilePath $dst -ArgumentList $argStr -Wait -PassThru
Remove-Item $dst -ErrorAction SilentlyContinue
if ($p.ExitCode -ne 0) { throw "Installer exited $($p.ExitCode)" }
# Verify binary appeared
$finalVer = Get-TelegramVersion $installDir
if (-not $finalVer) { throw "Telegram.exe not found at $installDir after install" }
# Give target user full control over the install tree
Write-Host "[*] Adjusting ACL on $installDir for '$TargetUser'"
& icacls $installDir /grant "${TargetUser}:(OI)(CI)F" /T /Q | Out-Null
# Create Start Menu shortcut in target user's profile
New-Item -ItemType Directory -Force -Path $startMenuDir | Out-Null
$wsh = New-Object -ComObject WScript.Shell
$lnk = $wsh.CreateShortcut((Join-Path $startMenuDir 'Telegram.lnk'))
$lnk.TargetPath = Join-Path $installDir 'Telegram.exe'
$lnk.WorkingDirectory = $installDir
$lnk.IconLocation = (Join-Path $installDir 'Telegram.exe') + ',0'
$lnk.Save()
Write-Host "[*] Start menu shortcut: $(Join-Path $startMenuDir 'Telegram.lnk')"
# Desktop shortcut
if (Test-Path $desktopDir) {
$dlnk = $wsh.CreateShortcut((Join-Path $desktopDir 'Telegram.lnk'))
$dlnk.TargetPath = Join-Path $installDir 'Telegram.exe'
$dlnk.WorkingDirectory = $installDir
$dlnk.IconLocation = (Join-Path $installDir 'Telegram.exe') + ',0'
$dlnk.Save()
Write-Host "[*] Desktop shortcut: $(Join-Path $desktopDir 'Telegram.lnk')"
}
# Fix ACL on the shortcuts too
& icacls (Join-Path $startMenuDir 'Telegram.lnk') /grant "${TargetUser}:F" /Q | Out-Null
if (Test-Path (Join-Path $desktopDir 'Telegram.lnk')) {
& icacls (Join-Path $desktopDir 'Telegram.lnk') /grant "${TargetUser}:F" /Q | Out-Null
}
Write-Host ""
Write-Host "[OK] Telegram $finalVer installed for '$TargetUser'"
Write-Host " Location: $installDir"
Write-Host " Data (tdata) will be created beside the exe on first launch."

View File

@@ -0,0 +1,73 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
function Test-Installed {
$keys = @(
'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
Get-ItemProperty $keys -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -match 'Thunderbird' } |
Select-Object -First 1 DisplayName,DisplayVersion,InstallLocation
}
$existing = Test-Installed
if ($existing) {
Write-Host "[=] Thunderbird already installed: $($existing.DisplayName) $($existing.DisplayVersion)"
Write-Host " Location: $($existing.InstallLocation)"
exit 0
}
$installed = $false
# --- Attempt 1: winget ---
$winget = Get-Command winget -ErrorAction SilentlyContinue
if ($winget) {
Write-Host "[*] winget found, installing Mozilla.Thunderbird"
try {
& winget install --id Mozilla.Thunderbird -e --silent `
--accept-source-agreements --accept-package-agreements `
--scope machine 2>&1 | Write-Host
if ($LASTEXITCODE -eq 0) { $installed = $true }
else { Write-Host "[!] winget exited $LASTEXITCODE, falling back to direct download" }
} catch {
Write-Host "[!] winget failed: $_"
}
} else {
Write-Host "[!] winget not available, using direct download"
}
# --- Attempt 2: direct download from Mozilla CDN ---
if (-not $installed) {
$url = 'https://download.mozilla.org/?product=thunderbird-latest&os=win64&lang=zh-TW'
$dst = Join-Path $env:TEMP 'thunderbird-setup.exe'
Write-Host "[*] Downloading installer -> $dst"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $url -OutFile $dst -UseBasicParsing
if (-not (Test-Path $dst) -or (Get-Item $dst).Length -lt 10MB) {
throw "Downloaded file looks wrong (size < 10 MB)"
}
Write-Host "[*] Running silent install"
$proc = Start-Process -FilePath $dst -ArgumentList '/S' -Wait -PassThru
if ($proc.ExitCode -ne 0) {
throw "Installer exited with code $($proc.ExitCode)"
}
Remove-Item $dst -ErrorAction SilentlyContinue
$installed = $true
}
# --- Verify ---
Start-Sleep -Seconds 2
$after = Test-Installed
if ($after) {
Write-Host ""
Write-Host "[OK] Installed: $($after.DisplayName) $($after.DisplayVersion)"
Write-Host " Location: $($after.InstallLocation)"
exit 0
} else {
Write-Host "[FAIL] Thunderbird was not detected in uninstall registry after install"
exit 1
}

View File

@@ -0,0 +1,135 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Investigating application installation failures"
Write-Host ""
# Error code analysis
Write-Host "=== Error Code Analysis ==="
Write-Host "Error code -1978335212 (0x8A150054) typically indicates:"
Write-Host "- APPINSTALLER_CLI_ERROR_INSTALLER_FAILED"
Write-Host "- The package installer failed during execution"
Write-Host ""
Write-Host "[1] Checking system requirements and dependencies..."
# Check Windows version
$osInfo = Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, WindowsBuildLabEx
Write-Host "OS: $($osInfo.WindowsProductName)"
Write-Host "Version: $($osInfo.WindowsVersion)"
Write-Host "Build: $($osInfo.WindowsBuildLabEx)"
# Check available disk space
$disk = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DeviceID -eq "C:"}
$freeSpaceGB = [math]::Round($disk.FreeSpace / 1GB, 2)
Write-Host "Free space on C: drive: $freeSpaceGB GB"
Write-Host ""
Write-Host "[2] Checking for conflicting installations..."
# Check if any versions are already partially installed
$installedApps = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -like "*AnyDesk*" -or
$_.Name -like "*LINE*" -or
$_.Name -like "*Adobe*Reader*"
} | Select-Object Name, Version, IdentifyingNumber
if ($installedApps) {
Write-Host "Found existing installations:"
foreach ($app in $installedApps) {
Write-Host " - $($app.Name) v$($app.Version)"
}
} else {
Write-Host "No conflicting installations found"
}
Write-Host ""
Write-Host "[3] Testing individual app availability..."
$failedApps = @(
@{Name="AnyDesk"; Id="AnyDeskSoftwareGmbH.AnyDesk"},
@{Name="LINE"; Id="LINE.LINE"},
@{Name="Adobe Reader"; Id="Adobe.Acrobat.Reader.64-bit"}
)
foreach ($app in $failedApps) {
Write-Host "Testing $($app.Name)..."
# Check if app is available in winget
try {
$searchResult = & winget show $app.Id --source winget 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] Package found in winget"
# Extract some key info
$lines = $searchResult -split "`n"
foreach ($line in $lines) {
if ($line -like "*Version:*" -or $line -like "*Publisher:*" -or $line -like "*Package Url:*") {
Write-Host " $line"
}
}
} else {
Write-Host " [!] Package not found or access denied"
}
} catch {
Write-Host " [!] Search failed: $($_.Exception.Message)"
}
Write-Host ""
}
Write-Host "[4] Checking system policies and restrictions..."
# Check execution policy
$execPolicy = Get-ExecutionPolicy -Scope LocalMachine
Write-Host "Execution Policy: $execPolicy"
# Check if running as administrator
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
Write-Host "Running as Administrator: $isAdmin"
# Check Windows Defender status
try {
$defender = Get-MpPreference -ErrorAction SilentlyContinue
if ($defender) {
Write-Host "Windows Defender Real-time Protection: $($defender.DisableRealtimeMonitoring -eq $false)"
}
} catch {
Write-Host "Cannot check Windows Defender status"
}
Write-Host ""
Write-Host "[5] Testing direct download availability..."
$downloadTests = @(
@{Name="AnyDesk"; Url="https://download.anydesk.com/AnyDesk.exe"},
@{Name="LINE"; Url="https://desktop.line-scdn.net/win/new/LineInst.exe"},
@{Name="Adobe Reader"; Url="https://ardownload2.adobe.com/pub/adobe/reader/win/AcrobatDC/2300820555/AcroRdrDC2300820555_en_US.exe"}
)
foreach ($test in $downloadTests) {
Write-Host "Testing $($test.Name) direct download..."
try {
$webRequest = Invoke-WebRequest -Uri $test.Url -Method Head -UseBasicParsing -TimeoutSec 10
Write-Host " [OK] Direct download available (Status: $($webRequest.StatusCode))"
} catch {
Write-Host " [!] Direct download failed: $($_.Exception.Message)"
}
}
Write-Host ""
Write-Host "=== Investigation Summary ==="
Write-Host ""
Write-Host "Possible reasons for failures:"
Write-Host "1. Package installer requirements not met (missing dependencies)"
Write-Host "2. Antivirus/Windows Defender blocking installation"
Write-Host "3. Insufficient permissions despite administrator status"
Write-Host "4. Network connectivity issues to specific download servers"
Write-Host "5. Package conflicts with existing system components"
Write-Host "6. Windows version compatibility issues"
Write-Host ""
Write-Host "Recommended solutions:"
Write-Host "1. Try direct installer downloads with elevated permissions"
Write-Host "2. Temporarily disable real-time protection during installation"
Write-Host "3. Use alternative installation sources or older versions"
Write-Host "4. Install dependencies manually before main applications"

View File

@@ -0,0 +1,145 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Mapping R: drive with anonymous access (no credentials)"
$networkPath = "\\192.168.88.231\RD"
$driveLetter = "R:"
# First, remove any existing R: mapping
Write-Host "[*] Cleaning up existing mappings"
try {
& net use $driveLetter /delete /yes 2>$null
Write-Host " Cleared any existing R: mapping"
} catch {
Write-Host " No existing mapping to clear"
}
Write-Host "[*] Testing anonymous access methods"
# Method 1: Simple net use without credentials
Write-Host "[1] Trying simple net use..."
try {
$result = & net use $driveLetter $networkPath /persistent:yes
if ($LASTEXITCODE -eq 0) {
Write-Host "[OK] Method 1 successful!"
$success = $true
} else {
Write-Host " Method 1 failed: $result"
$success = $false
}
} catch {
Write-Host " Method 1 exception: $($_.Exception.Message)"
$success = $false
}
# Method 2: Explicit guest access
if (-not $success) {
Write-Host "[2] Trying guest access..."
try {
$result = & net use $driveLetter $networkPath /user:guest "" /persistent:yes
if ($LASTEXITCODE -eq 0) {
Write-Host "[OK] Method 2 successful!"
$success = $true
} else {
Write-Host " Method 2 failed: $result"
}
} catch {
Write-Host " Method 2 exception: $($_.Exception.Message)"
}
}
# Method 3: Empty username
if (-not $success) {
Write-Host "[3] Trying empty username..."
try {
$result = & net use $driveLetter $networkPath /user:"" "" /persistent:yes
if ($LASTEXITCODE -eq 0) {
Write-Host "[OK] Method 3 successful!"
$success = $true
} else {
Write-Host " Method 3 failed: $result"
}
} catch {
Write-Host " Method 3 exception: $($_.Exception.Message)"
}
}
# Method 4: Using PowerShell New-PSDrive
if (-not $success) {
Write-Host "[4] Trying PowerShell PSDrive..."
try {
New-PSDrive -Name "R" -PSProvider FileSystem -Root $networkPath -Persist -ErrorAction Stop
Write-Host "[OK] Method 4 successful!"
$success = $true
} catch {
Write-Host " Method 4 exception: $($_.Exception.Message)"
}
}
# Verify the mapping
Write-Host "[*] Verifying drive mapping"
Start-Sleep -Seconds 2
$driveCheck = Get-WmiObject -Class Win32_LogicalDisk | Where-Object { $_.DeviceID -eq $driveLetter }
if ($driveCheck -and $driveCheck.DriveType -eq 4) {
Write-Host "[OK] Network drive R: successfully mapped!"
Write-Host " Device: $($driveCheck.DeviceID)"
Write-Host " Provider: $($driveCheck.ProviderName)"
Write-Host " Type: Network Drive"
# Test accessibility
try {
if (Test-Path "${driveLetter}\") {
Write-Host "[OK] Drive R: is accessible"
# List contents
$items = Get-ChildItem "${driveLetter}\" -ErrorAction SilentlyContinue
if ($items) {
Write-Host " Contents: $($items.Count) items found"
Write-Host " Sample items:"
$items | Select-Object -First 3 | ForEach-Object {
Write-Host " - $($_.Name) ($($_.Mode))"
}
} else {
Write-Host " Directory appears empty"
}
} else {
Write-Host "[!] Drive mapped but not accessible"
}
} catch {
Write-Host "[!] Error testing accessibility: $($_.Exception.Message)"
}
} else {
Write-Host "[!] Drive mapping verification failed"
# Show current network drives
$networkDrives = Get-WmiObject -Class Win32_LogicalDisk | Where-Object { $_.DriveType -eq 4 }
if ($networkDrives) {
Write-Host "Current network drives:"
foreach ($drive in $networkDrives) {
Write-Host " $($drive.DeviceID) -> $($drive.ProviderName)"
}
} else {
Write-Host "No network drives currently mapped"
}
Write-Host ""
Write-Host "Manual verification:"
Write-Host "1. Open File Explorer"
Write-Host "2. Check if R: drive appears under 'This PC'"
Write-Host "3. Try accessing \\192.168.88.231\RD directly"
}
Write-Host ""
Write-Host "[*] Drive mapping process completed"
# Clean up the desktop batch file since we don't need credentials
$batchFile = "C:\Users\User\Desktop\Map-Drive-R.bat"
if (Test-Path $batchFile) {
Remove-Item $batchFile -Force -ErrorAction SilentlyContinue
Write-Host " Removed credential batch file (not needed)"
}

View File

@@ -0,0 +1,98 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Mapping network drive R: with persistent connection"
$networkPath = "\\192.168.88.231\RD"
$driveLetter = "R:"
Write-Host "[*] Creating persistent network drive mapping"
Write-Host " Target: $networkPath"
Write-Host " Drive: $driveLetter"
# Method 1: Try mapping without credentials first (anonymous/guest access)
Write-Host "[*] Attempting anonymous mapping..."
try {
$result = & net use $driveLetter $networkPath /persistent:yes 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host "[OK] Anonymous mapping successful!"
} else {
Write-Host " Anonymous mapping failed, will require manual credentials"
}
} catch {
Write-Host " Exception during anonymous mapping"
}
# Check if mapping was successful
$driveCheck = Get-WmiObject -Class Win32_LogicalDisk | Where-Object { $_.DeviceID -eq $driveLetter }
if ($driveCheck -and $driveCheck.DriveType -eq 4) {
Write-Host "[OK] Network drive R: successfully mapped!"
Write-Host " Provider: $($driveCheck.ProviderName)"
# Test access
try {
$testAccess = Test-Path "${driveLetter}\"
if ($testAccess) {
Write-Host "[OK] Drive R: is accessible"
# Try to list contents
$items = Get-ChildItem "${driveLetter}\" -ErrorAction SilentlyContinue | Select-Object -First 3
if ($items) {
Write-Host " Found $($items.Count) items in the drive"
} else {
Write-Host " Drive appears empty or no read permission"
}
} else {
Write-Host "[!] Drive R: mapped but not accessible"
}
} catch {
Write-Host "[!] Cannot test drive access: $($_.Exception.Message)"
}
} else {
Write-Host "[!] Network drive mapping incomplete"
Write-Host ""
Write-Host "Manual mapping required:"
Write-Host "1. Open File Explorer"
Write-Host "2. Right-click 'This PC' > Map network drive"
Write-Host "3. Drive: R:"
Write-Host "4. Folder: \\192.168.88.231\RD"
Write-Host "5. Check 'Reconnect at sign-in'"
Write-Host "6. Enter credentials when prompted"
Write-Host ""
Write-Host "Or use command line:"
Write-Host "net use R: \\192.168.88.231\RD /user:username /persistent:yes"
}
# Create a batch file for easy manual mapping
$batchContent = @"
@echo off
echo Mapping network drive R: to \\192.168.88.231\RD
echo.
echo If prompted, enter the username and password for 192.168.88.231
echo.
net use R: \\192.168.88.231\RD /persistent:yes
echo.
if %errorlevel%==0 (
echo Success! Drive R: mapped successfully.
explorer R:\
) else (
echo Mapping failed. Please check credentials and network connectivity.
)
pause
"@
$batchPath = "C:\Users\User\Desktop\Map-Drive-R.bat"
$batchContent | Out-File -FilePath $batchPath -Encoding ASCII
Write-Host "[*] Created manual mapping batch file: Map-Drive-R.bat"
Write-Host ""
Write-Host "Network drive setup complete!"
Write-Host ""
Write-Host "If R: drive is not visible:"
Write-Host "1. Double-click 'Map-Drive-R.bat' on User's desktop"
Write-Host "2. Enter network credentials when prompted"
Write-Host "3. Drive R: will appear in File Explorer"

View File

@@ -0,0 +1,96 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
$ns = 'C:\Program Files\NirSoft'
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$hostname = $env:COMPUTERNAME
$outDir = Join-Path $env:TEMP "nirsoft-dump-$hostname-$stamp"
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
function Run-Tool {
param(
[string]$Name,
[string]$Exe,
[string[]]$ArgList,
[int]$TimeoutSec = 60
)
$path = Join-Path $ns "$Name\$Exe"
if (-not (Test-Path $path)) {
Write-Host "[skip] $Name not installed"
return
}
Write-Host "[*] $Name"
try {
$p = Start-Process -FilePath $path -ArgumentList $ArgList -Wait -PassThru -WindowStyle Hidden
if ($p.ExitCode -ne 0) { Write-Host " (exit $($p.ExitCode))" }
} catch {
Write-Host " [!] $($_.Exception.Message)"
}
}
# === NirSoft CSV dumps ===
Run-Tool 'BlueScreenView' 'BlueScreenView.exe' @('/scomma', (Join-Path $outDir 'bluescreen.csv'))
Run-Tool 'LastActivityView' 'LastActivityView.exe' @('/scomma', (Join-Path $outDir 'lastactivity.csv'))
Run-Tool 'WhatInStartup' 'WhatInStartup.exe' @('/scomma', (Join-Path $outDir 'startup.csv'))
Run-Tool 'OpenedFilesView' 'OpenedFilesView.exe' @('/scomma', (Join-Path $outDir 'opened-files.csv'))
Run-Tool 'InstalledAppView' 'InstalledAppView.exe' @('/scomma', (Join-Path $outDir 'installed-apps.csv'))
Run-Tool 'DevManView' 'DevManView.exe' @('/scomma', (Join-Path $outDir 'devices.csv'))
Run-Tool 'USBDeview' 'USBDeview.exe' @('/scomma', (Join-Path $outDir 'usb-history.csv'))
Run-Tool 'TurnedOnTimesView' 'TurnedOnTimesView.exe' @('/scomma', (Join-Path $outDir 'uptime.csv'))
Run-Tool 'CurrPorts' 'cports.exe' @('/scomma', (Join-Path $outDir 'ports.csv'))
Run-Tool 'WifiInfoView' 'WifiInfoView.exe' @('/scomma', (Join-Path $outDir 'wifi-nearby.csv'))
Run-Tool 'WirelessNetView' 'WirelessNetView.exe' @('/scomma', (Join-Path $outDir 'wifi-tracking.csv'))
Run-Tool 'DNSDataView' 'DNSDataView.exe' @('/scomma', (Join-Path $outDir 'dns-cache.csv'))
# === Native Windows snapshots ===
Write-Host ""
Write-Host "[*] Native Windows snapshots"
& systeminfo.exe | Out-File (Join-Path $outDir 'systeminfo.txt') -Encoding UTF8
& ipconfig.exe /all | Out-File (Join-Path $outDir 'ipconfig.txt') -Encoding UTF8
& netstat.exe -ano | Out-File (Join-Path $outDir 'netstat.txt') -Encoding UTF8
Get-Process | Select-Object Id,ProcessName,CPU,WS,@{n='WS_MB';e={[math]::Round($_.WS/1MB,1)}},Path,StartTime |
Export-Csv -Path (Join-Path $outDir 'processes.csv') -NoTypeInformation -Encoding UTF8
Get-Service | Select-Object Name,DisplayName,Status,StartType |
Export-Csv -Path (Join-Path $outDir 'services.csv') -NoTypeInformation -Encoding UTF8
Get-ScheduledTask | Select-Object TaskPath,TaskName,State,Author |
Export-Csv -Path (Join-Path $outDir 'scheduled-tasks.csv') -NoTypeInformation -Encoding UTF8
# Recent error/warning events (System + Application, last 24h)
Get-WinEvent -FilterHashtable @{LogName='System'; Level=1,2,3; StartTime=(Get-Date).AddHours(-24)} -MaxEvents 500 -ErrorAction SilentlyContinue |
Select-Object TimeCreated,Id,LevelDisplayName,ProviderName,Message |
Export-Csv -Path (Join-Path $outDir 'events-system-24h.csv') -NoTypeInformation -Encoding UTF8
Get-WinEvent -FilterHashtable @{LogName='Application'; Level=1,2,3; StartTime=(Get-Date).AddHours(-24)} -MaxEvents 500 -ErrorAction SilentlyContinue |
Select-Object TimeCreated,Id,LevelDisplayName,ProviderName,Message |
Export-Csv -Path (Join-Path $outDir 'events-application-24h.csv') -NoTypeInformation -Encoding UTF8
# === Summary file ===
@"
=== Nirsoft + System Dump ===
Host: $hostname
Timestamp: $stamp
User running: $env:USERDOMAIN\$env:USERNAME
OS: $((Get-CimInstance Win32_OperatingSystem).Caption) $((Get-CimInstance Win32_OperatingSystem).Version)
Boot time: $((Get-CimInstance Win32_OperatingSystem).LastBootUpTime)
Uptime: $((Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime)
Files in this archive:
$((Get-ChildItem $outDir | Sort-Object Name | ForEach-Object { " - $($_.Name) ($(if ($_.Length) { '{0:N0}' -f $_.Length } else { '-' }) bytes)" }) -join "`r`n")
"@ | Out-File (Join-Path $outDir '_summary.txt') -Encoding UTF8
# === Zip and announce ===
$zipPath = "$outDir.zip"
Compress-Archive -Path (Join-Path $outDir '*') -DestinationPath $zipPath -Force
$zipSize = (Get-Item $zipPath).Length
Write-Host ""
Write-Host "====================================="
Write-Host "DUMP_ZIP: $zipPath"
Write-Host "DUMP_SIZE: $zipSize"
Write-Host "====================================="
# Optional cleanup of the uncompressed dir
Remove-Item $outDir -Recurse -Force -ErrorAction SilentlyContinue

View File

@@ -0,0 +1,72 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Pin RDP connection to taskbar"
# File paths
$rdpFile = "C:\Users\User\Desktop\Remote-Desktop.rdp"
$shortcutPath = "C:\Users\User\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Remote Desktop.lnk"
# Check if RDP file exists
if (-not (Test-Path $rdpFile)) {
Write-Host "[!] RDP file not found: $rdpFile"
exit 1
}
Write-Host "[*] Creating Start Menu shortcut"
# Create WScript.Shell object
$WshShell = New-Object -comObject WScript.Shell
# Create shortcut
$Shortcut = $WshShell.CreateShortcut($shortcutPath)
$Shortcut.TargetPath = "mstsc.exe"
$Shortcut.Arguments = "`"$rdpFile`""
$Shortcut.WorkingDirectory = "C:\Windows\System32"
$Shortcut.IconLocation = "mstsc.exe,0"
$Shortcut.Description = "Remote Desktop Connection"
$Shortcut.WindowStyle = 1
$Shortcut.Save()
Write-Host " Shortcut created: $shortcutPath"
# Pin to taskbar method
Write-Host "[*] Attempting to pin to taskbar"
try {
# Method 1: Try using verb
$shell = New-Object -ComObject Shell.Application
$folder = $shell.Namespace((Split-Path $shortcutPath))
$item = $folder.ParseName((Split-Path $shortcutPath -Leaf))
$verbs = $item.Verbs()
$pinVerb = $verbs | Where-Object { $_.Name -match "Pin to taskbar|taskbar" }
if ($pinVerb) {
Write-Host " Found pin verb: $($pinVerb.Name)"
$pinVerb.DoIt()
Write-Host "[OK] Successfully pinned to taskbar"
} else {
Write-Host "[!] Pin to taskbar verb not found"
Write-Host "Manual steps:"
Write-Host "1. Open Start Menu"
Write-Host "2. Find 'Remote Desktop' shortcut"
Write-Host "3. Right-click > Pin to taskbar"
}
} catch {
Write-Host "[!] Auto-pin failed: $($_.Exception.Message)"
Write-Host "Please pin manually from Start Menu"
}
# Optionally remove desktop RDP file
Write-Host "[*] Cleaning up desktop RDP file"
try {
Remove-Item $rdpFile -Force
Write-Host " Desktop RDP file removed"
} catch {
Write-Host " Desktop RDP file kept"
}
Write-Host ""
Write-Host "[OK] Setup complete! Check Start Menu for Remote Desktop shortcut"

View File

@@ -0,0 +1,91 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'SilentlyContinue'
function Section($title) {
Write-Host ''
Write-Host ('=' * 6) $title ('=' * 6) -ForegroundColor Cyan
}
Section 'Computer'
Get-ComputerInfo -Property CsName,CsDomain,CsManufacturer,CsModel,
WindowsProductName,OsVersion,OsBuildNumber,OsArchitecture,OsInstallDate,
CsNumberOfProcessors,CsNumberOfLogicalProcessors,OsTotalVisibleMemorySize,
CsUserName,TimeZone | Format-List
Section 'Boot Time'
(Get-CimInstance Win32_OperatingSystem).LastBootUpTime
Section 'Local Users'
Get-LocalUser | Select-Object Name,Enabled,LastLogon,Description | Format-Table -AutoSize
Section 'Administrators Group'
Get-LocalGroupMember -Group Administrators |
Select-Object Name,ObjectClass,PrincipalSource | Format-Table -AutoSize
Section 'Disks'
Get-Volume | Where-Object DriveLetter | Select-Object DriveLetter,FileSystemLabel,
@{n='Size(GB)';e={[math]::Round($_.Size / 1GB, 1)}},
@{n='Free(GB)';e={[math]::Round($_.SizeRemaining / 1GB, 1)}} |
Format-Table -AutoSize
Section 'IPv4 Addresses'
Get-NetIPAddress -AddressFamily IPv4 |
Where-Object { $_.InterfaceAlias -notmatch 'Loopback' } |
Select-Object InterfaceAlias,IPAddress,PrefixLength | Format-Table -AutoSize
Section 'Listening TCP Ports'
Get-NetTCPConnection -State Listen |
Select-Object LocalAddress,LocalPort,OwningProcess |
Sort-Object LocalPort -Unique | Format-Table -AutoSize
Section 'Firewall Profiles'
Get-NetFirewallProfile |
Select-Object Name,Enabled,DefaultInboundAction,DefaultOutboundAction |
Format-Table -AutoSize
Section 'SMB Shares'
Get-SmbShare | Select-Object Name,Path,Description | Format-Table -AutoSize
Section 'Defender'
Get-MpComputerStatus |
Select-Object AMRunningMode,AntivirusEnabled,RealTimeProtectionEnabled,
AMEngineVersion,AntivirusSignatureLastUpdated | Format-List
Section 'Installed Apps (non-Microsoft)'
$uninstallPaths = @(
'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
Get-ItemProperty $uninstallPaths |
Where-Object { $_.DisplayName -and $_.Publisher -notmatch 'Microsoft' } |
Select-Object DisplayName,DisplayVersion,Publisher,InstallDate |
Sort-Object DisplayName | Format-Table -AutoSize
Section 'Startup Commands'
Get-CimInstance Win32_StartupCommand |
Select-Object Name,Command,Location,User | Format-Table -AutoSize
Section 'Scheduled Tasks (non-Microsoft, enabled)'
Get-ScheduledTask |
Where-Object { $_.State -ne 'Disabled' -and $_.TaskPath -notlike '\Microsoft\*' } |
Select-Object TaskPath,TaskName,State | Format-Table -AutoSize
Section 'SSH Services'
Get-Service sshd,ssh-agent | Format-Table Name,Status,StartType -AutoSize
Section 'Recent Logons (Security 4624, last 48h)'
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624; StartTime=(Get-Date).AddHours(-48)} -MaxEvents 50 |
ForEach-Object {
$xml = [xml]$_.ToXml()
$d = @{}
$xml.Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_.'#text' }
[pscustomobject]@{
Time = $_.TimeCreated
LogonType = $d['LogonType']
User = "$($d['TargetDomainName'])\$($d['TargetUserName'])"
IP = $d['IpAddress']
Process = $d['ProcessName']
}
} |
Where-Object { $_.User -notmatch 'SYSTEM|ANONYMOUS|LOCAL SERVICE|NETWORK SERVICE|DWM-|UMFD-|\$$' } |
Format-Table -AutoSize

View File

@@ -0,0 +1,102 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
$configPath = Join-Path $PSScriptRoot 'remove-apps-config.json'
if (-not (Test-Path $configPath)) { throw "Config not found: $configPath" }
$cfg = Get-Content $configPath -Raw -Encoding UTF8 | ConvertFrom-Json
$results = @()
function Record([string]$name, [string]$result, [string]$detail='') {
$script:results += [pscustomobject]@{ Name = $name; Result = $result; Detail = $detail }
}
Write-Host "===== Removing Appx packages ====="
foreach ($name in @($cfg.RemoveAppx)) {
$pkgs = @(Get-AppxPackage -AllUsers -Name $name -ErrorAction SilentlyContinue)
$prov = @(Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -eq $name })
if ($pkgs.Count -eq 0 -and $prov.Count -eq 0) {
Write-Host "[=] $name : not installed"
Record $name 'not-installed'
continue
}
foreach ($p in $pkgs) {
try {
Write-Host "[*] Remove-AppxPackage $($p.PackageFullName)"
Remove-AppxPackage -AllUsers -Package $p.PackageFullName -ErrorAction Stop
} catch {
# 0x80073D19 = NonRemovable system package. Worth noting but often unavoidable.
if ($_.Exception.Message -match '0x80073D19|NonRemovable') {
Write-Host "[!] $name marked NonRemovable by Windows - skipping"
Record $name 'nonremovable' $_.Exception.Message
} else {
Write-Host "[!] $name install removal failed: $($_.Exception.Message)"
Record $name 'failed-install' $_.Exception.Message
}
}
}
foreach ($p in $prov) {
try {
Remove-AppxProvisionedPackage -Online -PackageName $p.PackageName -ErrorAction Stop | Out-Null
Write-Host "[*] Remove-AppxProvisionedPackage $($p.PackageName)"
} catch {
# Provisioned removal often fails silently when package was already deprovisioned by other tools.
# Only worth logging, not flagging as a hard failure.
}
}
# Verify post-state
$after = @(Get-AppxPackage -AllUsers -Name $name -ErrorAction SilentlyContinue)
if ($after.Count -eq 0) {
Record $name 'removed'
} elseif (($results | Where-Object Name -eq $name | Select-Object -Last 1).Result -ne 'nonremovable') {
Record $name 'still-present' "after removal attempt: $(($after | Select -Expand PackageFullName) -join ',')"
}
}
Write-Host ""
Write-Host "===== Office (M365) removal ====="
if ($cfg.RemoveOffice) {
$c2rClient = 'C:\Program Files\Common Files\microsoft shared\ClickToRun\OfficeClickToRun.exe'
if (Test-Path $c2rClient) {
Write-Host "[*] Click-to-Run detected - running silent uninstall"
$p = Start-Process -FilePath $c2rClient -ArgumentList 'scenario=uninstall','sourcetype=None','DisplayLevel=False' -Wait -PassThru
Write-Host "[=] OfficeClickToRun exited $($p.ExitCode)"
} else {
Write-Host "[=] No Click-to-Run Office present"
}
$anyOfficeAppx = $false
foreach ($pat in @('Microsoft.MicrosoftOfficeHub','Microsoft.Office.*','Microsoft.OutlookForWindows')) {
$hit = @(Get-AppxPackage -AllUsers -Name $pat -ErrorAction SilentlyContinue)
foreach ($p in $hit) {
$anyOfficeAppx = $true
try {
Write-Host "[*] Remove-AppxPackage $($p.PackageFullName)"
Remove-AppxPackage -AllUsers -Package $p.PackageFullName -ErrorAction Stop
Record $p.Name 'removed'
} catch {
Write-Host "[!] $($p.Name) failed: $($_.Exception.Message)"
Record $p.Name 'failed-install' $_.Exception.Message
}
}
}
if ((-not (Test-Path $c2rClient)) -and (-not $anyOfficeAppx)) {
Write-Host "[=] No Office / M365 traces found - nothing to do"
}
}
Write-Host ""
Write-Host "===== Summary ====="
$byResult = $results | Group-Object Result | Sort-Object Name
foreach ($g in $byResult) {
Write-Host ("{0,-15}: {1}" -f $g.Name, $g.Count)
}
$problem = $results | Where-Object { $_.Result -in 'failed-install','still-present' }
if ($problem) {
Write-Host ""
Write-Host "Needs attention:"
$problem | ForEach-Object { Write-Host " - $($_.Name) [$($_.Result)] $($_.Detail)" }
}

View File

@@ -0,0 +1,82 @@
param(
[ValidateSet('Apply','Revert')]
[string]$Mode = 'Apply',
[switch]$SkipDownload # use existing C:\Users\Admin\RemoveWindowsAi.ps1 instead of re-downloading
)
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
# 1. Must be Windows PowerShell 5.1, NOT pwsh 7+
if ($PSVersionTable.PSVersion.Major -ge 7) {
throw "This wrapper must run under Windows PowerShell 5.1 (powershell.exe), not pwsh $($PSVersionTable.PSVersion). Relaunch explicitly with powershell.exe."
}
# 2. Must have Administrator token
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
throw "Current session is NOT running as Administrator. RemoveWindowsAi.ps1 requires admin and its self-elevation (UAC RunAs) will fail over SSH. Ensure the SSH user has full admin token."
}
# 3. Fetch upstream script
$workDir = Join-Path $env:TEMP 'RemoveWindowsAI'
$scriptPath = Join-Path $workDir 'RemoveWindowsAi.ps1'
$logPath = Join-Path $workDir ("run-$Mode-$(Get-Date -Format 'yyyyMMdd-HHmmss').log")
New-Item -ItemType Directory -Force -Path $workDir | Out-Null
if (-not $SkipDownload) {
$url = 'https://raw.githubusercontent.com/zoicware/RemoveWindowsAI/main/RemoveWindowsAi.ps1'
Write-Host "[*] Downloading $url"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $url -OutFile $scriptPath -UseBasicParsing
if ((Get-Item $scriptPath).Length -lt 100KB) {
throw "Downloaded script seems too small ($((Get-Item $scriptPath).Length) bytes)"
}
# PowerShell 5.1 reads files without BOM using the system ANSI code page (CP950 on zh-TW),
# which mangles non-ASCII content. Force UTF-8 by prepending a BOM if not already present.
$bytes = [IO.File]::ReadAllBytes($scriptPath)
$hasBom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF
if (-not $hasBom) {
$bom = [byte[]](0xEF, 0xBB, 0xBF)
[IO.File]::WriteAllBytes($scriptPath, $bom + $bytes)
Write-Host "[*] Added UTF-8 BOM"
}
Write-Host "[*] Saved -> $scriptPath ($((Get-Item $scriptPath).Length) bytes)"
} elseif (-not (Test-Path $scriptPath)) {
throw "-SkipDownload set but $scriptPath does not exist"
}
# 4. Build args based on mode
$psArgs = @('-NoProfile','-ExecutionPolicy','Bypass','-File', $scriptPath, '-nonInteractive', '-EnableLogging')
if ($Mode -eq 'Apply') {
$psArgs += @('-AllOptions','-backupMode')
Write-Host "[*] Mode=Apply: -AllOptions -backupMode (backup saved for later revert)"
} else {
$psArgs += @('-AllOptions','-revertMode')
Write-Host "[*] Mode=Revert: -AllOptions -revertMode (requires prior backup)"
}
# 5. Execute and tee output to log
Write-Host "[*] Executing: powershell.exe $($psArgs -join ' ')"
Write-Host "[*] Log -> $logPath"
Write-Host ('-' * 60)
$proc = Start-Process -FilePath 'powershell.exe' -ArgumentList $psArgs `
-NoNewWindow -Wait -PassThru `
-RedirectStandardOutput $logPath -RedirectStandardError "$logPath.err"
Write-Host ('-' * 60)
Get-Content $logPath -ErrorAction SilentlyContinue | Select-Object -Last 80
if (Test-Path "$logPath.err") {
$errs = Get-Content "$logPath.err"
if ($errs) {
Write-Host "--- stderr ---"
$errs
}
}
Write-Host ""
Write-Host "[=] Exit code: $($proc.ExitCode)"
Write-Host "[=] Full log: $logPath"
Write-Host "[!] A reboot is recommended after this operation."
exit $proc.ExitCode

View File

@@ -0,0 +1,51 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
# --- 1. Rename local account 'user' -> 'User' ---
$src = 'user'
$dst = 'User'
$u = Get-LocalUser -Name $src -ErrorAction SilentlyContinue
if ($u) {
if ($u.Name -ceq $dst) {
Write-Host "[=] Account is already '$dst'"
} else {
Write-Host "[*] Renaming local account '$($u.Name)' -> '$dst'"
Rename-LocalUser -Name $src -NewName $dst
Write-Host "[OK] Renamed"
}
} else {
$already = Get-LocalUser -Name $dst -ErrorAction SilentlyContinue
if ($already) {
Write-Host "[=] Account '$dst' already exists (no '$src' found). Nothing to rename."
} else {
throw "Neither '$src' nor '$dst' exists as local user"
}
}
# --- 2. Hide 'Admin' from sign-in screen ---
$listPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList'
if (-not (Test-Path $listPath)) {
New-Item -Path $listPath -Force | Out-Null
Write-Host "[*] Created $listPath"
}
New-ItemProperty -Path $listPath -Name 'Admin' -Value 0 -PropertyType DWord -Force | Out-Null
Write-Host "[OK] Hidden 'Admin' from sign-in screen (SpecialAccounts\UserList\Admin = 0)"
Write-Host ""
Write-Host "=== Post-state ==="
Get-LocalUser | Select-Object Name,Enabled,LastLogon | Format-Table -AutoSize
$lst = Get-ItemProperty -Path $listPath -ErrorAction SilentlyContinue
if ($lst) {
Write-Host "UserList values:"
$lst.PSObject.Properties | Where-Object { $_.Name -notmatch '^PS' } | ForEach-Object {
Write-Host (" {0} = {1}" -f $_.Name, $_.Value)
}
}
Write-Host ""
Write-Host "Notes:"
Write-Host " - Account SIDs don't change. C:\Users\user profile folder stays with lowercase name"
Write-Host " (NTFS is case-insensitive so all apps keep working)."
Write-Host " - Admin can still sign in: click 'Other user' on the lock screen and type 'Admin'."

View File

@@ -0,0 +1,97 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Setting desktop icons for User account"
# Icon GUIDs
$computerGUID = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
$controlPanelGUID = "{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}"
$recycleGUID = "{645FF040-5081-101B-9F08-00AA002F954E}"
# Get User SID
try {
$user = New-Object System.Security.Principal.NTAccount("User")
$userSID = $user.Translate([System.Security.Principal.SecurityIdentifier]).Value
Write-Host "[*] User SID: $userSID"
} catch {
Write-Host "[!] Could not get user SID, trying alternative method"
# Try to get SID from registry
$userProfiles = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
foreach ($profile in $userProfiles) {
$profileData = Get-ItemProperty -Path $profile.PSPath -ErrorAction SilentlyContinue
if ($profileData.ProfileImagePath -like "*\User") {
$userSID = $profile.PSChildName
Write-Host "[*] Found User SID: $userSID"
break
}
}
}
if (-not $userSID) {
Write-Host "[!] Could not determine User SID" -ForegroundColor Red
exit 1
}
# Check if user hive is loaded (user is logged in)
$userHivePath = "HKU:\$userSID"
if (Test-Path $userHivePath) {
Write-Host "[*] User is currently logged in, modifying active hive"
$desktopIconsPath = "$userHivePath\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"
$classicIconsPath = "$userHivePath\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu"
# Ensure registry paths exist
foreach ($path in @($desktopIconsPath, $classicIconsPath)) {
if (-not (Test-Path $path)) {
New-Item -Path $path -Force | Out-Null
Write-Host " Created registry path"
}
}
# Enable desktop icons
$icons = @{
"Computer" = $computerGUID
"Control Panel" = $controlPanelGUID
"Recycle Bin" = $recycleGUID
}
foreach ($iconName in $icons.Keys) {
$guid = $icons[$iconName]
Set-ItemProperty -Path $desktopIconsPath -Name $guid -Value 0 -Type DWord
Set-ItemProperty -Path $classicIconsPath -Name $guid -Value 0 -Type DWord
Write-Host " Enabled: $iconName"
}
Write-Host "[*] Refreshing desktop for logged-in user"
# Create a script to run as the user to refresh the desktop
$refreshScript = @"
Add-Type -TypeDefinition 'using System; using System.Runtime.InteropServices; public class Win32 { [DllImport("user32.dll")] public static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, bool bErase); [DllImport("user32.dll")] public static extern IntPtr GetDesktopWindow(); }'
[Win32]::InvalidateRect([Win32]::GetDesktopWindow(), [IntPtr]::Zero, $true)
"@
try {
# Try to refresh the desktop
Invoke-Expression $refreshScript
Write-Host " Desktop refresh attempted"
} catch {
Write-Host " Could not refresh desktop automatically"
}
Write-Host ""
Write-Host "[OK] Desktop icons configured for active User session"
Write-Host "Icons should appear shortly. If not visible:"
Write-Host "1. Right-click desktop > Refresh"
Write-Host "2. Log out and log back in as User"
} else {
Write-Host "[*] User is not currently logged in"
Write-Host "[!] Cannot modify registry while user is logged out"
Write-Host ""
Write-Host "Please:"
Write-Host "1. Log in as User"
Write-Host "2. Run this script again"
Write-Host "3. Or reboot and log in as User, then run the script"
}

View File

@@ -0,0 +1,138 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Setting up network drive R: and removing desktop shortcut"
# File paths
$shortcutPath = "C:\Users\User\Desktop\Network Share (RD).lnk"
$networkPath = "\\192.168.88.231\rd"
$driveLetter = "R:"
Write-Host "[*] Step 1: Removing desktop shortcut"
if (Test-Path $shortcutPath) {
try {
Remove-Item $shortcutPath -Force
Write-Host "[OK] Desktop shortcut removed: Network Share (RD).lnk"
} catch {
Write-Host "[!] Failed to remove shortcut: $($_.Exception.Message)"
}
} else {
Write-Host " Desktop shortcut not found (already removed)"
}
Write-Host "[*] Step 2: Checking current network drives"
# Check existing drives
$existingDrives = Get-WmiObject -Class Win32_LogicalDisk | Select-Object DeviceID, DriveType, ProviderName
$networkDrives = $existingDrives | Where-Object { $_.DriveType -eq 4 }
if ($networkDrives) {
Write-Host " Current network drives:"
foreach ($drive in $networkDrives) {
Write-Host " - $($drive.DeviceID) -> $($drive.ProviderName)"
}
} else {
Write-Host " No network drives currently mapped"
}
Write-Host "[*] Step 3: Mapping network drive R:"
# Check if R: is already in use
$rDriveExists = $existingDrives | Where-Object { $_.DeviceID -eq $driveLetter }
if ($rDriveExists) {
Write-Host " R: drive already exists"
if ($rDriveExists.ProviderName -eq $networkPath) {
Write-Host "[OK] R: is already mapped to $networkPath"
exit 0
} else {
Write-Host " R: is mapped to: $($rDriveExists.ProviderName)"
Write-Host " Disconnecting existing mapping..."
try {
& net use $driveLetter /delete /yes
Write-Host " Existing R: mapping removed"
} catch {
Write-Host "[!] Failed to disconnect R: drive"
}
}
}
Write-Host " Mapping $networkPath to $driveLetter"
# Test network connectivity first
Write-Host "[*] Step 4: Testing network connectivity"
try {
$testConnection = Test-NetConnection -ComputerName "192.168.88.231" -Port 445 -WarningAction SilentlyContinue
if ($testConnection.TcpTestSucceeded) {
Write-Host "[OK] Network connection to 192.168.88.231:445 successful"
} else {
Write-Host "[!] Warning: Cannot reach 192.168.88.231:445"
}
} catch {
Write-Host "[!] Network test failed: $($_.Exception.Message)"
}
# Map the network drive
Write-Host "[*] Step 5: Creating network drive mapping"
try {
# Use net use command for mapping
$result = & net use $driveLetter $networkPath 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host "[OK] Network drive mapped successfully!"
Write-Host " $driveLetter -> $networkPath"
# Verify the mapping
Start-Sleep -Seconds 2
$verification = Get-WmiObject -Class Win32_LogicalDisk | Where-Object { $_.DeviceID -eq $driveLetter }
if ($verification) {
Write-Host "[OK] Drive mapping verified"
Write-Host " Drive type: $($verification.DriveType) (4 = Network)"
Write-Host " Provider: $($verification.ProviderName)"
}
} else {
Write-Host "[!] Network drive mapping failed"
Write-Host " Error output: $result"
# Provide troubleshooting info
Write-Host ""
Write-Host "Possible solutions:"
Write-Host "1. Run as Administrator: net use R: \\192.168.88.231\rd"
Write-Host "2. With credentials: net use R: \\192.168.88.231\rd /user:username"
Write-Host "3. Check if the share exists and is accessible"
Write-Host "4. Verify network connectivity to 192.168.88.231"
}
} catch {
Write-Host "[!] Exception during mapping: $($_.Exception.Message)"
}
Write-Host ""
Write-Host "[*] Final status check"
# Final verification
$finalDrives = Get-WmiObject -Class Win32_LogicalDisk | Where-Object { $_.DriveType -eq 4 }
if ($finalDrives) {
Write-Host "Current network drives:"
foreach ($drive in $finalDrives) {
if ($drive.DeviceID -eq $driveLetter) {
Write-Host "[OK] $($drive.DeviceID) -> $($drive.ProviderName) (SUCCESS)"
} else {
Write-Host " $($drive.DeviceID) -> $($drive.ProviderName)"
}
}
} else {
Write-Host "No network drives mapped"
}
Write-Host ""
Write-Host "Setup complete!"
Write-Host "- Desktop shortcut removed"
Write-Host "- Network drive R: mapping attempted"
Write-Host ""
Write-Host "Access the network share via:"
Write-Host "1. File Explorer > This PC > R: drive"
Write-Host "2. Address bar: R:\"
Write-Host "3. Run dialog: R:\"

View File

@@ -0,0 +1,102 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Setting up network share access"
# Network share path
$sharePath = "\\192.168.88.231\rd"
$shortcutPath = "C:\Users\User\Desktop\Network Share (RD).lnk"
Write-Host "[*] Testing connection to network share"
Write-Host " Target: $sharePath"
# Test network connectivity
try {
$testConnection = Test-NetConnection -ComputerName "192.168.88.231" -Port 445 -WarningAction SilentlyContinue
if ($testConnection.TcpTestSucceeded) {
Write-Host "[OK] Network connection successful (Port 445 accessible)"
} else {
Write-Host "[!] Warning: Port 445 not accessible - SMB might be blocked"
}
} catch {
Write-Host "[!] Network test failed: $($_.Exception.Message)"
}
Write-Host "[*] Creating desktop shortcut to network share"
# Create shortcut using WScript.Shell
try {
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut($shortcutPath)
$Shortcut.TargetPath = $sharePath
$Shortcut.WorkingDirectory = $sharePath
$Shortcut.IconLocation = "shell32.dll,4" # Folder icon
$Shortcut.Description = "Network Share - RD"
$Shortcut.Save()
Write-Host "[OK] Desktop shortcut created: Network Share (RD).lnk"
} catch {
Write-Host "[!] Failed to create shortcut: $($_.Exception.Message)"
}
Write-Host "[*] Testing share access"
# Test if we can access the share
try {
if (Test-Path $sharePath) {
Write-Host "[OK] Network share is accessible"
# Try to list contents
$items = Get-ChildItem $sharePath -ErrorAction SilentlyContinue | Select-Object -First 5
if ($items) {
Write-Host " Found $($items.Count) items in share"
} else {
Write-Host " Share appears empty or no read permission"
}
} else {
Write-Host "[!] Network share not accessible"
Write-Host " Possible issues:"
Write-Host " - Share doesn't exist"
Write-Host " - No network access"
Write-Host " - Authentication required"
Write-Host " - SMB protocol blocked"
}
} catch {
Write-Host "[!] Error accessing share: $($_.Exception.Message)"
}
Write-Host "[*] Checking if drive mapping is needed"
# Check if we should map as network drive
$availableDrives = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3} | Select-Object -ExpandProperty DeviceID
$networkDrives = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DriveType -eq 4} | Select-Object -ExpandProperty DeviceID
Write-Host " Current network drives: $($networkDrives -join ', ')"
# Suggest mapping to Z: drive if not already used
if ("Z:" -notin ($availableDrives + $networkDrives)) {
Write-Host "[*] Attempting to map network drive Z:"
try {
& net use Z: $sharePath
Write-Host "[OK] Network drive Z: mapped successfully"
} catch {
Write-Host "[!] Drive mapping failed - may require credentials"
Write-Host " Manual mapping: net use Z: $sharePath /user:username"
}
} else {
Write-Host " Z: drive already in use"
}
Write-Host ""
Write-Host "[OK] Network share setup complete!"
Write-Host ""
Write-Host "Access methods:"
Write-Host "1. Double-click 'Network Share (RD).lnk' on desktop"
Write-Host "2. Type '$sharePath' in File Explorer address bar"
if ("Z:" -notin $availableDrives) {
Write-Host "3. Use Z: drive if mapping was successful"
}
Write-Host ""
Write-Host "If access is denied, you may need to:"
Write-Host "- Right-click shortcut > Run as administrator"
Write-Host "- Provide network credentials when prompted"

View File

@@ -0,0 +1,89 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Continue'
Write-Host "[*] Setting up RDP connection with saved credentials"
# RDP file path on desktop
$rdpFile = "C:\Users\User\Desktop\Remote-PC.rdp"
# RDP file content with credentials
$rdpContent = @"
screen mode id:i:2
use multimon:i:0
desktopwidth:i:1920
desktopheight:i:1080
session bpp:i:32
winposstr:s:0,3,0,0,800,600
compression:i:1
keyboardhook:i:2
audiocapturemode:i:0
videoplaybackmode:i:1
connection type:i:7
networkautodetect:i:1
bandwidthautodetect:i:1
displayconnectionbar:i:1
enableworkspacereconnect:i:0
disable wallpaper:i:0
allow font smoothing:i:0
allow desktop composition:i:0
disable full window drag:i:1
disable menu anims:i:1
disable themes:i:0
disable cursor setting:i:0
bitmapcachepersistenable:i:1
full address:s:192.168.88.21
audiomode:i:0
redirectprinters:i:1
redirectcomports:i:0
redirectsmartcards:i:1
redirectclipboard:i:1
redirectposdevices:i:0
autoreconnection enabled:i:1
authentication level:i:2
prompt for credentials:i:0
negotiate security layer:i:1
remoteapplicationmode:i:0
alternate shell:s:
shell working directory:s:
gatewayhostname:s:
gatewayusagemethod:i:4
gatewaycredentialssource:i:4
gatewayprofileusagemethod:i:0
promptcredentialonce:i:0
gatewaybrokeringtype:i:0
use redirection server name:i:0
rdgiskdcproxy:i:0
kdcproxyname:s:
drivestoredirect:s:
username:s:ChiaYing
domain:s:
"@
# Write RDP file
$rdpContent | Out-File -FilePath $rdpFile -Encoding UTF8
Write-Host "[*] RDP file created: $rdpFile"
# Add credential to Windows Credential Manager
Write-Host "[*] Adding credentials to Windows Credential Manager"
try {
# Use cmdkey to add credential
& cmdkey /generic:"TERMSRV/192.168.88.21" /user:"ChiaYing" /pass:"!ChiaYing"
Write-Host "[OK] Credentials saved to Credential Manager"
} catch {
Write-Host "[!] Failed to save credentials: $($_.Exception.Message)"
}
# Verify the RDP file was created
if (Test-Path $rdpFile) {
$fileInfo = Get-Item $rdpFile
Write-Host "[OK] RDP file ready: $($fileInfo.Name) ($($fileInfo.Length) bytes)"
Write-Host ""
Write-Host "Usage:"
Write-Host "1. Double-click 'Remote-PC.rdp' on desktop"
Write-Host "2. Connection should start automatically with saved credentials"
Write-Host "3. If prompted for password, enter: !ChiaYing"
} else {
Write-Host "[!] Failed to create RDP file"
exit 1
}

View File

@@ -0,0 +1,150 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
$configPath = Join-Path $PSScriptRoot 'thunderbird-config.json'
if (-not (Test-Path $configPath)) { throw "Config not found: $configPath" }
$cfg = Get-Content $configPath -Raw -Encoding UTF8 | ConvertFrom-Json
$socketMap = @{ 'none' = 0; 'STARTTLS' = 2; 'SSL' = 3 }
$authMap = @{ 'normal' = 3; 'encrypted' = 4; 'ntlm' = 8; 'gssapi' = 7; 'oauth2' = 10 }
if (-not $socketMap.ContainsKey($cfg.Incoming.SocketType)) {
throw "Incoming.SocketType must be one of: $($socketMap.Keys -join ', ')"
}
if (-not $socketMap.ContainsKey($cfg.Outgoing.SocketType)) {
throw "Outgoing.SocketType must be one of: $($socketMap.Keys -join ', ')"
}
if (-not $authMap.ContainsKey($cfg.Incoming.AuthMethod)) {
throw "Incoming.AuthMethod must be one of: $($authMap.Keys -join ', ')"
}
if (-not $authMap.ContainsKey($cfg.Outgoing.AuthMethod)) {
throw "Outgoing.AuthMethod must be one of: $($authMap.Keys -join ', ')"
}
$winUser = $cfg.WindowsUser
$appRoot = "C:\Users\$winUser\AppData\Roaming\Thunderbird"
$profilesDir = Join-Path $appRoot 'Profiles'
$profileName = $cfg.ProfileName
$profilePath = Join-Path $profilesDir $profileName
$iniPath = Join-Path $appRoot 'profiles.ini'
if (-not (Test-Path "C:\Users\$winUser")) {
throw "Windows user '$winUser' not found (no C:\Users\$winUser folder)"
}
# Stop any running Thunderbird so we don't fight it
Get-Process thunderbird -ErrorAction SilentlyContinue | Stop-Process -Force
New-Item -ItemType Directory -Force -Path $profilePath | Out-Null
$incSocket = $socketMap[$cfg.Incoming.SocketType]
$outSocket = $socketMap[$cfg.Outgoing.SocketType]
$incAuth = $authMap[$cfg.Incoming.AuthMethod]
$outAuth = $authMap[$cfg.Outgoing.AuthMethod]
$prefs = @"
// Generated by setup-thunderbird.ps1
user_pref("mail.shell.checkDefaultClient", false);
user_pref("mailnews.start_page.enabled", false);
user_pref("mail.accountmanager.accounts", "account1,account2");
user_pref("mail.accountmanager.defaultaccount", "account1");
user_pref("mail.accountmanager.localfoldersserver", "server2");
user_pref("mail.account.account1.identities", "id1");
user_pref("mail.account.account1.server", "server1");
user_pref("mail.account.account2.server", "server2");
user_pref("mail.server.server1.type", "$($cfg.Incoming.Type)");
user_pref("mail.server.server1.hostname", "$($cfg.Incoming.Hostname)");
user_pref("mail.server.server1.port", $($cfg.Incoming.Port));
user_pref("mail.server.server1.socketType", $incSocket);
user_pref("mail.server.server1.userName", "$($cfg.Incoming.Username)");
user_pref("mail.server.server1.authMethod", $incAuth);
user_pref("mail.server.server1.name", "$($cfg.Identity.Email)");
user_pref("mail.server.server1.login_at_startup", true);
user_pref("mail.server.server1.check_new_mail", true);
user_pref("mail.server.server2.type", "none");
user_pref("mail.server.server2.hostname", "Local Folders");
user_pref("mail.server.server2.name", "Local Folders");
user_pref("mail.server.server2.userName", "nobody");
user_pref("mail.identity.id1.fullName", "$($cfg.Identity.FullName)");
user_pref("mail.identity.id1.useremail", "$($cfg.Identity.Email)");
user_pref("mail.identity.id1.smtpServer", "smtp1");
user_pref("mail.identity.id1.valid", true);
user_pref("mail.smtpservers", "smtp1");
user_pref("mail.smtp.defaultserver", "smtp1");
user_pref("mail.smtpserver.smtp1.hostname", "$($cfg.Outgoing.Hostname)");
user_pref("mail.smtpserver.smtp1.port", $($cfg.Outgoing.Port));
user_pref("mail.smtpserver.smtp1.try_ssl", $outSocket);
user_pref("mail.smtpserver.smtp1.username", "$($cfg.Outgoing.Username)");
user_pref("mail.smtpserver.smtp1.authMethod", $outAuth);
user_pref("mail.smtpserver.smtp1.description", "$($cfg.Outgoing.Hostname)");
"@
$prefsPath = Join-Path $profilePath 'prefs.js'
Set-Content -Path $prefsPath -Value $prefs -Encoding UTF8
Write-Host "[*] Wrote prefs.js -> $prefsPath"
# profiles.ini: Thunderbird 72+ selects profile via [Install<HASH>] section, not Default=1 on Profile.
# Merge: preserve existing Profile/Install entries, force our profile as default everywhere.
$profileRelPath = "Profiles/$profileName"
if (Test-Path $iniPath) {
$iniRaw = Get-Content $iniPath -Raw
# Redirect any existing Install<HASH> block to our profile
$iniRaw = [regex]::Replace($iniRaw, '(?m)^Default=Profiles/[^\r\n]+', "Default=$profileRelPath")
# Clear Default=1 from other Profile sections so only ours is default
$iniRaw = [regex]::Replace($iniRaw, '(?ms)(\[Profile\d+\][^\[]*?Name=(?!' + [regex]::Escape($profileName) + ')[^\r\n]+[^\[]*?)Default=1\s*', '$1')
# If our Profile entry is missing, append it
if ($iniRaw -notmatch "(?m)^Name=$([regex]::Escape($profileName))\s*$") {
$nextIdx = 0
while ($iniRaw -match "(?m)^\[Profile$nextIdx\]") { $nextIdx++ }
$append = @"
[Profile$nextIdx]
Name=$profileName
IsRelative=1
Path=$profileRelPath
Default=1
"@
$iniRaw = $iniRaw.TrimEnd() + "`r`n" + $append + "`r`n"
}
Set-Content -Path $iniPath -Value $iniRaw -Encoding ASCII
Write-Host "[*] Merged profiles.ini -> $iniPath"
} else {
$ini = @"
[General]
StartWithLastProfile=1
Version=2
[Profile0]
Name=$profileName
IsRelative=1
Path=$profileRelPath
Default=1
"@
Set-Content -Path $iniPath -Value $ini -Encoding ASCII
Write-Host "[*] Wrote profiles.ini -> $iniPath"
}
# Also update installs.ini (Thunderbird 72+) if present
$installsIni = Join-Path $appRoot 'installs.ini'
if (Test-Path $installsIni) {
$raw = Get-Content $installsIni -Raw
$raw = [regex]::Replace($raw, '(?m)^Default=Profiles/[^\r\n]+', "Default=$profileRelPath")
Set-Content -Path $installsIni -Value $raw -Encoding ASCII
Write-Host "[*] Updated installs.ini -> $installsIni"
}
# If we're running as a different user than the profile target, fix ownership so they can read/write
if ($winUser -ne $env:USERNAME) {
Write-Host "[*] Adjusting ACL for '$winUser' on $appRoot"
& icacls $appRoot /grant "${winUser}:(OI)(CI)F" /T /Q | Out-Null
}
Write-Host ""
Write-Host "[OK] Thunderbird profile '$profileName' configured for Windows user '$winUser'"
Write-Host " Identity: $($cfg.Identity.FullName) <$($cfg.Identity.Email)>"
Write-Host " Incoming: $($cfg.Incoming.Type) $($cfg.Incoming.Hostname):$($cfg.Incoming.Port) ($($cfg.Incoming.SocketType))"
Write-Host " Outgoing: smtp $($cfg.Outgoing.Hostname):$($cfg.Outgoing.Port) ($($cfg.Outgoing.SocketType))"
Write-Host ""
Write-Host "Next step: log in as '$winUser', start Thunderbird; it will prompt for the password on first connection."

View File

@@ -0,0 +1,111 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'SilentlyContinue'
$pass = 0; $fail = 0
function Check($label, [bool]$ok, $detail='') {
if ($ok) { $script:pass++; $mark = '[OK] ' } else { $script:fail++; $mark = '[FAIL]' }
Write-Host ("{0} {1}" -f $mark, $label)
if ($detail) { Write-Host (" {0}" -f $detail) }
}
Write-Host "===== Services (expect removed) ====="
# Only actual AI services that RemoveWindowsAI targets.
foreach ($s in @('WSAIFabricSvc','AarSvc')) {
$svc = Get-Service -Name $s -ErrorAction SilentlyContinue
$detail = if ($svc) { "still present (Status=$($svc.Status))" } else { "gone" }
Check "service '$s' removed" (-not $svc) $detail
}
Write-Host ""
Write-Host "===== Appx packages (expect removed) ====="
foreach ($pat in @('Microsoft.Copilot','Microsoft.MicrosoftCopilot','Microsoft.Windows.Copilot','MicrosoftWindows.Client.AIX','MicrosoftWindows.Client.CoreAI')) {
$pkg = Get-AppxPackage -AllUsers -Name "$pat*" -ErrorAction SilentlyContinue
$detail = if ($pkg) { "still present: $(($pkg | Select -Expand Name) -join ',')" } else { "not installed" }
Check "Appx '$pat*' removed" (-not $pkg) $detail
}
Write-Host ""
Write-Host "===== Recall ====="
$recall = Get-WindowsOptionalFeature -Online -FeatureName 'Recall' -ErrorAction SilentlyContinue
if ($recall) {
Check "Recall optional feature disabled" ($recall.State -eq 'Disabled') "state=$($recall.State)"
} else {
Check "Recall optional feature absent" $true "feature not found"
}
$rct = @(Get-ScheduledTask -TaskPath '\Microsoft\Windows\WindowsAI\*' -ErrorAction SilentlyContinue)
$detail = if ($rct.Count -gt 0) { "remaining: $(($rct | Select -Expand TaskName) -join ',')" } else { "none" }
Check "WindowsAI scheduled tasks removed" ($rct.Count -eq 0) $detail
Write-Host ""
Write-Host "===== Policy registry ====="
# Copilot's turn-off flag is under HKCU (tool writes to current user hive).
# WindowsAI policy keys are machine-wide (HKLM).
$policies = @(
@{ Path = 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\WindowsCopilot'; Name = 'TurnOffWindowsCopilot'; Expect = 1 },
@{ Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI'; Name = 'DisableAIDataAnalysis'; Expect = 1 },
@{ Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI'; Name = 'DisableClickToDo'; Expect = 1 },
@{ Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI'; Name = 'AllowRecallEnablement'; Expect = 0 }
)
foreach ($p in $policies) {
$val = (Get-ItemProperty -Path $p.Path -Name $p.Name -ErrorAction SilentlyContinue).($p.Name)
$shortPath = $p.Path -replace '^HK..:\\SOFTWARE\\',''
Check "$shortPath : $($p.Name) == $($p.Expect)" ($val -eq $p.Expect) "actual=$val"
}
Write-Host ""
Write-Host "===== Notepad Rewrite (per-user, populated on first Notepad launch) ====="
# Key only appears after a user opens Notepad. Fail only if any user hive has RewriteEnabled=1.
$bad = @()
Get-ChildItem 'Registry::HKEY_USERS' -ErrorAction SilentlyContinue | ForEach-Object {
$np = "Registry::$($_.Name)\Software\Microsoft\Notepad"
$v = (Get-ItemProperty $np -Name RewriteEnabled -ErrorAction SilentlyContinue).RewriteEnabled
if ($v -eq 1) { $bad += "$($_.Name)=1" }
}
$d = if ($bad) { "enabled in: $($bad -join ',')" } else { "not enabled in any user hive" }
Check "Notepad Rewrite not enabled anywhere" (-not $bad) $d
Write-Host ""
Write-Host "===== IntegratedServicesRegionPolicySet (Copilot entries) ====="
$jsonPath = 'C:\Windows\System32\IntegratedServicesRegionPolicySet.json'
if (Test-Path $jsonPath) {
$j = Get-Content $jsonPath -Raw | ConvertFrom-Json
$copilot = @($j.policies | Where-Object { ($_ | ConvertTo-Json -Depth 3) -match '[Cc]opilot' })
$disabled = @($copilot | Where-Object { $_.defaultState -eq 'disabled' })
$ok = ($copilot.Count -gt 0) -and ($disabled.Count -eq $copilot.Count)
Check "all Copilot policies disabled" $ok "disabled $($disabled.Count) of $($copilot.Count) Copilot entries"
} else {
Check "IntegratedServicesRegionPolicySet.json present" $false "file missing"
}
Write-Host ""
Write-Host "===== Update cleanup safety net ====="
$uct = Get-ScheduledTask -TaskName '*RemoveAI*' -ErrorAction SilentlyContinue
$uctDetail = if ($uct) { "found: $($uct.TaskName), state=$($uct.State)" } else { "missing" }
Check "RemoveAI update-cleanup scheduled task exists" ([bool]$uct) $uctDetail
Write-Host ""
Write-Host "===== Leftover AI SystemApps (expect gone) ====="
# Only check SystemApps dirs and WindowsApps — DLLs in System32 are protected and not
# expected to be deleted; the services/executables are what matter.
$paths = @(
'C:\Windows\SystemApps\MicrosoftWindows.Client.CoPilot_cw5n1h2txyewy',
'C:\Windows\SystemApps\MicrosoftWindows.Client.AIX_cw5n1h2txyewy'
)
foreach ($p in $paths) {
$hit = Get-Item -Path $p -ErrorAction SilentlyContinue
$d = if ($hit) { "still exists" } else { "gone" }
Check "path gone: $p" (-not $hit) $d
}
$wap = @(Get-ChildItem 'C:\Program Files\WindowsApps' -Filter 'Microsoft.Copilot_*' -ErrorAction SilentlyContinue)
$d = if ($wap.Count -gt 0) { "$($wap.Count) dir(s)" } else { "none" }
Check "WindowsApps Microsoft.Copilot_* gone" ($wap.Count -eq 0) $d
Write-Host ""
Write-Host "===== Restore point ====="
$rps = Get-ComputerRestorePoint -ErrorAction SilentlyContinue | Where-Object { $_.Description -match 'RemoveWindowsAI' }
$rpDetail = if ($rps) { "found: $(($rps | Select -Expand Description) -join ',')" } else { "none" }
Check "RemoveWindowsAI restore point exists" ([bool]$rps) $rpDetail
Write-Host ""
Write-Host "===== Summary ====="
Write-Host ("PASS: {0} FAIL: {1}" -f $pass, $fail)

View File

@@ -0,0 +1,106 @@
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'SilentlyContinue'
$pass = 0; $fail = 0
function Check($label, [bool]$ok, $detail='') {
if ($ok) { $script:pass++; $mark = '[OK] ' } else { $script:fail++; $mark = '[FAIL]' }
Write-Host ("{0} {1}" -f $mark, $label)
if ($detail) { Write-Host (" {0}" -f $detail) }
}
$userHives = Get-ChildItem 'Registry::HKEY_USERS' |
Where-Object { $_.Name -match 'S-1-5-21-' -and $_.Name -notmatch '_Classes$' } |
ForEach-Object { $_.Name }
function Get-UserRegValue {
param([string]$SubPath, [string]$Name)
$hits = @()
foreach ($h in $userHives) {
$p = "Registry::$h\$SubPath"
$v = (Get-ItemProperty -Path $p -Name $Name -ErrorAction SilentlyContinue).$Name
if ($null -ne $v) { $hits += [pscustomobject]@{ Hive=$h; Value=$v } }
}
return $hits
}
Write-Host "===== Appx packages removed ====="
foreach ($name in @('Microsoft.GamingApp','Microsoft.XboxGameOverlay','Microsoft.XboxGamingOverlay','Microsoft.windowscommunicationsapps','Microsoft.People','Microsoft.OutlookForWindows','Microsoft.BingSearch','Microsoft.Copilot','Microsoft.StartExperiencesApp')) {
$pkg = Get-AppxPackage -AllUsers -Name $name -ErrorAction SilentlyContinue
$detail = if ($pkg) { "still present" } else { "gone" }
Check "Appx '$name' removed" (-not $pkg) $detail
}
Write-Host ""
Write-Host "===== Telemetry (HKLM) ====="
$val = (Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection' -Name AllowTelemetry).AllowTelemetry
Check "Policies\DataCollection\AllowTelemetry == 0" ($val -eq 0) "actual=$val"
Write-Host ""
Write-Host "===== Widgets / News & Interests (HKLM) ====="
$val = (Get-ItemProperty 'HKLM:\Software\Policies\Microsoft\Dsh' -Name AllowNewsAndInterests).AllowNewsAndInterests
Check "Dsh\AllowNewsAndInterests == 0" ($val -eq 0) "actual=$val"
Write-Host ""
Write-Host "===== GameDVR (HKLM policy + per-user) ====="
$val = (Get-ItemProperty 'HKLM:\Software\Policies\Microsoft\Windows\GameDVR' -Name AllowGameDVR).AllowGameDVR
Check "GameDVR policy AllowGameDVR == 0" ($val -eq 0) "actual=$val"
$userDVR = Get-UserRegValue -SubPath 'System\GameConfigStore' -Name 'GameDVR_Enabled'
$match = @($userDVR | Where-Object { $_.Value -eq 0 })
Check "per-user GameDVR_Enabled == 0" ($match.Count -gt 0) "disabled in $($match.Count)/$($userDVR.Count) user hives"
Write-Host ""
Write-Host "===== Update behavior ====="
$val = (Get-ItemProperty 'HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate\AU' -Name NoAutoRebootWithLoggedOnUsers).NoAutoRebootWithLoggedOnUsers
Check "WindowsUpdate\AU\NoAutoRebootWithLoggedOnUsers == 1" ($val -eq 1) "actual=$val"
Write-Host ""
Write-Host "===== Edge ads / Settings ads ====="
foreach ($c in @(
@{ Path='HKLM:\Software\Policies\Microsoft\Edge'; Name='ShowRecommendationsEnabled'; Expect=0 },
@{ Path='HKLM:\Software\Policies\Microsoft\Edge'; Name='HubsSidebarEnabled'; Expect=0 }
)) {
$val = (Get-ItemProperty -Path $c.Path -Name $c.Name -ErrorAction SilentlyContinue).($c.Name)
$short = $c.Path -replace '^HKLM:\\',''
Check "$short : $($c.Name) == $($c.Expect)" ($val -eq $c.Expect) "actual=$val"
}
Write-Host ""
Write-Host "===== Bing / Search suggestions (per-user) ====="
foreach ($c in @(
@{ Sub='Software\Policies\Microsoft\Windows\Explorer'; Name='DisableSearchBoxSuggestions'; Expect=1; Desc='Bing web search blocked in Start/Search' },
@{ Sub='Software\Microsoft\Windows\CurrentVersion\SearchSettings'; Name='IsDynamicSearchBoxEnabled'; Expect=0; Desc='Search highlights disabled' }
)) {
$hits = Get-UserRegValue -SubPath $c.Sub -Name $c.Name
$match = @($hits | Where-Object { $_.Value -eq $c.Expect })
Check $c.Desc ($match.Count -gt 0) "$($match.Count) of $($hits.Count) user hives match"
}
Write-Host ""
Write-Host "===== Spotlight (per-user) ====="
$hits = Get-UserRegValue -SubPath 'Software\Policies\Microsoft\Windows\CloudContent' -Name 'DisableSpotlightCollectionOnDesktop'
$match = @($hits | Where-Object { $_.Value -eq 1 })
Check 'Desktop Spotlight disabled' ($match.Count -gt 0) "$($match.Count) of $($hits.Count) user hives match"
Write-Host ""
Write-Host "===== Explorer / UI (per-user) ====="
$uiChecks = @(
@{ Sub='Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; Name='HideFileExt'; Expect=0; Desc='Show known file extensions' },
@{ Sub='Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; Name='Hidden'; Expect=1; Desc='Show hidden items' },
@{ Sub='Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; Name='TaskbarAl'; Expect=0; Desc='Taskbar aligned left' },
@{ Sub='Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; Name='ShowTaskViewButton'; Expect=0; Desc='Taskview button hidden' },
@{ Sub='Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; Name='LaunchTo'; Expect=1; Desc='Explorer opens to This PC' },
@{ Sub='Software\Microsoft\Windows\CurrentVersion\Themes\Personalize'; Name='AppsUseLightTheme'; Expect=0; Desc='Dark mode for apps' },
@{ Sub='Software\Microsoft\Windows\CurrentVersion\Themes\Personalize'; Name='SystemUsesLightTheme'; Expect=0; Desc='Dark mode for system' }
)
foreach ($r in $uiChecks) {
$hits = Get-UserRegValue -SubPath $r.Sub -Name $r.Name
$match = @($hits | Where-Object { $_.Value -eq $r.Expect })
$ok = $match.Count -gt 0
$detail = if ($hits.Count -eq 0) { "not set in any user hive" }
else { ($hits | ForEach-Object { "$(Split-Path $_.Hive -Leaf)=$($_.Value)" }) -join ', ' }
Check $r.Desc $ok $detail
}
Write-Host ""
Write-Host "===== Summary ====="
Write-Host ("PASS: {0} FAIL: {1}" -f $pass, $fail)

View File

@@ -0,0 +1,91 @@
param(
[switch]$KeepWorkDir
)
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$ErrorActionPreference = 'Stop'
# 1. Must be Windows PowerShell 5.1 (Win11Debloat targets powershell.exe)
if ($PSVersionTable.PSVersion.Major -ge 7) {
throw "Run with powershell.exe 5.1, not pwsh $($PSVersionTable.PSVersion)"
}
# 2. Must have Administrator token
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) { throw "Administrator token required" }
# 3. Config must exist beside this script
$userConfigSrc = Join-Path $PSScriptRoot 'win11debloat-config.json'
if (-not (Test-Path $userConfigSrc)) { throw "Missing $userConfigSrc" }
# 4. Download repo zip to a fresh work dir
$workDir = Join-Path $env:TEMP 'Win11Debloat-run'
if (Test-Path $workDir) { Remove-Item $workDir -Recurse -Force }
New-Item -ItemType Directory -Path $workDir | Out-Null
$zipUrl = 'https://github.com/Raphire/Win11Debloat/archive/refs/heads/master.zip'
$zipPath = Join-Path $workDir 'repo.zip'
Write-Host "[*] Downloading $zipUrl"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath -UseBasicParsing
if ((Get-Item $zipPath).Length -lt 100KB) { throw "Downloaded zip seems too small" }
Expand-Archive -Path $zipPath -DestinationPath $workDir -Force
$repoRoot = Join-Path $workDir 'Win11Debloat-master'
if (-not (Test-Path (Join-Path $repoRoot 'Win11Debloat.ps1'))) {
throw "Win11Debloat.ps1 missing after extract"
}
# 5. Stage our config alongside the repo and BOM-patch all .ps1 files
# (PowerShell 5.1 on zh-TW Windows reads non-BOM files as CP950 → breaks)
$userConfigDst = Join-Path $repoRoot 'my-config.json'
Copy-Item $userConfigSrc $userConfigDst -Force
$psFiles = Get-ChildItem -Path $repoRoot -Recurse -Filter '*.ps1'
$added = 0
foreach ($f in $psFiles) {
$bytes = [IO.File]::ReadAllBytes($f.FullName)
$hasBom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF
if (-not $hasBom) {
$bom = [byte[]](0xEF, 0xBB, 0xBF)
[IO.File]::WriteAllBytes($f.FullName, $bom + $bytes)
$added++
}
}
Write-Host "[*] BOM-patched $added of $($psFiles.Count) .ps1 files"
# 6. Run Win11Debloat
$logPath = Join-Path $repoRoot ("run-$(Get-Date -Format 'yyyyMMdd-HHmmss').log")
$script = Join-Path $repoRoot 'Win11Debloat.ps1'
Write-Host "[*] Running Win11Debloat -Silent -Config my-config.json"
Write-Host "[*] Log -> $logPath"
Write-Host ('-' * 60)
Push-Location $repoRoot
try {
$proc = Start-Process -FilePath 'powershell.exe' -ArgumentList @(
'-NoProfile','-ExecutionPolicy','Bypass','-File', $script,
'-Silent','-Config', $userConfigDst, '-LogPath', $logPath, '-NoRestartExplorer'
) -NoNewWindow -Wait -PassThru
}
finally {
Pop-Location
}
Write-Host ('-' * 60)
if (Test-Path $logPath) {
Write-Host "--- log tail ---"
Get-Content $logPath | Select-Object -Last 100
}
Write-Host ""
Write-Host "[=] Exit code: $($proc.ExitCode)"
Write-Host "[=] Full log: $logPath"
Write-Host "[!] Reboot (or at least restart Explorer) to apply UI changes."
if (-not $KeepWorkDir) {
Write-Host "[*] Cleaning up $workDir (use -KeepWorkDir to keep)"
Remove-Item $workDir -Recurse -Force -ErrorAction SilentlyContinue
}
exit $proc.ExitCode