398 lines
13 KiB
PowerShell
398 lines
13 KiB
PowerShell
#!/bin/pwsh
|
|
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] $defaultUser, [string] $statement) {
|
|
$this.AddPowerShellProfileStatement($defaultUser, $null, $statement);
|
|
}
|
|
|
|
[void] AddPowerShellProfileStatement([bool] $defaultUser, [string] $category, [string] $statement) {
|
|
[string] $userDir = $null;
|
|
|
|
if ($defaultUser) {
|
|
$userDir = "C:\Users\Default";
|
|
} else {
|
|
$userDir = "~";
|
|
}
|
|
|
|
$this.AddPowerShellProfileStatement($userDir, $category, $statement);
|
|
}
|
|
|
|
[void] AddPowerShellProfileStatement([string] $userDir, [string] $category, [string] $statement) {
|
|
Push-Location ~;
|
|
$profileFiles = @((powershell -c '$PROFILE'), (pwsh -c '$PROFILE')) | ForEach-Object { Resolve-Path -Relative $_ };
|
|
|
|
if ($category) {
|
|
$profileFiles = $profileFiles | ForEach-Object { Join-Path (Split-Path -Parent $_) "profile.d" "$category.ps1"; };
|
|
}
|
|
|
|
$profileFiles | ForEach-Object {
|
|
$fileName = "$userDir\$_";
|
|
$dirName = Split-Path -Parent $fileName;
|
|
|
|
if (-not (Test-Path -PathType Container $dirName)) {
|
|
New-Item -ItemType Directory $dirName;
|
|
}
|
|
|
|
if (Test-Path -PathType Leaf $fileName) {
|
|
Add-Content -Force "$fileName" "`n$statement";
|
|
} else {
|
|
Set-Content -Force "$fileName" "$statement";
|
|
}
|
|
};
|
|
|
|
Pop-Location;
|
|
}
|
|
|
|
[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, [string[]]$arguments) {
|
|
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",
|
|
#"-mx=9",
|
|
$archivePath) + $arguments) `
|
|
-Wait `
|
|
-NoNewWindow;
|
|
}
|
|
|
|
[void] Restore([string]$archivePath, [string]$destinationPath) {
|
|
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;
|
|
}
|
|
}
|
|
}
|