console
<
.SYNOPSIS
启动独立隐藏的 PowerShell 进程阻止 Windows 关机,支持管理员权限检查和自动清理。
.DESCRIPTION
- 自动请求管理员权限(如需)
- 进程退出时自动删除临时脚本
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
$scriptPath = if ($MyInvocation.MyCommand.Path) {
$MyInvocation.MyCommand.Path
} else {
$tempFile = [System.IO.Path]::GetTempFileName() + ".ps1"
[System.IO.File]::WriteAllText($tempFile, $MyInvocation.MyCommand.Definition)
$tempFile
}
$arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`""
Write-Host "正在请求管理员权限..." -ForegroundColor Yellow
try {
$process = Start-Process -FilePath "pwsh.exe" -ArgumentList $arguments -Verb RunAs -WindowStyle Normal -PassThru
if ($scriptPath -ne $MyInvocation.MyCommand.Path) {
Register-ObjectEvent -InputObject $process -EventName Exited -Action {
Remove-Item $scriptPath -Force -ErrorAction SilentlyContinue
} | Out-Null
}
} catch {
Write-Host "无法提升权限: $_" -ForegroundColor Red
pause
}
exit
}
$csharpCode = @'
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class ShutdownBlocker {
private static NativeWindow _window;
[DllImport("user32.dll")]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll")]
private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private const int GWLP_WNDPROC = -4;
private const int WM_QUERYENDSESSION = 0x11;
public static void BlockShutdown() {
_window = new NativeWindow();
_window.CreateHandle(new CreateParams());
SetWindowLongPtr(_window.Handle, GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(
new WndProcDelegate(WindowProc)));
}
private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
private static IntPtr WindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) {
if (msg == WM_QUERYENDSESSION) {
return IntPtr.Zero; // 阻止关机
}
return CallWindowProc(IntPtr.Zero, hWnd, msg, wParam, lParam);
}
}
'@
$psScript = @"
# 加载 C# 代码
Add-Type -TypeDefinition @'
$csharpCode
'@
# 阻止关机
[ShutdownBlocker]::BlockShutdown()
# 保持进程运行(无窗口)
[System.Windows.Forms.Application]::Run()
"@
$tempScriptPath = [System.IO.Path]::Combine(
[System.IO.Path]::GetTempPath(),
"ShutdownBlocker_" + [Guid]::NewGuid().ToString("N") + ".ps1"
)
$psScript | Out-File -FilePath $tempScriptPath -Encoding UTF8
try {
$process = Start-Process `
-FilePath "powershell.exe" `
-ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$tempScriptPath`"" `
-WindowStyle Hidden `
-PassThru `
-ErrorAction Stop
Write-Host "后台进程已启动 (进程ID: $($process.Id))" -ForegroundColor Green
Write-Host "临时脚本位置: $tempScriptPath" -ForegroundColor DarkGray
$cleanupScript = {
param($scriptPath)
while ((Get-Process -Id $($process.Id) -ErrorAction SilentlyContinue) -ne $null) {
Start-Sleep -Seconds 1
}
Remove-Item -Path $scriptPath -Force -ErrorAction SilentlyContinue
Write-Host "临时文件已清理: $scriptPath" -ForegroundColor DarkGray
}
Start-Job -ScriptBlock $cleanupScript -ArgumentList $tempScriptPath | Out-Null
}
catch {
Write-Host "启动失败: $_" -ForegroundColor Red
Remove-Item -Path $tempScriptPath -Force -ErrorAction SilentlyContinue
}