CH-J Server Managerserverihaldus üle SSH
Menüü
Avaldatud allikas

CH-J Server Manager

Vaata katalooge ja faile konkreetse rakenduse vabastamiseks.

Laadi alla allikas ZIP
CH-J / Server Manager 377 failid
core-20261019T111616Z-160a00bfcddc Lisatud: · Ehitatud:
windowsPagefile.ps1 Lisatud: Kuupäeva ei registreerita 10,7 KB · 138 read
Kood Faili allalaadimine
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.
4param([string]$ArgsJson)
5Set-StrictMode -Version 2
6$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'
12function Fail([string]$Code, [string]$Message) { throw [System.Exception]::new("CHJ:${Code}:$Message") }
13function Prop($Object, [string]$Name) { if ($null -ne $Object -and $Object.PSObject.Properties[$Name]) { return $Object.$Name }; return $null }
14function Elevated { (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) }
15function 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.' } }
16function Boot-Time { try { return (Get-CimInstance Win32_OperatingSystem -ErrorAction Stop).LastBootUpTime.ToUniversalTime().ToString('o') } catch { return $null } }
18function Get-State {
19 $errors = @()
20 $memory = Get-ItemProperty $MemoryKey -ErrorAction SilentlyContinue
21 $state = [ordered]@{
22 elevated = (Elevated)
23 automatic = $null
24 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:SystemDrive
31 commitLimit = $null; committed = $null
32 pending = $null
33 bootTime = (Boot-Time)
34 errors = $errors
35 }
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-Json
43 # 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 $state
50function 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.DirectorySecurity
53 $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 $acl
56 $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 SilentlyContinue
59 $path
62function 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)))
71function 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 1
74 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 1
77 $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." }
81function Op-Apply($A, $State) {
82 Require-Elevation
83 $action = [string]$A.action
84 $before = $State
85 $backup = $null
86 $cs = Get-CimInstance Win32_ComputerSystem
87 switch ($action) {
88 'automatic' {
89 if ($before.automatic -eq $true) { Fail 'PAGEFILE_NO_CHANGE' 'Windows already manages the pagefile automatically.' }
90 $backup = Save-Backup $before
91 Set-CimInstance -InputObject $cs -Property @{ AutomaticManagedPagefile = $true } | Out-Null
92 Mark-Pending 'Automatic pagefile management enabled.' $before
93 }
94 'set' {
95 $drive = ([string]$A.drive).ToUpperInvariant(); $initial = [int]$A.initialMb; $maximum = [int]$A.maximumMb
96 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 $before
98 $backup = Save-Backup $before
99 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 1
102 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-Null
104 Mark-Pending "Pagefile $name set to $initial-$maximum MB (0 = system managed size)." $before
105 }
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 1
112 if (-not $setting) { Fail 'PAGEFILE_NOT_FOUND' 'No pagefile is configured on this drive.' }
113 $remaining = @($before.configured | Where-Object { $_.name -ine $name }).Count
114 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 $before
117 Remove-CimInstance -InputObject $setting
118 Mark-Pending "Pagefile $name removed." $before
119 }
120 default { Fail 'ACTION_INVALID' 'Unsupported pagefile action.' }
121 }
122 $after = Get-State
123 [ordered]@{ result = 'ok'; backup = $backup; restartRequired = $true; state = $after }
126try {
127 $A = $ArgsJson | ConvertFrom-Json
128 $state = Get-State
129 $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 = $_.Exception
133 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)))
SHA-25688469a3b5a6da96c584ff4ecaf14b958c15e1108897817fa341ee7db749ee7d2

CH-J Proprietary Software License 1.14 · Allikas on esitatud CH-J Proprietary Software License 1.14 all. Selle kättesaadavus ei muuda litsentsitingimusi ega anna täiendavaid õigusi.

Arhiiv SHA-256a9605c0870a223b6a8542bb0705edd51d8b04f3069582653417a8397fabcc09a
Failid