Sumber yang diterbitkan
Unduh ZIP sumber
CH-J Server Manager
Jelajahi direktori dan file untuk rilis aplikasi tertentu.
CH-J / Server Manager
377 file
core-20261019T111616Z-160a00bfcddc
Ditambahkan: · Dibuat:
1
# CH-J Server Manager - fixed remote helper for Windows pagefile inspection and configuration.2
# Started through the short -EncodedCommand bootstrap; arguments arrive as JSON on stdin.3
# Changes require an elevated token, are backed up first and never restart Windows.4
param([string]$ArgsJson)5
Set-StrictMode -Version 26
$ErrorActionPreference = 'Stop'7
$ProgressPreference = 'SilentlyContinue'8
$StateDir = Join-Path $env:ProgramData 'CH-J\chj-system-monitor'9
$MemoryKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management'10
$CrashKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl'12
function Fail([string]$Code, [string]$Message) { throw [System.Exception]::new("CHJ:${Code}:$Message") }13
function Prop($Object, [string]$Name) { if ($null -ne $Object -and $Object.PSObject.Properties[$Name]) { return $Object.$Name }; return $null }14
function Elevated { (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) }15
function Require-Elevation { if (-not (Elevated)) { Fail 'WINDOWS_ELEVATION_REQUIRED' 'Changing the pagefile requires an SSH session with an elevated administrator token. CH-J does not bypass UAC.' } }16
function Boot-Time { try { return (Get-CimInstance Win32_OperatingSystem -ErrorAction Stop).LastBootUpTime.ToUniversalTime().ToString('o') } catch { return $null } }18
function Get-State {19
$errors = @()20
$memory = Get-ItemProperty $MemoryKey -ErrorAction SilentlyContinue21
$state = [ordered]@{22
elevated = (Elevated)23
automatic = $null24
configured = @()25
active = @()26
registryPagingFiles = @([string[]](Prop $memory 'PagingFiles') | Where-Object { $_ })27
existingPageFiles = @([string[]](Prop $memory 'ExistingPageFiles') | Where-Object { $_ })28
crashDumpEnabled = [int](Prop (Get-ItemProperty $CrashKey -ErrorAction SilentlyContinue) 'CrashDumpEnabled')29
volumes = @([IO.DriveInfo]::GetDrives() | Where-Object { $_.DriveType -eq 'Fixed' -and $_.IsReady } | ForEach-Object { [ordered]@{ drive = $_.Name.Substring(0, 2); format = [string]$_.DriveFormat; free = [double]$_.AvailableFreeSpace; total = [double]$_.TotalSize } })30
systemDrive = [string]$env:SystemDrive31
commitLimit = $null; committed = $null32
pending = $null33
bootTime = (Boot-Time)34
errors = $errors35
}36
try { $state.automatic = [bool](Get-CimInstance Win32_ComputerSystem -ErrorAction Stop).AutomaticManagedPagefile } catch { $state.errors += "Win32_ComputerSystem: $($_.Exception.Message)" }37
try { $state.configured = @(Get-CimInstance Win32_PageFileSetting -ErrorAction Stop | ForEach-Object { [ordered]@{ name = [string]$_.Name; initialMb = [int]$_.InitialSize; maximumMb = [int]$_.MaximumSize } }) } catch { $state.errors += "Win32_PageFileSetting: $($_.Exception.Message)" }38
try { $state.active = @(Get-CimInstance Win32_PageFileUsage -ErrorAction Stop | ForEach-Object { [ordered]@{ name = [string]$_.Name; allocatedMb = [int]$_.AllocatedBaseSize; currentMb = [int]$_.CurrentUsage; peakMb = [int]$_.PeakUsage } }) } catch { $state.errors += "Win32_PageFileUsage: $($_.Exception.Message)" }39
try { $m = Get-CimInstance Win32_PerfRawData_PerfOS_Memory -ErrorAction Stop; $state.commitLimit = [double]$m.CommitLimit; $state.committed = [double]$m.CommittedBytes } catch { $state.errors += "Memory counters: $($_.Exception.Message)" }40
$marker = Join-Path $StateDir 'pending.json'41
if (Test-Path -LiteralPath $marker) {42
$pending = Get-Content -LiteralPath $marker -Raw | ConvertFrom-Json43
# A change that was reverted to the configuration active since boot is no longer pending.44
$sameAsBoot = ($pending.baseline.automatic -eq $state.automatic) -and ((@($pending.baseline.registryPagingFiles) -join '|') -eq ($state.registryPagingFiles -join '|'))45
if ($pending.bootTime -eq $state.bootTime -and -not $sameAsBoot) { $state.pending = $pending } else { Remove-Item -LiteralPath $marker -Force -ErrorAction SilentlyContinue }46
}47
$state48
}50
function Save-Backup($Before) {51
if (-not (Test-Path -LiteralPath $StateDir)) { New-Item -ItemType Directory -Path $StateDir -Force | Out-Null }52
$acl = New-Object Security.AccessControl.DirectorySecurity53
$acl.SetAccessRuleProtection($true, $false)54
foreach ($sid in @('S-1-5-18', 'S-1-5-32-544')) { $acl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule((New-Object Security.Principal.SecurityIdentifier($sid)), 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow'))) }55
Set-Acl -LiteralPath $StateDir -AclObject $acl56
$path = Join-Path $StateDir ('pagefile-backup-' + (Get-Date).ToUniversalTime().ToString('yyyyMMddTHHmmssZ') + '.json')57
[IO.File]::WriteAllText($path, (ConvertTo-Json -InputObject ([ordered]@{ automatic = $Before.automatic; configured = $Before.configured; registryPagingFiles = $Before.registryPagingFiles }) -Depth 5), (New-Object Text.UTF8Encoding($false)))58
Get-ChildItem -LiteralPath $StateDir -Filter 'pagefile-backup-*.json' | Sort-Object LastWriteTime -Descending | Select-Object -Skip 20 | Remove-Item -Force -ErrorAction SilentlyContinue59
$path60
}62
function Mark-Pending([string]$Description, $Before) {63
$marker = Join-Path $StateDir 'pending.json'64
$existing = @()65
$baseline = [ordered]@{ automatic = $Before.automatic; registryPagingFiles = @($Before.registryPagingFiles) }66
if (Test-Path -LiteralPath $marker) { $old = Get-Content -LiteralPath $marker -Raw | ConvertFrom-Json; if ($old.bootTime -eq (Boot-Time)) { $existing = @($old.changes); $baseline = $old.baseline } }67
$value = [ordered]@{ bootTime = (Boot-Time); baseline = $baseline; changes = @($existing + @([ordered]@{ at = (Get-Date).ToUniversalTime().ToString('o'); description = $Description })) }68
[IO.File]::WriteAllText($marker, (ConvertTo-Json -InputObject $value -Depth 5), (New-Object Text.UTF8Encoding($false)))69
}71
function Check-Drive([string]$Drive, [int]$InitialMb, $State) {72
if ($Drive -notmatch '^[A-Za-z]:$') { Fail 'PAGEFILE_DRIVE_INVALID' 'Invalid drive letter.' }73
$volume = @($State.volumes | Where-Object { $_.drive -ieq $Drive }) | Select-Object -First 174
if (-not $volume) { Fail 'PAGEFILE_DRIVE_INVALID' 'The drive is not a ready fixed volume.' }75
if ($volume.format -notin @('NTFS', 'ReFS')) { Fail 'PAGEFILE_DRIVE_UNSUPPORTED' "Pagefiles are supported on NTFS volumes; $Drive is $($volume.format)." }76
$current = @($State.active | Where-Object { $_.name -like "$Drive*" }) | Select-Object -First 177
$reuse = 0; if ($current) { $reuse = [double]$current.allocatedMb * 1MB }78
if ($InitialMb -gt 0 -and ($volume.free + $reuse) -lt ([double]$InitialMb * 1MB + 1GB)) { Fail 'PAGEFILE_DISK_FULL' "Not enough free space on $Drive for $InitialMb MB plus a 1 GB reserve." }79
}81
function Op-Apply($A, $State) {82
Require-Elevation83
$action = [string]$A.action84
$before = $State85
$backup = $null86
$cs = Get-CimInstance Win32_ComputerSystem87
switch ($action) {88
'automatic' {89
if ($before.automatic -eq $true) { Fail 'PAGEFILE_NO_CHANGE' 'Windows already manages the pagefile automatically.' }90
$backup = Save-Backup $before91
Set-CimInstance -InputObject $cs -Property @{ AutomaticManagedPagefile = $true } | Out-Null92
Mark-Pending 'Automatic pagefile management enabled.' $before93
}94
'set' {95
$drive = ([string]$A.drive).ToUpperInvariant(); $initial = [int]$A.initialMb; $maximum = [int]$A.maximumMb96
if ($initial -lt 0 -or $maximum -lt 0 -or $initial -gt 4194304 -or $maximum -gt 4194304 -or ($maximum -gt 0 -and $initial -gt $maximum) -or (($initial -eq 0) -ne ($maximum -eq 0)) -or ($initial -gt 0 -and $initial -lt 16)) { Fail 'PAGEFILE_SIZE_INVALID' 'Initial and maximum size must be 16 MB or more with initial <= maximum, or both 0 for a system-managed size.' }97
Check-Drive $drive $initial $before98
$backup = Save-Backup $before99
if ($before.automatic -ne $false) { Set-CimInstance -InputObject $cs -Property @{ AutomaticManagedPagefile = $false } | Out-Null }100
$name = "$drive\pagefile.sys"101
$setting = @(Get-CimInstance Win32_PageFileSetting | Where-Object { $_.Name -ieq $name }) | Select-Object -First 1102
if (-not $setting) { $setting = New-CimInstance -ClassName Win32_PageFileSetting -Property @{ Name = $name } }103
Set-CimInstance -InputObject $setting -Property @{ InitialSize = [uint32]$initial; MaximumSize = [uint32]$maximum } | Out-Null104
Mark-Pending "Pagefile $name set to $initial-$maximum MB (0 = system managed size)." $before105
}106
'remove' {107
$drive = ([string]$A.drive).ToUpperInvariant()108
if ($drive -notmatch '^[A-Z]:$') { Fail 'PAGEFILE_DRIVE_INVALID' 'Invalid drive letter.' }109
if ($before.automatic -ne $false) { Fail 'PAGEFILE_AUTOMATIC' 'Switch to manual management before removing a pagefile.' }110
$name = "$drive\pagefile.sys"111
$setting = @(Get-CimInstance Win32_PageFileSetting | Where-Object { $_.Name -ieq $name }) | Select-Object -First 1112
if (-not $setting) { Fail 'PAGEFILE_NOT_FOUND' 'No pagefile is configured on this drive.' }113
$remaining = @($before.configured | Where-Object { $_.name -ine $name }).Count114
if ($remaining -eq 0 -and (Prop $A 'confirmLast') -ne $true) { Fail 'PAGEFILE_LAST' 'This is the last configured pagefile. Removing it lowers the commit limit to physical memory and can break crash dumps; explicit confirmation is required.' }115
if ($drive -ieq $before.systemDrive -and $before.crashDumpEnabled -ne 0 -and (Prop $A 'confirmCrashDump') -ne $true) { Fail 'PAGEFILE_CRASHDUMP' 'Crash dumps are enabled and normally need a pagefile on the system drive; explicit confirmation is required.' }116
$backup = Save-Backup $before117
Remove-CimInstance -InputObject $setting118
Mark-Pending "Pagefile $name removed." $before119
}120
default { Fail 'ACTION_INVALID' 'Unsupported pagefile action.' }121
}122
$after = Get-State123
[ordered]@{ result = 'ok'; backup = $backup; restartRequired = $true; state = $after }124
}126
try {127
$A = $ArgsJson | ConvertFrom-Json128
$state = Get-State129
$value = switch ([string]$A.op) { 'inspect' { $state } 'apply' { Op-Apply $A $state } default { Fail 'ACTION_INVALID' 'Unsupported operation.' } }130
[Console]::Out.WriteLine('CHJ_RESULT:' + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject $value -Depth 8 -Compress))))131
} catch {132
$exception = $_.Exception133
while ($exception.InnerException -and -not $exception.Message.StartsWith('CHJ:')) { $exception = $exception.InnerException }134
$message = $exception.Message; $code = 'WINDOWS_OPERATION_FAILED'135
if ($message -match '^CHJ:([A-Z0-9_]+):([\s\S]*)$') { $code = $Matches[1]; $message = $Matches[2] }136
elseif ($exception.GetType().FullName -match 'AccessDenied|UnauthorizedAccess' -or $exception.HResult -eq -2147024891) { $code = 'ACCESS_DENIED' }137
[Console]::Out.WriteLine('CHJ_ERR:' + $code + ':' + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($message)))138
}SHA-256
88469a3b5a6da96c584ff4ecaf14b958c15e1108897817fa341ee7db749ee7d2CH-J Proprietary Software License 1.14 · Kode sumber disediakan berdasarkan CH-J Proprietary Software License 1.14. Ketersediaannya tidak mengubah ketentuan lisensi atau memberikan hak tambahan.
SHA-256 arsip
a9605c0870a223b6a8542bb0705edd51d8b04f3069582653417a8397fabcc09a