Files
BaiLongma/scripts/prebuild-clean.ps1

126 lines
4.9 KiB
PowerShell

# prebuild-clean.ps1
# Clean dist before build: detect file locks, close locking processes, remove old artifacts.
param([string]$DistPath = "dist")
$ErrorActionPreference = "Stop"
$distFull = Join-Path (Split-Path $PSScriptRoot) $DistPath
# Skip when dist does not exist.
if (-not (Test-Path $distFull)) {
Write-Host "[prebuild] dist does not exist; skipping clean" -ForegroundColor Green
exit 0
}
$asarPath = Join-Path $distFull "win-unpacked\resources\app.asar"
# If app.asar does not exist, remove dist directly.
if (-not (Test-Path $asarPath)) {
Remove-Item $distFull -Recurse -Force
Write-Host "[prebuild] dist removed" -ForegroundColor Green
exit 0
}
# Use Restart Manager API to find locking processes.
$rmCode = @'
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public static class RestartManager {
[StructLayout(LayoutKind.Sequential)]
struct RM_UNIQUE_PROCESS {
public int dwProcessId;
public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct RM_PROCESS_INFO {
public RM_UNIQUE_PROCESS Process;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string strAppName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string strServiceShortName;
public int ApplicationType;
public uint AppStatus;
public int TSSessionId;
[MarshalAs(UnmanagedType.Bool)] public bool bRestartable;
}
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);
[DllImport("rstrtmgr.dll")]
static extern int RmEndSession(uint pSessionHandle);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
static extern int RmRegisterResources(uint pSessionHandle, uint nFiles, string[] rgsFilenames,
uint nApplications, [In] RM_UNIQUE_PROCESS[] rgApplications, uint nServices, string[] rgsServiceNames);
[DllImport("rstrtmgr.dll")]
static extern int RmGetList(uint dwSessionHandle, out uint pnProcInfoNeeded, ref uint pnProcInfo,
[In, Out] RM_PROCESS_INFO[] rgAffectedApps, ref uint lpdwRebootReasons);
public static List<int> GetLockingPids(string path) {
var pids = new List<int>();
uint session;
string key = Guid.NewGuid().ToString();
if (RmStartSession(out session, 0, key) != 0) return pids;
try {
if (RmRegisterResources(session, 1, new[] { path }, 0, null, 0, null) != 0) return pids;
uint needed = 0, count = 0, reboot = 0;
RmGetList(session, out needed, ref count, null, ref reboot);
if (needed == 0) return pids;
var infos = new RM_PROCESS_INFO[needed];
count = needed;
if (RmGetList(session, out needed, ref count, infos, ref reboot) == 0)
foreach (var i in infos) pids.Add(i.Process.dwProcessId);
} finally {
RmEndSession(session);
}
return pids;
}
}
'@
Add-Type -TypeDefinition $rmCode
$lockingPids = [RestartManager]::GetLockingPids($asarPath)
if ($lockingPids.Count -gt 0) {
Write-Host "[prebuild] app.asar is locked by these processes:" -ForegroundColor Yellow
$closedNames = @()
foreach ($procId in $lockingPids) {
$proc = Get-Process -Id $procId -ErrorAction SilentlyContinue
if ($proc) {
Write-Host " -> PID $procId $($proc.Name) $($proc.MainWindowTitle)" -ForegroundColor Yellow
$closedNames += $proc.Name
# Ask the process to close first so it can save state.
$proc.CloseMainWindow() | Out-Null
}
}
# Wait up to 6 seconds before forcing termination.
$deadline = (Get-Date).AddSeconds(6)
foreach ($procId in $lockingPids) {
$proc = Get-Process -Id $procId -ErrorAction SilentlyContinue
while ($proc -and -not $proc.HasExited -and (Get-Date) -lt $deadline) {
Start-Sleep -Milliseconds 300
$proc = Get-Process -Id $procId -ErrorAction SilentlyContinue
}
$proc = Get-Process -Id $procId -ErrorAction SilentlyContinue
if ($proc -and -not $proc.HasExited) {
Write-Host " -> PID $procId did not exit; terminating" -ForegroundColor Red
Stop-Process -Id $procId -Force -ErrorAction SilentlyContinue
}
}
Write-Host "[prebuild] closed locking processes: $($closedNames -join ', ')" -ForegroundColor Green
Write-Host "[prebuild] reopen these apps after the build completes" -ForegroundColor Cyan
Start-Sleep -Milliseconds 500
}
# Remove dist.
try {
Remove-Item $distFull -Recurse -Force
Write-Host "[prebuild] dist removed; starting build" -ForegroundColor Green
} catch {
Write-Host "[prebuild] clean failed: $_" -ForegroundColor Red
exit 1
}