SOURCE

console 命令行工具 X clear

                    
>
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 {
        # 对于直接从ISE或VSCode运行的情况
        $tempFile = [System.IO.Path]::GetTempFileName() + ".ps1"
        [System.IO.File]::WriteAllText($tempFile, $MyInvocation.MyCommand.Definition)
        $tempFile
    }
    
    # 使用Start-Process以管理员身份重新启动脚本
    $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
}

# 定义 C# 代码
$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);
    }
}
'@

# 生成 PowerShell 脚本内容
$psScript = @"
# 加载 C# 代码
Add-Type -TypeDefinition @'
$csharpCode
'@

# 阻止关机
[ShutdownBlocker]::BlockShutdown()

# 保持进程运行(无窗口)
[System.Windows.Forms.Application]::Run()
"@

# 保存为临时 .ps1 文件
$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
}