#!/bin/pwsh . "$PSScriptRoot/../../Common/Config/powershell/lib.ps1"; class Context { [string]$EntryPoint; [string]$RootDir; [string]$BackupName; [string]$UserName; [string]$AdminName = "Admin"; [string]$ConfigRoot = "HKLM:\Software\PortValhalla"; [string]$RunOnceName = "PortValhalla"; [string]$StagePropertyName = "Stage"; [string] ProjectRoot() { return Resolve-Path (Join-Path $PSScriptRoot ".." ".." ".."); } [string] BackupRoot() { if (-not $this.RootDir) { return Join-Path $this.ProjectRoot() "backup" $this.BackupName; } else { return $this.RootDir; } } [void] RemoveDesktopIcon($pattern) { Remove-Item "$env:PUBLIC/Desktop/$pattern"; Remove-Item "~/Desktop/$pattern"; } [void] RemoveTaskbarItem($pattern) { Import-Module -UseWindowsPowerShell PinnedItem; Get-PinnedItem -Type TaskBar | Where-Object { $_.Name -like "$pattern" } | Remove-PinnedItem; } [void] AddPowerShellProfileStatement([string] $statement) { $this.AddPowerShellProfileStatement($true, $statement); } [void] AddPowerShellProfileStatement([string] $category, [string] $statement) { $this.AddPowerShellProfileStatement($true, $category, $statement); } [void] AddPowerShellProfileStatement([bool] $system, [string] $statement) { $this.AddPowerShellProfileStatement($system, $null, $statement); } [void] AddPowerShellProfileStatement([bool] $system, [string] $category, [string] $statement) { if ($category) { $overwrite = $true; } else { $overwrite = $false; } $this.AddPowerShellProfileStatement($system, $category, $statement, $overwrite); } [void] AddPowerShellProfileStatement([bool] $system, [string] $category, [string] $statement, [bool] $overwrite) { if ($system) { Add-PowerShellProfileStatement -System -Category $category -Statement $statement -Overwrite $overwrite; } else { Add-PowerShellProfileStatement -Category $category -Statement $statement -Overwrite $overwrite; } } [Microsoft.Win32.RegistryKey] EnsureConfigKey() { if (-not (Test-Path $this.ConfigRoot)) { $null = New-Item $this.ConfigRoot; $acl = Get-Acl $this.ConfigRoot; $acl.AddAccessRule( [System.Security.AccessControl.RegistryAccessRule]::new( [System.Security.Principal.SecurityIdentifier]::new([System.Security.Principal.WellKnownSidType]::BuiltinUsersSid, $null), [System.Security.AccessControl.RegistryRights]::FullControl, [System.Security.AccessControl.InheritanceFlags]::ObjectInherit -bor [System.Security.AccessControl.InheritanceFlags]::ContainerInherit, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow)); Set-Acl $this.ConfigRoot $acl; } return Get-Item $this.ConfigRoot; } [object] Get([string] $key) { $configKey = $this.EnsureConfigKey(); if ($configKey.GetValueNames().Contains($key)) { return $configKey.GetValue($key); } else { return $null; } } [void] Set([string] $key, $value, [Microsoft.Win32.RegistryValueKind] $type) { $configKey = $this.EnsureConfigKey(); $null = Set-ItemProperty -Path $configKey.PSPath -Name $key -Value $value -Type $type; } [void] Remove([string] $key) { $configKey = $this.EnsureConfigKey(); $null = Remove-ItemProperty -Path $configKey.PSPath -Name $key; } [void] SetStage([string] $name) { $this.Set($this.StagePropertyName, $name, "ExpandString"); } [string] GetStage() { return $this.Get($this.StagePropertyName); } [void] RemoveStage() { $this.Remove($this.StagePropertyName); } [string] ArchivePath($name) { return Join-Path $this.BackupRoot() "$name.7z"; } [string] FileArchivePath($name) { return $this.ArchivePath($(Join-Path "Files" $name)); } [string] SoftwareArchive([string]$softwareName) { return $this.ArchivePath($softwareName); } [void] Backup([string]$sourcePath, [string]$archivePath) { $this.Backup($sourcePath, $archivePath, @()); } [void] Backup([string]$sourcePath, [string]$archivePath, [string[]]$arguments) { $this.Backup($sourcePath, $archivePath, $arguments, $true); } [void] Backup([string]$sourcePath, [string]$archivePath, [string[]]$arguments, [bool]$split) { if (Test-Path $archivePath) { Remove-Item -Recurse $archivePath; } if (Test-Path "$archivePath.*") { Remove-Item -Recurse "$archivePath.*"; } Start-Process -WorkingDirectory "$sourcePath" ` -FilePath "7z" ` -ArgumentList ( @( "a", "-xr!desktop.ini", "-xr!thumbs.db", "-xr!Thumbs.db", "-slp", $archivePath) + $arguments + $( if ($split) { @("-v2g"); } else { @(); } )) ` -Wait ` -NoNewWindow; } [void] Restore([string]$archivePath, [string]$destinationPath) { if (-not (Test-Path -PathType Leaf $archivePath)) { $archivePath = "$archivePath.001"; } if (-not (Test-Path -PathType Leaf $archivePath)) { Write-Information ( [string]::Join( "`n", @( "An archive at the specified path $archivePath does not exist.", "No restoration will be performed."))); } else { if (-not (Test-Path -PathType Container $destinationPath)) { New-Item -ItemType Directory "$destinationPath"; } Start-Process -WorkingDirectory "$destinationPath" ` -FilePath "7z" ` -ArgumentList @("x", "$archivePath") ` -Wait ` -NoNewWindow; } } [string] GetTempDirectory() { $tempDir = Join-Path $([System.IO.Path]::GetTempPath()) $([System.IO.Path]::GetRandomFileName()); $null = New-Item -ItemType Directory $tempDir; return $tempDir; } [void] ProcessDefaultUserKey([System.Action[Microsoft.Win32.RegistryKey]] $action) { $rootPath = "HKLM:\DefaultUser"; $regRootPath = $rootPath.Replace(":", ""); $hivePath = "$env:SystemDrive\Users\Default\NTUSER.dat" $null = & reg load $regRootPath $hivePath; $root = Get-Item $rootPath; $action.Invoke($root); $root.Handle.Close(); [System.GC]::Collect(); & reg unload $regRootPath; } [void] ProcessLogonKey([System.Action[Microsoft.Win32.RegistryKey]] $action) { $key = Get-Item "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"; $action.Invoke($key); } [Microsoft.Win32.RegistryKey] GetSystemPolicyKey() { $keyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"; return Get-Item "$keyPath"; } [Microsoft.Win32.RegistryKey] GetRunOnceKey() { return $this.GetRunOnceKey($null); } [Microsoft.Win32.RegistryKey] GetRunOnceKey([Microsoft.Win32.RegistryKey] $userKey) { if (-not $userKey) { $userKey = Get-Item "HKCU:\"; } Push-Location $userKey.PSPath; $runOncePath = "Software\Microsoft\Windows\CurrentVersion\RunOnce"; if (-not (Test-Path $runOncePath)) { New-Item $runOncePath; } $result = Get-Item $runOncePath; Pop-Location; return $result; } [bool] GetUACState() { return [bool](Get-ItemPropertyValue -Path ($this.GetSystemPolicyKey().PSPath) -Name "EnableLUA"); } [void] SetUACState([bool] $value) { $null = Set-ItemProperty -Path ($this.GetSystemPolicyKey().PSPath) -Name "EnableLUA" -Value ([int]$value); } [void] RegisterReboot() { $this.RegisterReboot($null); } [void] RegisterReboot([Microsoft.Win32.RegistryKey] $userKey) { $runOnceKey = $this.GetRunOnceKey($userKey); Set-ItemProperty -Path $runOnceKey.PSPath -Name $this.RunOnceName -Value "pwsh `"$($this.EntryPoint)`"" -Type "ExpandString"; $runOnceKey.Handle.Close(); } [void] RegisterNewUserReboot() { $this.ProcessDefaultUserKey({ param ($root) $this.RegisterReboot($root); }); } [void] DeregisterNewUserReboot() { $this.ProcessDefaultUserKey({ param ($root) Remove-Item -Path $this.GetRunOnceKey($root).PSPath }); } [void] SetAutologin($user, $pw) { $this.ProcessLogonKey( { param ($logon) $path = $logon.PSPath; Set-ItemProperty $path -Name "AutoAdminLogon" 1; Set-ItemProperty $path -Name "DefaultUserName" $user; if ($pw) { Set-ItemProperty $path -Name "DefaultPassword" $pw; } else { Remove-ItemProperty $path -Name "DefaultPassword"; } }); } [void] RemoveAutologin() { $this.ProcessLogonKey( { param ($logon) $path = $logon.PSPath; Set-ItemProperty $path -Name "AutoAdminLogon" 0; Remove-ItemProperty $path -Name "DefaultDomainName" -ErrorAction SilentlyContinue; Remove-ItemProperty $path -Name "DefaultUserName" -ErrorAction SilentlyContinue; Remove-ItemProperty $path -Name "DefaultPassword" -ErrorAction SilentlyContinue; }); } [string] GetNextcloudConfigFile() { return "$env:APPDATA/Nextcloud/nextcloud.cfg"; } [void] AddNextcloudSync([string] $localPath, [string] $targetPath) { $this.AddNextcloudSync($localPath, $targetPath, $false); } [void] AddNextcloudSync([string] $localPath, [string] $targetPath, [bool] $virtualFiles) { Write-Host "Adding a Nextcloud sync"; Write-Information "$targetPath <=> $localPath"; $pattern = "^\d+\\Folders(?:WithPlaceholders)?\\(\d+)"; $folderID = ( Get-Content $($this.GetNextcloudConfigFile()) | ` Where-Object { $_ -match "$pattern" } | ` ForEach-Object { $_ -replace "$pattern.*$","`$1" } | ` Sort-Object -Unique | ` Measure-Object -Maximum).Maximum + 1; $configName = "Folders"; $localPath = $localPath.Replace("\", "/"); $targetPath = $targetPath.Replace("\", "/"); if ($virtualFiles) { $configName += "WithPlaceholders"; } Write-Information "Stopping Nextcloud process"; $nextcloudProcess = Get-Process nextcloud; $nextcloudPath = [string]$nextcloudProcess[0].Path; $nextcloudProcess | Stop-Process -Force; $accountSectionEntered = $false; $accountSectionLeft = $false; $newSettings = [string]::Join( "`n", @( "0\$configName\$folderID\localPath=$localPath", "0\$configName\$folderID\targetPath=$targetPath")); $oldContent = Get-Content ($this.GetNextcloudConfigFile()); $( for ($i = 0; $i -lt $oldContent.Count; $i++) { $line = $oldContent[$i]; if ($line -eq "[Accounts]") { $accountSectionEntered = $true; } if ($line -eq "" -and $accountSectionEntered) { $accountSectionLeft = $true; $newSettings; } $line; if ( (-not $accountSectionLeft) -and ($i -eq ($oldContent.Count - 1))) { $newSettings; } }) | Set-Content ($this.GetNextcloudConfigFile()); Write-Information "New nextcloud config:"; Write-Information (Get-Content $($this.GetNextcloudConfigFile()) | Out-String); Write-Information "Restarting Nextcloud"; Start-Process $nextcloudPath; } [void] Reboot() { Write-Host "Restarting Computer..."; $this.RegisterReboot(); Restart-Computer -Force; exit; } [void] PreventSleepMode() { $performanceScheme = "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"; $currentScheme = [regex]::Match((powercfg /GETACTIVESCHEME), "Power Scheme GUID: ([0-9a-f-]+) ").Groups[1].Value; if ($currentScheme -ne $performanceScheme) { Write-Information "Disabling Power Save mode"; $this.Set("Power Scheme", $currentScheme, "ExpandString"); powercfg /S 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c; } } [void] Cleanup() { $this.DeregisterNewUserReboot(); $this.RemoveAutologin(); $this.SetUACState($true); $originalScheme = $this.Get("Power Scheme"); Remove-Item $($this.EnsureConfigKey().PSPath); if ($originalScheme) { Write-Information "Reset power plan to original state"; powercfg /S $originalScheme; } } }