Compare commits

...

26 commits

Author SHA1 Message Date
Manuel Thalmann 7d488aea38 Add scripts for backing up and restoring LGHub 2024-08-28 05:05:55 +02:00
Manuel Thalmann 621e0df51b Allow users to restore a backup 2024-08-28 04:40:32 +02:00
Manuel Thalmann 15fd56eb94 Add scripts for backing up and restoring personal files 2024-08-28 04:40:00 +02:00
Manuel Thalmann a33b3b3a5b Fix non-functioning profile script 2024-08-28 04:39:15 +02:00
Manuel Thalmann 31760a42a5 Ensure 7z is installed for backups 2024-08-28 04:38:56 +02:00
Manuel Thalmann de3f516b54 Streamline restoration of directories 2024-08-28 04:38:30 +02:00
Manuel Thalmann 627692cdfd Set a default path for backup artifacts 2024-08-28 00:38:20 +02:00
Manuel Thalmann 70621a1bbf Add capabilities to back up apps 2024-08-28 00:37:04 +02:00
Manuel Thalmann 3433b22f1d Allow specifying a backup action 2024-08-28 00:29:33 +02:00
Manuel Thalmann 63e357d193 Ignore unspecified backup archives 2024-08-28 00:22:38 +02:00
Manuel Thalmann 45487af3de Ignore inexistent backup artifacts 2024-08-28 00:21:06 +02:00
Manuel Thalmann 967e993970 Make the install script action agnostic 2024-08-28 00:03:28 +02:00
Manuel Thalmann 16f5767612 Rename the Windows installer script 2024-08-27 23:35:56 +02:00
Manuel Thalmann 9ef76a0b8a Rename outdated archive 2024-08-27 23:08:41 +02:00
Manuel Thalmann a8ff2b23b4 Silence errors concerning empty aliae configurations 2024-08-27 22:35:31 +02:00
Manuel Thalmann 31f787b722 Make Operations script cross platform 2024-08-27 22:27:44 +02:00
Manuel Thalmann 71403f3e76 Handle OneShot tasks only on Windows 2024-08-27 21:32:49 +02:00
Manuel Thalmann 101a4556d2 Add a script for managing backups 2024-08-27 21:05:51 +02:00
Manuel Thalmann 87459559e8 Add tools for managing aliae 2024-08-27 18:58:33 +02:00
Manuel Thalmann cda60830fb Fix non-functioning aliae installation 2024-08-27 18:55:12 +02:00
Manuel Thalmann 75bb170d33 Create dedicated script for creating users 2024-08-27 17:04:17 +02:00
Manuel Thalmann c3cef8396e Create dedicated script for installing software 2024-08-27 16:41:08 +02:00
Manuel Thalmann e7b0005991 Prevent reading nix config multiple times 2024-08-27 14:35:04 +02:00
Manuel Thalmann 7f1f4a4c12 Ensure only one user is enabled at once 2024-08-27 14:11:31 +02:00
Manuel Thalmann 3605fbbf89 Prevent unnecessary file creation 2024-08-27 14:06:56 +02:00
Manuel Thalmann 714a4cd2d5 Execute OneShot tasks in any operation 2024-08-27 14:05:16 +02:00
20 changed files with 1220 additions and 747 deletions

View file

@ -1,7 +1,7 @@
#!/bin/pwsh #!/bin/pwsh
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1"; . "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1";
. "$PSScriptRoot/../../../scripts/Windows/OS/Manage.ps1"; . "$PSScriptRoot/../../../scripts/Windows/OS/Legacy.ps1";
Write-Host "Starting Backup of Windows"; Write-Host "Starting Backup of Windows";
$context = [Context]::new(); $context = [Context]::new();

View file

@ -2,7 +2,7 @@
. "$PSScriptRoot/Drivers.ps1"; . "$PSScriptRoot/Drivers.ps1";
. "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1"; . "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1";
. "$PSScriptRoot/../../../scripts/Windows/Collections/Personal.ps1" . "$PSScriptRoot/../../../scripts/Windows/Collections/Personal.ps1"
. "$PSScriptRoot/../../../scripts/Windows/OS/Install.ps1"; . "$PSScriptRoot/../../../scripts/Windows/OS/Manage.ps1";
function Initialize-Configuration { function Initialize-Configuration {
# Fix synchronization between Linux and Windows clock # Fix synchronization between Linux and Windows clock

View file

@ -1,6 +1,6 @@
#!/bin/pwsh #!/bin/pwsh
. "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1"; . "$PSScriptRoot/../../../scripts/Common/Scripts/Context.ps1";
. "$PSScriptRoot/../../../scripts/Windows/OS/Install.ps1"; . "$PSScriptRoot/../../../scripts/Windows/OS/Manage.ps1";
. "$PSScriptRoot/../../../scripts/Windows/Collections/Generic.ps1" . "$PSScriptRoot/../../../scripts/Windows/Collections/Generic.ps1"
function Restore-Apps { function Restore-Apps {

View file

@ -2,9 +2,13 @@ using namespace Microsoft.Win32;
using namespace System.Security.AccessControl; using namespace System.Security.AccessControl;
using namespace System.Security.Principal; using namespace System.Security.Principal;
enum WindowsInstallerStage {
Initialize
Run
Completed
}
enum SetupStage { enum SetupStage {
Idle
OneShot
Configure Configure
Install Install
CreateUser CreateUser
@ -20,6 +24,7 @@ enum UserStage {
$null = New-Module { $null = New-Module {
[string] $configRoot = "HKLM:\Software\PortValhalla"; [string] $configRoot = "HKLM:\Software\PortValhalla";
[string] $stageOption = "Stage"; [string] $stageOption = "Stage";
[string] $setupStageOption = "SetupStage";
[string] $userOption = "SetupUser"; [string] $userOption = "SetupUser";
[string] $userStageOption = "UserStage"; [string] $userStageOption = "UserStage";
[string] $accountOption = "MSAccount"; [string] $accountOption = "MSAccount";
@ -274,11 +279,44 @@ $null = New-Module {
<# <#
.SYNOPSIS .SYNOPSIS
Gets the name of the current setup stage. Gets the name of the current stage of the Windows install script action.
#> #>
function Get-Stage { function Get-Stage {
$stage = Get-SetupOption $stageOption; $stage = Get-SetupOption $stageOption;
if ($null -ne $stage) {
$stage = [WindowsInstallerStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the name of the current stage of the Windows install script action.
.PARAMETER Name
The name of the stage to set.
#>
function Set-Stage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([WindowsInstallerStage]$Name).ToString();
}
$null = Set-SetupOption $stageOption $Name;
}
<#
.SYNOPSIS
Gets the name of the current setup stage.
#>
function Get-SetupStage {
$stage = Get-SetupOption $setupStageOption;
if ($null -ne $stage) { if ($null -ne $stage) {
$stage = [SetupStage]$stage; $stage = [SetupStage]$stage;
} }
@ -293,7 +331,7 @@ $null = New-Module {
.PARAMETER Name .PARAMETER Name
The name to set the current stage to. The name to set the current stage to.
#> #>
function Set-Stage { function Set-SetupStage {
param( param(
$Name $Name
) )
@ -302,7 +340,7 @@ $null = New-Module {
$Name = ([SetupStage]$Name).ToString(); $Name = ([SetupStage]$Name).ToString();
} }
$null = Set-SetupOption $stageOption $Name; $null = Set-SetupOption $setupStageOption $Name;
} }
<# <#
@ -389,7 +427,7 @@ $null = New-Module {
Gets a value indicating whether the setup has finished. Gets a value indicating whether the setup has finished.
#> #>
function Get-IsFinished { function Get-IsFinished {
return [bool] (((Get-Stage) -eq ([SetupStage]::Idle)) -or (Get-SetupOption $finishedOption)); return [bool](Get-SetupOption $finishedOption);
} }
<# <#

View file

@ -29,13 +29,18 @@ $null = New-Module {
function Start-Operation { function Start-Operation {
param( param(
[switch] $NonInteractive = ((Get-Stage) -eq ([SetupStage]::OneShot)), [switch] $NonInteractive,
[switch] $NoImplicitCleanup, [switch] $NoImplicitCleanup,
[scriptblock] $Action [scriptblock] $Action
) )
$cleanup = { }; $cleanup = { };
if ($IsWindows -and ($null -ne (Get-OneShotTask))) {
$taskPending = $true;
[switch] $NonInteractive = $true;
}
if (-not $Global:InOperation) { if (-not $Global:InOperation) {
if ($env:DEBUG) { if ($env:DEBUG) {
Set-PSDebug -Trace 1; Set-PSDebug -Trace 1;
@ -142,12 +147,8 @@ $null = New-Module {
$sys32 = "$env:WINDIR/System32"; $sys32 = "$env:WINDIR/System32";
$osk = (Get-Item "$sys32/osk.exe").FullName; $osk = (Get-Item "$sys32/osk.exe").FullName;
$cmd = (Get-Item "$sys32/cmd.exe").FullName; $cmd = (Get-Item "$sys32/cmd.exe").FullName;
$tmpOsk = New-TemporaryFile;
$tmpCmd = New-TemporaryFile;
gsudo -d copy "$osk" "$tmpOsk";
gsudo -d copy "$cmd" "$tmpCmd";
if ((Get-FileHash $tmpOsk).Hash -ne (Get-FileHash $tmpCmd).Hash) { if ((Get-FileHash $osk).Hash -ne (Get-FileHash $cmd).Hash) {
Set-MpPreference -ExclusionPath $osk; Set-MpPreference -ExclusionPath $osk;
gsudo -d --ti move $osk "${osk}_"; gsudo -d --ti move $osk "${osk}_";
gsudo -d -s copy $cmd $osk; gsudo -d -s copy $cmd $osk;
@ -167,6 +168,18 @@ $null = New-Module {
continue; continue;
} }
if (-not (Test-Command "7z")) {
Install-ChocoPackage 7zip.portable;
refreshenv;
continue;
}
if (-not (Test-Command "yq")) {
Install-ChocoPackage "yq";
refreshenv;
continue;
}
if (-not (Test-Wsl)) { if (-not (Test-Wsl)) {
Install-Wsl; Install-Wsl;
Restart-Intermediate; Restart-Intermediate;
@ -188,33 +201,6 @@ $null = New-Module {
continue; continue;
} }
Invoke-Hook "Install-PSModules" -Fallback {
$modules = @(
@("KnownFolders"),
@("PSWindowsUpdate"),
@("PSScriptAnalyzer"),
@("LocalAccounts", $true),
@("NuGet")
);
foreach ($module in $modules) {
$parameters = @{ };
if ($module[1]) {
$parameters = @{
allowPrerelease = $true;
};
}
if (-not (Test-PSModule $module[0])) {
Install-Module -Scope AllUsers -AcceptLicense -Force $module[0] @parameters;
Import-Module $module[0];
}
}
. "$PSScriptRoot/../../Windows/Software/PinnedItem/Manage.ps1";
};
if (-not (Test-PSPackage Selenium.WebDriver)) { if (-not (Test-PSPackage Selenium.WebDriver)) {
Write-Host "Installing browser automation tools…"; Write-Host "Installing browser automation tools…";
$null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies; $null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies;
@ -223,13 +209,56 @@ $null = New-Module {
Install-ChocoPackage selenium-gecko-driver firefox; Install-ChocoPackage selenium-gecko-driver firefox;
Install-WingetPackage AutoHotkey.AutoHotkey; Install-WingetPackage AutoHotkey.AutoHotkey;
$initialized = $true; . "$PSScriptRoot/../../Windows/Software/PinnedItem/Manage.ps1";
} }
Invoke-Hook "Install-PSModules" -Fallback {
$modules = @(
@("PSScriptAnalyzer")
) + (& {
if (-not $IsWindows) {
@()
} else {
@(
@("KnownFolders"),
@("PSWindowsUpdate"),
@("LocalAccounts", $true),
@("NuGet")
)
}
});
foreach ($module in $modules) {
$parameters = @{ };
if ($module -is [string]) {
$module = @($module);
}
if ($module[1]) {
$parameters = @{
allowPrerelease = $true;
};
}
if (-not (Test-PSModule $module[0])) {
Install-Module -Scope AllUsers -AcceptLicense -Force $module[0] @parameters;
Import-Module $module[0];
}
}
};
$initialized = $true;
} }
} }
} }
& $Action; if ($taskPending) {
Start-OneShot;
} else {
& $Action;
}
& $cleanup; & $cleanup;
} }
@ -238,7 +267,13 @@ $null = New-Module {
Gets the current OneShot task. Gets the current OneShot task.
#> #>
function Get-OneShotTask { function Get-OneShotTask {
[OneShotTask](Get-SetupOption $taskOption); $task = Get-SetupOption $taskOption;
if ($task) {
return [OneShotTask]$task;
} else {
return $null;
}
} }
<# <#
@ -291,8 +326,6 @@ $null = New-Module {
[OneShotTask] $Task [OneShotTask] $Task
) )
$currentStage = Get-Stage;
Set-Stage ([SetupStage]::OneShot);
& $taskSetter $Task; & $taskSetter $Task;
& { & {
@ -321,8 +354,6 @@ $null = New-Module {
} }
}; };
Set-Stage $currentStage;
if (Test-Path $errorPath) { if (Test-Path $errorPath) {
$errorMessage = Get-Content $errorPath; $errorMessage = Get-Content $errorPath;
Remove-Item $errorPath; Remove-Item $errorPath;
@ -340,23 +371,29 @@ $null = New-Module {
Executes the specified action and notifies the OneShot task executor. Executes the specified action and notifies the OneShot task executor.
#> #>
function Start-OneShot { function Start-OneShot {
param(
[scriptblock] $Action
)
try { try {
Start-Operation -NonInteractive @PSBoundParameters; Write-Host "Running OneShot task ``$(Get-OneShotTask)``";
Start-Operation {
switch (Get-OneShotTask) {
([OneShotTask]::InitializeMSAccount) {
Initialize-UserCreation;
}
([OneShotTask]::DisableUAC) {
Disable-UAC;
Register-Setup;
}
}
};
} }
catch { catch {
Set-Content -Path $errorPath -Value $Error; Set-Content -Path $errorPath -Value $Error;
Set-UserPermissions $errorPath; Set-UserPermissions $errorPath;
} }
finally { finally {
Set-Stage ([SetupStage]::Idle); & $taskSetter $null;
Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "The OneShot task ``$(Get-OneShotTask)`` finished."; Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "The OneShot task ``$(Get-OneShotTask)`` finished.";
} }
exit;
} }
<# <#
@ -364,6 +401,8 @@ $null = New-Module {
Clears resources allocated during the operation. Clears resources allocated during the operation.
#> #>
function Clear-OperationResources { function Clear-OperationResources {
Uninstall-WslDistribution; if ($IsWindows) {
Uninstall-WslDistribution;
}
} }
}; };

View file

@ -197,8 +197,10 @@ $null = New-Module {
function Start-SoftwareInstaller { function Start-SoftwareInstaller {
param( param(
[string] $Name, [string] $Name,
[scriptblock] $Backup = $null,
[scriptblock] $Installer = $null, [scriptblock] $Installer = $null,
[scriptblock] $Configurator = $null, [scriptblock] $Configurator = $null,
[scriptblock] $UserBackup = $null,
[scriptblock] $UserConfigurator = $null, [scriptblock] $UserConfigurator = $null,
[Nullable[InstallerAction]] $Action, [Nullable[InstallerAction]] $Action,
[hashtable] $Arguments [hashtable] $Arguments
@ -236,31 +238,52 @@ $null = New-Module {
arguments = $Arguments; arguments = $Arguments;
}; };
if ($action -eq ([InstallerAction]::Install)) { switch ($Action) {
if ($Installer) { ([InstallerAction]::Backup) {
Write-Host "Installing $Name"; if ($Backup) {
& $Installer @argumentList; Write-Host "Backing up $Name";
& $Backup @argumentList;
}
} }
([InstallerAction]::Install) {
if ($Installer) {
Write-Host "Installing $Name";
& $Installer @argumentList;
}
& $installHandler @argumentList -Action ([InstallerAction]::Configure); & $installHandler @argumentList -Action ([InstallerAction]::Configure);
if ($UserConfigurator -and (-not (Test-SetupUser))) { if ($UserConfigurator -and (-not (Test-SetupUser))) {
& $installHandler @argumentList -Action ([InstallerAction]::ConfigureUser); & $installHandler @argumentList -Action ([InstallerAction]::ConfigureUser);
}
} }
# ToDo: Automatically configure after installation ([InstallerAction]::Configure) {
} elseif ($Action -eq ([InstallerAction]::Configure)) { if ($Configurator) {
if ($Configurator) { Write-Host "Configuring $Name";
Write-Host "Configuring $Name"; & $Configurator @argumentList;
& $Configurator @argumentList; }
}
} elseif ($Action -eq ([InstallerAction]::ConfigureUser)) {
if ((-not $Arguments.ContainsKey($userArgument)) -or (-not $Arguments[$userArgument])) {
$Arguments.Add($userArgument, ($IsWindows ? $env:UserName : $env:USER));
} }
default {
if ((-not $Arguments.ContainsKey($userArgument)) -or (-not $Arguments[$userArgument])) {
$Arguments.Add($userArgument, ($IsWindows ? $env:UserName : $env:USER));
}
if ($UserConfigurator) { $user = $Arguments[$userArgument];
Write-Host "Configuring $Name for user ``$($Arguments[$userArgument])``";
& $UserConfigurator @argumentList; switch ($_) {
([InstallerAction]::BackupUser) {
if ($UserBackup) {
Write-Host "Backing up ``$Name`` for user ``$user``";
& $UserBackup @argumentList;
}
}
([InstallerAction]::ConfigureUser) {
if ($UserConfigurator) {
Write-Host "Configuring $Name for user ``$user``";
& $UserConfigurator @argumentList;
}
}
}
} }
} }
}; };

View file

@ -75,9 +75,11 @@ $null = New-Module {
Push-Location ~; Push-Location ~;
$profiles = $profiles | $profiles = @(
ForEach-Object { [System.IO.Path]::GetRelativePath((Get-Location), $_) } | $profiles |
ForEach-Object { "$HomeDir/$_" }; ForEach-Object { [System.IO.Path]::GetRelativePath((Get-Location), $_) } |
ForEach-Object { "$HomeDir/$_" }
);
Pop-Location; Pop-Location;
} }

View file

@ -34,14 +34,14 @@ Start-SoftwareInstaller @PSBoundParameters `
}; };
if (Test-Path $globalPath) { if (Test-Path $globalPath) {
& ([scriptblock]::Create((aliae init pwsh --config $globalPath))); $null = & ([scriptblock]::Create((aliae init pwsh --config $globalPath))) *>&1;
} }
if (Test-Path $userPath) { if (Test-Path $userPath) {
& ([scriptblock]::Create((aliae init pwsh))); $null = & ([scriptblock]::Create((aliae init pwsh))) *>&1;
} }
& ([scriptblock]::Create((aliae completion powershell))); aliae completion powershell | Out-String | Invoke-Expression;
} }
) -join [System.Environment]::NewLine) ) -join [System.Environment]::NewLine)
} ` } `

View file

@ -1,5 +1,7 @@
enum InstallerAction { enum InstallerAction {
Backup
Install Install
Configure Configure
BackupUser
ConfigureUser ConfigureUser
} }

View file

@ -1,593 +0,0 @@
#!/bin/pwsh
using namespace System.Security.Principal;
. "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1";
. "$PSScriptRoot/../../../scripts/Windows/Scripts/WSL.ps1";
. "$PSScriptRoot/../../Common/Scripts/Context.ps1";
. "$PSScriptRoot/../Scripts/Security.ps1";
. "$PSScriptRoot/../Software/Firefox/Install.ps1";
. "$PSScriptRoot/Manage.ps1";
. "$PSScriptRoot/User/Install.ps1";
$null = New-Module {
. "$PSScriptRoot/../Scripts/Hooks.ps1";
. "$PSScriptRoot/../Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../Scripts/Registry.ps1";
. "$PSScriptRoot/../Scripts/Security.ps1";
. "$PSScriptRoot/../Scripts/Update.ps1";
. "$PSScriptRoot/../Scripts/Users.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
. "$PSScriptRoot/../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Types/InstallerAction.ps1";
<#
.SYNOPSIS
Finishes the installation of a running Windows machine.
#>
function Start-WindowsInstallation {
Start-Operation -NoImplicitCleanup {
Start-InstallationLoop;
};
}
<#
.SYNOPSIS
Starts the installation loop.
#>
function Start-InstallationLoop {
while (-not (Get-IsFinished)) {
switch (Get-Stage) {
($null) {
Set-Stage ([SetupStage]::Configure);
break;
}
([SetupStage]::OneShot) {
Write-Host "Running OneShot task ``$(Get-OneShotTask)``";
Start-OneShot {
switch (Get-OneShotTask) {
([OneShotTask]::InitializeMSAccount) {
Initialize-UserCreation;
}
([OneShotTask]::DisableUAC) {
Disable-UAC;
Register-Setup;
}
}
};
break;
}
default {
if (Test-Admin) {
$null = Import-Module PSWindowsUpdate;
Invoke-Hook "Invoke-WindowsUpdate" -Fallback {
Update-WindowsInstallation;
};
if ((Get-WURebootStatus -Silent)) {
Restart-Intermediate;
return;
}
}
<#
.SYNOPSIS
Deploys an action for each software.
.PARAMETER Action
The action to execute by default.
#>
function Deploy-SoftwareAction {
param(
[Nullable[InstallerAction]] $Action = $null
)
[bool] $install = $false;
$arguments = [hashtable]@{ };
if ($null -ne $Action) {
$install = ($Action -eq ([InstallerAction]::Install));
$null = $arguments.Add("action", $Action);
} else {
$install = $true;
}
# Drivers
& {
$driverPath = "$PSScriptRoot/../Drivers";
$mbPath = "$driverPath/ROG Zenith Extreme Alpha";
if ($install) {
if (Get-Config "valhalla.hardware.elgatoWave") {
if (-not (Test-ChocoPackage wavelink)) {
Install-ChocoPackage wavelink -ArgumentList '--install-arguments="/norestart"';
Remove-DesktopIcon "*Wave Link*";
Restart-Intermediate;
exit;
}
}
}
foreach ($component in (Get-Config "valhalla.hardware.components")) {
switch ($component) {
("ROG Zenith Extreme Alpha") {
& "$mbPath/MarvellEthernet/Manage.ps1" @arguments;
& "$mbPath/IntelWiFi/Manage.ps1" @arguments;
& "$mbPath/IntelBluetooth/Manage.ps1" @arguments;
& "$mbPath/AMDChipsetX399/Manage.ps1" @arguments;
& "$driverPath/AMDChipsetX399/Manage.ps1" @arguments;
}
("Predator Z301C") {
& "$driverPath/Predator Z301C/Manage.ps1" @arguments;
}
}
}
if ($install) {
if (Get-Config "valhalla.hardware.amdCPU") {
Install-ChocoPackage amd-ryzen-master;
# ToDo: backup Ryzen energy saving plan
}
if (Get-Config "valhalla.hardware.nvidiaGPU") {
Install-ChocoPackage geforce-game-ready-driver;
Remove-DesktopIcon "*Geforce*";
}
if (Get-Config "valhalla.hardware.corsairDevice") {
Install-ChocoPackage icue;
}
}
if (Get-Config "valhalla.hardware.eyeX") {
& "$driverPath/Tobii EyeX/Manage.ps1" @arguments;
}
};
& {
# Windows Config
$softwarePath = "$PSScriptRoot/../Software";
$commonSoftware = "$PSScriptRoot/../../Common/Software";
& "$softwarePath/Windows/Manage.ps1" @arguments;
if (Get-Config "valhalla.hardware.logitechG") {
& "$softwarePath/LGHub/Manage.ps1" @arguments;
}
if (Test-Collection "essential") {
# Essentials
& "$softwarePath/aliae/Main.ps1" @arguments;
& "$softwarePath/OpenSSH/Manage.ps1" @arguments;
& "$softwarePath/PowerShell/Manage.ps1" @arguments;
& "$softwarePath/chocolatey/Manage.ps1" @arguments;
& "$softwarePath/zoxide/Manage.ps1" @arguments;
& "$commonSoftware/posh-git/Manage.ps1" @arguments;
& "$commonSoftware/Terminal-Icons/Manage.ps1" @arguments;
& "$softwarePath/Oh My Posh/Manage.ps1" @arguments;
if (Get-Config "valhalla.windows.dualboot") {
& "$softwarePath/Ext4Fsd/Main.ps1" @arguments;
}
if ($install) {
Install-ChocoPackage `
procexp `
procmon `
;
Install-WingetPackage `
KDE.KDEConnect `
;
}
}
if (Test-Collection "common") {
# Common Software
& "$softwarePath/WinSCP/Manage.ps1" @arguments;
& "$softwarePath/Thunderbird/Manage.ps1" @arguments;
& "$softwarePath/PuTTY/Manage.ps1" @arguments;
if ($install) {
Install-ChocoPackage `
7zip `
chocolateygui `
DefaultProgramsEditor `
bitwarden `
keepass `
;
Install-WingetPackage `
SomePythonThings.WingetUIStore `
;
Remove-DesktopIcon "UniGetUI*";
}
}
if (Test-Collection "desktopExperience") {
if ($install) {
# Fonts
Install-ChocoPackage nerd-fonts-CascadiaCode;
# Internet Access
Install-WingetPackage Brave.Brave kamranahmedse.pennywise;
Remove-DesktopIcon "*Brave*";
Remove-TaskbarItem "*Brave*";
Remove-DesktopIcon "Pennywise*";
# Tools
Install-SetupPackage -Source "https://github.com/mRemoteNG/mRemoteNG/releases/download/2023.03.03-v1.77.3-nb/mRemoteNG-Installer-1.77.3.nb-1784.msi" -ArgumentList "/Quiet";
Remove-DesktopIcon "mRemoteNG*";
Install-ChocoPackage `
gimp `
gpu-z `
windirstat `
winmerge `
handbrake `
hwmonitor `
qbittorrent `
imgburn `
inkscape `
krita `
MetaX `
obs-studio `
;
Remove-DesktopIcon "GIMP*";
Remove-DesktopIcon "GPU-Z*";
Remove-DesktopIcon "WinDirStat*";
Remove-DesktopIcon "*HWMonitor*";
Remove-DesktopIcon "ImgBurn*";
Remove-DesktopIcon "InkScape*";
Remove-DesktopIcon "Krita*";
Remove-DesktopIcon "MetaX*";
Remove-DesktopIcon "OBS Studio*";
Install-WingetPackage `
AntSoftware.AntRenamer `
AppWork.JDownloader;
Remove-DesktopIcon "JDownloader*";
}
# ToDo: Consider hiding behind own config?
& "$softwarePath/Ubiquiti UniFi Controller/Manage.ps1" @arguments;
# Internet Access
& "$softwarePath/Firefox/Manage.ps1" @arguments;
& "$softwarePath/MSEdgeRedirect/Manage.ps1" @arguments;
if (Test-Collection "fileSync") {
& "$softwarePath/Nextcloud/Main.ps1" @arguments;
}
}
if (Test-Collection "socialMedia") {
if ($install) {
Install-ChocoPackage `
signal `
threema-desktop `
element-desktop `
teamspeak `
;
Remove-DesktopIcon "*Element*";
Remove-DesktopIcon "*TeamSpeak*";
Install-WingetPackage Discord.Discord;
Remove-DesktopIcon "*Discord*";
}
}
if (Test-Collection "media") {
if ($install) {
Install-ChocoPackage `
k-litecodecpackmega `
vlc `
;
Remove-DesktopIcon "VLC*";
Install-ChocoPackage jellyfin-media-player -ArgumentList "--install-args","/norestart";
Remove-DesktopIcon "Jellyfin Media Player*";
Install-WingetPackage Ytmdesktop.Ytmdesktop;
Remove-DesktopIcon "Youtube Music*";
}
}
if (Test-Collection "coding") {
if ($install) {
& "$softwarePath/vscode/Main.ps1" @arguments;
Install-ChocoPackage `
gh `
github-desktop `
ida-free `
HxD `
docker-desktop `
imhex `
dotpeek `
;
Remove-DesktopIcon "IDA *";
Remove-DesktopIcon "GitHub*";
Remove-DesktopIcon "Docker*";
}
& "$softwarePath/VisualStudio/Manage.ps1" @arguments;
# Node.js
& "$softwarePath/NVS/Manage.ps1" @arguments;
}
if (Test-Collection "gaming") {
# Gaming
if ($install) {
Install-ChocoPackage `
goggalaxy `
epicgameslauncher `
rayman-controlpanel `
ppsspp `
;
Remove-DesktopIcon "*Epic Games*";
Remove-DesktopIcon "*PPSSPP *-Bit*";
Install-ChocoPackage `
steam `
ubisoft-connect `
-ArgumentList "--ignore-checksums" `
;
Remove-DesktopIcon "*Steam*";
Remove-DesktopIcon "*Ubisoft Connect*";
Install-WingetPackage ElectronicArts.EADesktop;
Remove-DesktopIcon "EA.*";
}
& "$softwarePath/TrackMania Nations Forever/Manage.ps1" @arguments;
& "$softwarePath/TrackMania United Forever/Manage.ps1" @arguments;
& "$softwarePath/ManiaPlanet/Manage.ps1" @arguments;
& "$softwarePath/osu!/Manage.ps1" @arguments;
& "$softwarePath/osu!lazer/Manage.ps1" @arguments;
& "$softwarePath/RetroArch/Manage.ps1" @arguments;
& "$softwarePath/reWASD/Manage.ps1" @arguments;
}
};
}
switch ($_) {
([SetupStage]::Configure) {
if (Get-Config "valhalla.windows.dualboot.enable") {
if (-not (Test-Qemu)) {
# Fix synchronization between Linux and Windows clocks.
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" -Name "RealTimeIsUniversal" -Value 1 -Type "DWord";
}
# Force time resynchronization
$timeZoneOption = "Start";
$timeZoneKey = "HKLM:\SYSTEM\CurrentControlSet\Services\tzautoupdate";
$service = Get-Service W32Time;
$autoUpdate = (Get-Item $timeZoneKey).GetValue($timeZoneOption);
$stopped = ($service.Status -eq "Stopped");
$setUpdate = { param([int] $Value) Set-ItemProperty $timeZoneKey -Name $timeZoneOption $Value };
& $setUpdate 3;
Start-Service $service;
w32tm /resync /force;
& $setUpdate $autoUpdate;
if ($stopped) {
Stop-Service $service;
}
}
Set-Stage ([SetupStage]::Install);
}
([SetupStage]::Install) {
Write-Host "Entering install phase";
Deploy-SoftwareAction;
Set-Stage ([SetupStage]::CreateUser);
}
([SetupStage]::CreateUser) {
$users = @(Get-Users);
$i = Get-CurrentUser;
for (; $i -lt $users.Count; $i++) {
$name = $users[$i];
Set-CurrentUser $i;
if (Test-Admin) {
Disable-BootMessage;
}
while ((Get-UserStage) -ne ([UserStage]::Completed)) {
switch (Get-UserStage) {
($null) {
Set-UserStage ([UserStage]::Create);
continue;
}
([UserStage]::Create) {
$msAccount = Get-UserConfig -UserName $name "microsoftAccount";
if ($env:UserName -ne $name) {
New-ValhallaUser $name;
if ($msAccount) {
logoff;
} else {
Restart-Intermediate;
}
exit;
} else {
if ($msAccount) {
if (-not (Test-Admin)) {
Invoke-OneShot DisableUAC;
Restart-Intermediate -NoRegister;
return;
}
Clear-SetupRegistration;
Disable-OneShotListener;
}
Set-UserStage ([UserStage]::Configure);
}
}
(([UserStage]::Configure)) {
$displayName = Get-UserConfig -UserName $name "displayName";
$userArguments = @{
name = $name;
};
if ($displayName) {
$userArguments.fullName = $displayName;
}
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
Set-LocalUser @userArguments;
Deploy-SoftwareAction -Action ([InstallerAction]::ConfigureUser);
Remove-LocalGroupMember -Member "$name" @adminGroup -ErrorAction SilentlyContinue;
foreach ($group in Get-UserConfig "groups") {
Add-LocalGroupMember -Member "$name" -Name "$group";
}
Set-UserStage ([UserStage]::Cleanup);
}
([UserStage]::Cleanup) {
$user = Get-SetupUser;
Enable-LocalUser $user;
Set-AutologinUser $user;
Unregister-WslDistribution;
Set-UserStage ([UserStage]::Completed);
Restart-Intermediate;
}
}
}
}
Set-IsFinished $true;
}
}
}
}
}
}
function Invoke-WindowsInstallation([Context] $context) {
$Global:InformationPreference = "Continue";
$Global:ErrorActionPreference = "Inquire";
$context.UserNames ??= @("Manuel");
Start-OldWindowsInstallationScript $context;
}
function Start-OldWindowsInstallationScript([Context] $context) {
. "$PSScriptRoot/Upgrade.ps1";
$finished = $false;
Remove-Item Env:\POSH_THEME -ErrorAction SilentlyContinue;
$configPath = "$PSScriptRoot/../Config";
$softwarePath = "$PSScriptRoot/../Software";
$initialConfigStage = "InitialConfiguration";
$prerequisitesStage = "InstallationPrerequisites";
$driverStage = "DriverInstallation";
$softwareStage = "MachineWideSoftwareInstallation";
$userStage = "CreatingUser";
$restorationStage = "Restoring";
while (-not $finished) {
switch ($context.GetStage()) {
{ (-not $_) -or ($_ -eq $initialConfigStage) } {
$context.SetStage($initialConfigStage);
if ((Get-Command Initialize-Configuration -ErrorAction SilentlyContinue)) {
Write-Information "Configuration initialization function was found. Running...";
Initialize-Configuration $context;
}
$null = Enable-WindowsOptionalFeature -Online -All -FeatureName "NetFx3";
. "$configPath/Windows/Install.ps1" $context;
. "$configPath/Explorer/Install.ps1" $context;
. "$configPath/OpenSSH/Install.ps1" $context;
. "$configPath/chocolatey/Install.ps1";
$context.RemoveDesktopIcon("*Microsoft Edge*");
$context.SetStage($prerequisitesStage);
break;
}
# Always install updates
default {
Write-Host "Starting Installation and Restoration of Windows";
Update-WindowsInstallation $context;
}
$prerequisitesStage {
Write-Host "Installing prerequisites for installing software";
if (-not $(Get-Command winget)) {
choco install -y winget;
}
Install-Module -AcceptLicense -Force "NuGet";
Import-Module NuGet;
Install-Firefox $context;
choco install -y selenium-gecko-driver;
$null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies;
winget install --accept-source-agreements --accept-package-agreements -e --id AutoHotkey.AutoHotkey;
$context.SetStage($driverStage);
break;
}
$driverStage {
Write-Host "Installing drivers";
if ((Get-Command Install-PortValhallaDrivers -ErrorAction SilentlyContinue)) {
Write-Information "Driver installation function was found. Starting installation";
Install-PortValhallaDrivers $context;
}
Write-Information "Finished installing drivers";
$context.SetStage($softwareStage);
$context.Reboot();
exit;
}
$softwareStage {
Write-Host "Setting up software with default app associations";
. "$softwarePath/WinSCP/Install.ps1" $context;
. "$softwarePath/Thunderbird/Install.ps1" $context;
Write-Host "Installing default settings for new users";
. "$softwarePath/aliae/Install.ps1" $context;
. "$softwarePath/posh-git/Install.ps1";
. "$softwarePath/Terminal-Icons/Install.ps1";
. "$softwarePath/Oh My Posh/Install.ps1" $context;
$context.SetStage($userStage);
break;
}
$userStage {
Install-PersonalUsers $context;
$context.SetStage($restorationStage);
break;
}
$restorationStage {
Restore-WindowsInstallation $context;
$finished = $true;
break;
}
}
}
}
};

View file

@ -0,0 +1,63 @@
#!/bin/pwsh
. "$PSScriptRoot/../Scripts/PersonalFiles.ps1";
. "$PSScriptRoot/../Software/Firefox/Install.ps1";
. "$PSScriptRoot/../Software/Nextcloud/Install.ps1";
. "$PSScriptRoot/../Collections/Personal.ps1";
. "$PSScriptRoot/../../Common/Scripts/Context.ps1";
function Backup-WindowsInstallation([Context] $context) {
Write-Information "Backing up Windows";
$Global:InformationPreference = "Continue";
$Global:ErrorActionPreference = "Inquire";
. "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1";
$backupRoot = $context.BackupRoot();
Backup-PersonalFiles $context;
Backup-PersonalApps $context;
$context.Backup($backupRoot, "$backupRoot.7z", @("-sdel"), $false);
$context.Cleanup();
Write-Host "Never forget to store the backup somewhere safe!";
Write-Host "I mean... what kind of a dumbass would ever forget to do so, right?";
}
function Restore-WindowsInstallation([Context] $context) {
Write-Host "Restoring Windows";
choco feature enable -n useEnhancedExitCodes;
function Read-Path()
{
$backupPath = Read-Host -Prompt "Please enter the path to the archive to load the backup from.";
if ($backupPath -and (-not (Test-Path -PathType Leaf $backupPath)))
{
Write-Host "No file could be found at the specified path.";
return Read-Path;
}
else
{
return $backupPath;
}
}
Install-Firefox $context;
Restore-Nextcloud $context;
Write-Information "Determining Backup Archive Path";
$backupPath = Read-Path;
$context.BackupName ??= "PortValhalla";
$context.RootDir = $context.GetTempDirectory();
if ($backupPath)
{
$context.Restore($backupPath, $context.BackupRoot());
}
Copy-UserInternationalSettingsToSystem -WelcomeScreen $True -NewUser $False;
Restore-PersonalFiles $context;
if ((Get-Command Restore-Apps -ErrorAction SilentlyContinue)) {
Restore-Apps $context;
}
Remove-Item -Recurse $context.RootDir;
$context.Cleanup();
}

View file

@ -1,63 +1,244 @@
#!/bin/pwsh #!/bin/pwsh
. "$PSScriptRoot/../Scripts/PersonalFiles.ps1"; using namespace System.Security.Principal;
. "$PSScriptRoot/../Software/Firefox/Install.ps1";
. "$PSScriptRoot/../Software/Nextcloud/Install.ps1"; . "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1";
. "$PSScriptRoot/../Collections/Personal.ps1"; . "$PSScriptRoot/../../../scripts/Windows/Scripts/WSL.ps1";
. "$PSScriptRoot/../../Common/Scripts/Context.ps1"; . "$PSScriptRoot/../../Common/Scripts/Context.ps1";
. "$PSScriptRoot/../Scripts/Security.ps1";
. "$PSScriptRoot/../Software/Firefox/Install.ps1";
. "$PSScriptRoot/Legacy.ps1";
. "$PSScriptRoot/User/Install.ps1";
function Backup-WindowsInstallation([Context] $context) { $null = New-Module {
Write-Information "Backing up Windows"; . "$PSScriptRoot/../Scripts/Deployment.ps1";
$Global:InformationPreference = "Continue"; . "$PSScriptRoot/../Scripts/Hooks.ps1";
$Global:ErrorActionPreference = "Inquire"; . "$PSScriptRoot/../Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1"; . "$PSScriptRoot/../Scripts/Registry.ps1";
$backupRoot = $context.BackupRoot(); . "$PSScriptRoot/../Scripts/Security.ps1";
Backup-PersonalFiles $context; . "$PSScriptRoot/../Scripts/Update.ps1";
Backup-PersonalApps $context; . "$PSScriptRoot/../Scripts/Users.ps1";
$context.Backup($backupRoot, "$backupRoot.7z", @("-sdel"), $false); . "$PSScriptRoot/../Types/WindowsInstallerAction.ps1";
$context.Cleanup(); . "$PSScriptRoot/../../Common/Scripts/Config.ps1";
Write-Host "Never forget to store the backup somewhere safe!"; . "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
Write-Host "I mean... what kind of a dumbass would ever forget to do so, right?"; . "$PSScriptRoot/../../Common/Scripts/Software.ps1";
} . "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Types/InstallerAction.ps1";
function Restore-WindowsInstallation([Context] $context) { <#
Write-Host "Restoring Windows"; .SYNOPSIS
choco feature enable -n useEnhancedExitCodes; Finishes the installation of a running Windows machine.
#>
function Start-WindowsInstallation {
Start-Operation -NoImplicitCleanup {
Start-InstallationLoop ([WindowsInstallerAction]::Install);
};
}
function Read-Path() <#
{ .SYNOPSIS
$backupPath = Read-Host -Prompt "Please enter the path to the archive to load the backup from."; Starts the installation loop.
#>
function Start-InstallationLoop {
param(
[WindowsInstallerAction] $Action
)
if ($backupPath -and (-not (Test-Path -PathType Leaf $backupPath))) while ((Get-Stage) -ne ([WindowsInstallerStage]::Completed)) {
{ switch (Get-Stage) {
Write-Host "No file could be found at the specified path."; ($null) {
return Read-Path; Set-Stage ([WindowsInstallerStage]::Initialize);
} break;
else }
{ ([WindowsInstallerStage]::Initialize) {
return $backupPath; $env:BACKUP_ARCHIVE = pwsh -Command Write-Host (
Read-Host (
& {
switch ($Action) {
([WindowsInstallerAction]::Backup) {
"Please select the path you wish to store your backup at"
}
([WindowsInstallerAction]::Install) {
"Please select the backup archive you wish to restore from"
}
}
}));
Set-Stage ([WindowsInstallerStage]::Run);
break;
}
([WindowsInstallerStage]::Run) {
switch ($Action) {
([WindowsInstallerAction]::Install) {
while (-not (Get-IsFinished)) {
if (Test-Admin) {
$null = Import-Module PSWindowsUpdate;
Invoke-Hook "Invoke-WindowsUpdate" -Fallback {
Update-WindowsInstallation;
};
if ((Get-WURebootStatus -Silent)) {
Restart-Intermediate;
return;
}
}
switch (Get-SetupStage) {
($null) {
Set-SetupStage ([SetupStage]::Configure);
break;
}
([SetupStage]::Configure) {
if (Get-Config "valhalla.windows.dualboot.enable") {
if (-not (Test-Qemu)) {
# Fix synchronization between Linux and Windows clocks.
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" -Name "RealTimeIsUniversal" -Value 1 -Type "DWord";
}
# Force time resynchronization
$timeZoneOption = "Start";
$timeZoneKey = "HKLM:\SYSTEM\CurrentControlSet\Services\tzautoupdate";
$service = Get-Service W32Time;
$autoUpdate = (Get-Item $timeZoneKey).GetValue($timeZoneOption);
$stopped = ($service.Status -eq "Stopped");
$setUpdate = { param([int] $Value) Set-ItemProperty $timeZoneKey -Name $timeZoneOption $Value };
& $setUpdate 3;
Start-Service $service;
w32tm /resync /force;
& $setUpdate $autoUpdate;
if ($stopped) {
Stop-Service $service;
}
}
Set-SetupStage ([SetupStage]::Install);
}
([SetupStage]::Install) {
Write-Host "Entering install phase";
Deploy-SoftwareAction;
Set-SetupStage ([SetupStage]::CreateUser);
}
([SetupStage]::CreateUser) {
Install-ValhallaUsers;
Set-IsFinished $true;
}
}
}
}
}
Set-Stage ([WindowsInstallerStage]::Completed);
break;
}
}
} }
} }
Install-Firefox $context; function Invoke-WindowsInstallation([Context] $context) {
Restore-Nextcloud $context; $Global:InformationPreference = "Continue";
$Global:ErrorActionPreference = "Inquire";
Write-Information "Determining Backup Archive Path"; $context.UserNames ??= @("Manuel");
$backupPath = Read-Path; Start-OldWindowsInstallationScript $context;
$context.BackupName ??= "PortValhalla";
$context.RootDir = $context.GetTempDirectory();
if ($backupPath)
{
$context.Restore($backupPath, $context.BackupRoot());
} }
Copy-UserInternationalSettingsToSystem -WelcomeScreen $True -NewUser $False; function Start-OldWindowsInstallationScript([Context] $context) {
Restore-PersonalFiles $context; . "$PSScriptRoot/Upgrade.ps1";
$finished = $false;
Remove-Item Env:\POSH_THEME -ErrorAction SilentlyContinue;
$configPath = "$PSScriptRoot/../Config";
$softwarePath = "$PSScriptRoot/../Software";
$initialConfigStage = "InitialConfiguration";
$prerequisitesStage = "InstallationPrerequisites";
$driverStage = "DriverInstallation";
$softwareStage = "MachineWideSoftwareInstallation";
$userStage = "CreatingUser";
$restorationStage = "Restoring";
if ((Get-Command Restore-Apps -ErrorAction SilentlyContinue)) {
Restore-Apps $context; while (-not $finished) {
switch ($context.GetStage()) {
{ (-not $_) -or ($_ -eq $initialConfigStage) } {
$context.SetStage($initialConfigStage);
if ((Get-Command Initialize-Configuration -ErrorAction SilentlyContinue)) {
Write-Information "Configuration initialization function was found. Running...";
Initialize-Configuration $context;
}
$null = Enable-WindowsOptionalFeature -Online -All -FeatureName "NetFx3";
. "$configPath/Windows/Install.ps1" $context;
. "$configPath/Explorer/Install.ps1" $context;
. "$configPath/OpenSSH/Install.ps1" $context;
. "$configPath/chocolatey/Install.ps1";
$context.RemoveDesktopIcon("*Microsoft Edge*");
$context.SetStage($prerequisitesStage);
break;
}
# Always install updates
default {
Write-Host "Starting Installation and Restoration of Windows";
Update-WindowsInstallation $context;
}
$prerequisitesStage {
Write-Host "Installing prerequisites for installing software";
if (-not $(Get-Command winget)) {
choco install -y winget;
}
Install-Module -AcceptLicense -Force "NuGet";
Import-Module NuGet;
Install-Firefox $context;
choco install -y selenium-gecko-driver;
$null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies;
winget install --accept-source-agreements --accept-package-agreements -e --id AutoHotkey.AutoHotkey;
$context.SetStage($driverStage);
break;
}
$driverStage {
Write-Host "Installing drivers";
if ((Get-Command Install-PortValhallaDrivers -ErrorAction SilentlyContinue)) {
Write-Information "Driver installation function was found. Starting installation";
Install-PortValhallaDrivers $context;
}
Write-Information "Finished installing drivers";
$context.SetStage($softwareStage);
$context.Reboot();
exit;
}
$softwareStage {
Write-Host "Setting up software with default app associations";
. "$softwarePath/WinSCP/Install.ps1" $context;
. "$softwarePath/Thunderbird/Install.ps1" $context;
Write-Host "Installing default settings for new users";
. "$softwarePath/aliae/Install.ps1" $context;
. "$softwarePath/posh-git/Install.ps1";
. "$softwarePath/Terminal-Icons/Install.ps1";
. "$softwarePath/Oh My Posh/Install.ps1" $context;
$context.SetStage($userStage);
break;
}
$userStage {
Install-PersonalUsers $context;
$context.SetStage($restorationStage);
break;
}
$restorationStage {
Restore-WindowsInstallation $context;
$finished = $true;
break;
}
}
}
} }
};
Remove-Item -Recurse $context.RootDir;
$context.Cleanup();
}

View file

@ -0,0 +1,293 @@
. "$PSScriptRoot/../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Types/InstallerAction.ps1";
<#
.SYNOPSIS
Deploys an action for each software selected for installation.
.PARAMETER
The action to execute.
#>
function Deploy-SoftwareAction {
param(
[System.Nullable[InstallerAction]] $Action = $null
)
[bool] $install = $false;
$arguments = [hashtable]@{ };
if ($null -ne $Action) {
$install = ($Action -eq ([InstallerAction]::Install));
$null = $arguments.Add("action", $Action);
} else {
$install = $true;
}
# Drivers
& {
$driverPath = "$PSScriptRoot/../Drivers";
$mbPath = "$driverPath/ROG Zenith Extreme Alpha";
if ($install) {
if (Get-Config "valhalla.hardware.elgatoWave") {
if (-not (Test-ChocoPackage wavelink)) {
Install-ChocoPackage wavelink -ArgumentList '--install-arguments="/norestart"';
Remove-DesktopIcon "*Wave Link*";
Restart-Intermediate;
exit;
}
}
}
foreach ($component in (Get-Config "valhalla.hardware.components")) {
switcH ($component) {
("ROG Zenith Extreme Alpha") {
& "$mbPath/MarvellEthernet/Manage.ps1" @arguments;
& "$mbPath/IntelWiFi/Manage.ps1" @arguments;
& "$mbPath/IntelBluetooth/Manage.ps1" @arguments;
& "$mbPath/AMDChipsetX399/Manage.ps1" @arguments;
& "$driverPath/AMDChipsetX399/Manage.ps1" @arguments;
}
("Predator Z301C") {
& "$driverPath/Predator Z301C/Manage.ps1" @arguments;
}
}
}
if ($install) {
if (Get-Config "valhalla.hardware.amdCPU") {
Install-ChocoPackage amd-ryzen-master;
# ToDo: backup Ryzen energy saving plan
}
if (Get-Config "valhalla.hardware.nvidiaGPU") {
Install-ChocoPackage geforce-game-ready-driver;
Remove-DesktopIcon "*Geforce*";
}
if (Get-Config "valhalla.hardware.corsairDevice") {
Install-ChocoPackage icue;
}
}
if (Get-Config "valhalla.hardware.eyeX") {
& "$driverPath/Tobii EyeX/Manage.ps1" @arguments;
}
};
& {
$softwarePath = "$PSScriptRoot/../Software";
$commonSoftware = "$PSScriptRoot/../../Common/Software";
# Windows Config
& "$softwarePath/Windows/Manage.ps1" @arguments;
if (Get-Config "valhalla.hardware.logitechG") {
& "$softwarePath/LGHub/Manage.ps1" @arguments;
}
# Essentials
if (Test-Collection "essential") {
& "$softwarePath/aliae/Main.ps1" @arguments;
& "$softwarePath/OpenSSH/Manage.ps1" @arguments;
& "$softwarePath/PowerShell/Manage.ps1" @arguments;
& "$softwarePath/chocolatey/Manage.ps1" @arguments;
& "$softwarePath/zoxide/Manage.ps1" @arguments;
& "$commonSoftware/posh-git/Manage.ps1" @arguments;
& "$commonSoftware/Terminal-Icon/Manage.ps1" @arguments;
& "$softwarePath/Oh My Posh/Manage.ps1" @arguments;
if (Get-Config "valhalla.windows.dualboot") {
& "$softwarePath/Ext4Fsd/Main.ps1" @arguments;
}
if ($install) {
Install-ChocoPackage `
procexp `
procmon `
;
Install-WingetPackage `
KDE.KDEConnect `
;
}
}
# Common Software
if (Test-Collection "common") {
& "$softwarePath/WinSCP/Manage.ps1" @arguments;
& "$softwarePath/Thunderbird/Manage.ps1" @arguments;
& "$softwarePath/PuTTY/Manage.ps1" @arguments;
if ($install) {
Install-ChocoPackage `
7zip `
chocolateygui `
DefaultProgramsEditor `
bitwarden `
keepass `
;
Install-WingetPackage `
SomePythonThings.WingetUIStore `
;
Remove-DesktopIcon "UniGetUI*";
}
}
if (Test-Collection "desktopExperience") {
if ($install) {
# Fonts
Install-ChocoPackage nerd-fonts-CascadiaCode;
# Internet Access
Install-WingetPackage Brave.Brave kamranahmedse.pennywise;
Remove-DesktopIcon "*Brave*";
Remove-TaskbarItem "*Brave*";
Remove-DesktopIcon "Pennywise*";
# Tools
Install-SetupPackage -Source "https://github.com/mRemoteNG/mRemoteNG/releases/download/2023.03.03-v1.77.3-nb/mRemoteNG-Installer-1.77.3.nb-1784.msi" -ArgumentList "/Quiet";
Remove-DesktopIcon "mRemoteNG*";
Install-ChocoPackage `
gimp `
gpu-z `
windirstat `
winmerge `
handbrake `
hwmonitor `
qbittorrent `
imgburn `
inkscape `
krita `
MetaX `
obs-studio `
;
Remove-DesktopIcon "GIMP*";
Remove-DesktopIcon "GPU-Z*";
Remove-DesktopIcon "WinDirStat*";
Remove-DesktopIcon "*HWMonior*";
Remove-DesktopIcon "ImgBurn*";
Remove-DesktopIcon "InkScape*";
Remove-DesktopIcon "Krita*";
Remove-DesktopIcon "MetaX*";
Remove-DesktopIcon "OBS Studio*";
Install-WingetPackage `
AntSoftware.AntRenamer `
AppWork.JDownloader `
;
Remove-DesktopIcon "JDownloader*";
}
# ToDo: Consider hiding behind own config?
& "$softwarePath/Ubiquiti UniFi Controller/Manage.ps1" @arguments;
# Internet Access
& "$softwarePath/Firefox/Manage.ps1" @arguments;
& "$softwarePath/MSEdgeRedirect/Manage.ps1" @arguments;
if (Test-Collection "fileSync") {
& "$softwarePath/Nextcloud/Main.ps1" @arguments;
}
}
if (Test-Collection "socialMedia") {
if ($install) {
Install-ChocoPackage `
signal `
threema-desktop `
element-desktop `
teamspeak `
;
Remove-DesktopIcon "*Element*";
Remove-DesktopIcon "*TeamSpeak*";
Install-WingetPackage Discord.Discord;
Remove-DesktopIcon "*Discord*";
}
}
if (Test-Collection "media") {
if ($install) {
Install-ChocoPackage `
k-litecodecpackmega `
vlc `
;
Remove-DesktopIcon "VLC*";
# When installing Jellyfin Media Player after iCUE, Jellyfin will try to reboot automatically
Install-ChocoPackage jellyfin-media-player -ArgumentList "--install-args","/norestart";
Remove-DesktopIcon "Jellyfin Media Player*";
Install-WingetPackage Ytmdesktop.Ytmdesktop;
Remove-DesktopIcon "Youtube Music*";
}
}
if (Test-Collection "coding") {
if ($install) {
& "$softwarePath/vscode/Main.ps1" @arguments;
Install-ChocoPackage `
gh `
github-desktop `
ida-free `
HxD `
docker-desktop `
imhex `
dotpeek `
;
Remove-DesktopIcon "IDA *";
Remove-DesktopIcon "GitHub*";
Remove-DesktopIcon "Docker*";
}
& "$softwarePath/VisualStudio/Manage.ps1" @arguments;
# Node.js
& "$softwarePath/NVS/Manage.ps1" @arguments;
}
# Gaming
if (Test-Collection "gaming") {
if ($install) {
Install-ChocoPackage `
goggalaxy `
epicgameslauncher `
rayman-controlpanel `
ppsspp `
;
Remove-DesktopIcon "*Epic Games*";
Remove-DesktopIcon "*PPSSPP *-Bit*";
Install-ChocoPackage `
steam `
ubisoft-connect `
-ArgumentList "--ignore-checksums" `
;
Remove-DesktopIcon "*Steam*";
Remove-DesktopIcon "*Ubisoft Connect*";
Install-WingetPackage ElectronicArts.EADesktop;
Remove-DesktopIcon "EA.*";
}
& "$softwarePath/TrackMania Nations Forever/Manage.ps1" @arguments;
& "$softwarePath/TrackMania United Forever/Manage.ps1" @arguments;
& "$softwarePath/ManiaPlanet/Manage.ps1" @arguments;
& "$softwarePath/osu!/Manage.ps1" @arguments;
& "$softwarePath/osu!lazer/Manage.ps1" @arguments;
& "$softwarePath/RetroArch/Manage.ps1" @arguments;
& "$softwarePath/reWASD/Manage.ps1" @arguments;
}
};
}

View file

@ -53,6 +53,7 @@ $null = New-Module {
function Get-StartupCommand { function Get-StartupCommand {
($env:PWSH_PATH ? "`$env:PWSH_PATH = $(ConvertTo-Injection $env:PWSH_PATH);" : "") + ($env:PWSH_PATH ? "`$env:PWSH_PATH = $(ConvertTo-Injection $env:PWSH_PATH);" : "") +
($env:DEBUG ? "`$env:DEBUG = $([int]$env:DEBUG);" : "") + ($env:DEBUG ? "`$env:DEBUG = $([int]$env:DEBUG);" : "") +
($env:BACKUP_ARCHIVE ? "`$env:BACKUP_ARCHIVE = $(ConvertTo-Injection (Resolve-Path $env:BACKUP_ARCHIVE));" : "") +
"`$env:INSTALLER_SCRIPT = $(ConvertTo-Injection (Resolve-Path $env:INSTALLER_SCRIPT));" + "`$env:INSTALLER_SCRIPT = $(ConvertTo-Injection (Resolve-Path $env:INSTALLER_SCRIPT));" +
"`$env:CONFIG_MODULE = $(ConvertTo-Injection (Resolve-Path $env:CONFIG_MODULE));" + "`$env:CONFIG_MODULE = $(ConvertTo-Injection (Resolve-Path $env:CONFIG_MODULE));" +
"& `$env:INSTALLER_SCRIPT;"; "& `$env:INSTALLER_SCRIPT;";

View file

@ -0,0 +1,171 @@
using namespace System.Collections.Generic;
. "$PSScriptRoot/../../Common/Scripts/System.ps1";
$null = New-Module {
$pathResolver = {
param(
[string] $User,
[string] $Path
)
[string] $result = $null;
if ($User) {
$result = "Users/$User";
} else {
$result = "System";
}
if (-not $Path) {
$Path = "Files";
}
$result = Join-Path $result $Path;
return $result;
};
<#
.SYNOPSIS
Gets the name of the variable holding the path to the backup archive of the current machine.
#>
function Get-ArchiveVariableName {
return "BACKUP_ARCHIVE";
}
<#
.SYNOPSIS
Gets the path to the backup archive of the current machine.
#>
function Get-ValhallaBackupArchive {
(Get-Item "Env:\$(Get-ArchiveVariableName)").Value;
}
<#
.SYNOPSIS
Sets the path to the backup archive of the current machine.
.PARAMETER Path
The path to set.
#>
function Set-ValhallaBackupArchive {
param(
[string] $Path
)
Set-Item "Env:\$(Get-ArchiveVariableName)" $Path;
}
<#
.SYNOPSIS
Adds files to the backup archive.
.PARAMETER User
The user to add the files to.
.PARAMETER Source
The file or directory to add to the backup archive.
.PARAMETER Path
The path to the location to store the file or directory at.
.PARAMETER ArgumentList
The arguments to pass to the `7z` command.
#>
function Add-BackupArtifacts {
param(
[string] $User,
[string] $Source,
[string] $Path,
[string[]] $Include,
[string[]] $Exclude
)
if ($env:BACKUP_ARCHIVE) {
[List[string]] $argumentList = @();
$dir = New-TemporaryDirectory;
$targetPath = & $pathResolver @PSBoundParameters;
$fullPath = Join-Path $dir $targetPath;
$null = New-Item -ItemType Directory -Force (Split-Path -Parent $fullPath);
if (Test-Path -PathType Container $Source) {
$null = New-Item -ItemType Junction $fullPath -Target $Source;
} elseif (Test-Path -PathType Leaf $Source) {
$null = New-Item -ItemType Directory -Force $fullPath;
Copy-Item $Source $fullPath;
}
$options = @(
@("i", $Include),
@("x", $Exclude)
);
foreach ($option in $options) {
$indicator = $option[0];
$list = $option[1];
foreach ($pattern in $list) {
$argumentList.Add("-$indicator!`"$(Join-Path $targetPath $pattern)`"");
}
}
Start-Process `
-NoNewWindow `
-Wait `
-WorkingDirectory $dir `
-FilePath 7z `
-ArgumentList (
@(
"a",
(Get-ValhallaBackupArchive),
"-xr!desktop.ini",
"-xr!thumbs.db",
"-xr!Thumbs.db"
) + $argumentList);
Remove-Item -Recurse -Force $dir;
}
}
<#
.SYNOPSIS
Extracts the specified backup artifacts to the specified target path.
.PARAMETER User
The user to restore the files for.
.PARAMETER Path
The path to restore the files from.
.PARAMETER Target
The path to restore the files to.
.PARAMETER ArgumentList
The arguments to pass to `7z`.
#>
function Expand-BackupArtifacts {
param(
[string] $User,
[string] $Path,
[string] $Target,
[Parameter(ValueFromRemainingArguments)]
[string[]] $ArgumentList
)
if ($env:BACKUP_ARCHIVE) {
$dir = New-TemporaryDirectory;
$sourcePath = & $pathResolver @PSBoundParameters;
$filePath = Join-Path $dir $sourcePath;
7z x "-o$dir" (Get-ValhallaBackupArchive) $sourcePath @ArgumentList;
if (Test-Path $filePath) {
if (Test-Path -PathType Container $filePath) {
$filePath = "$filePath/*";
}
Copy-Item -Recurse $filePath $Target -Force;
}
Remove-Item -Recurse -Force $dir;
}
}
};

View file

@ -2,20 +2,122 @@ using namespace System.Management.Automation.Host;
using namespace System.Security.Principal; using namespace System.Security.Principal;
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/../Scripts/Deployment.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1"; . "$PSScriptRoot/../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../Common/Scripts/Operations.ps1"; . "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
$loggedInUserOption = "LoggedInUser"; $loggedInUserOption = "LoggedInUser";
<#
.SYNOPSIS
Installs all pending users to the system.
#>
function Install-ValhallaUsers {
$users = @(Get-Users);
$i = Get-CurrentUser;
for (; $i -lt $users.Count; $i++) {
Set-CurrentUser $i;
if (Test-Admin) {
Disable-BootMessage;
}
while ((Get-UserStage) -ne ([UserStage]::Completed)) {
switch (Get-UserStage) {
($null) {
Set-UserStage ([UserStage]::Create);
break;
}
([UserStage]::Create) {
$msAccount = Get-UserConfig -UserName $name "microsoftAccount";
if ($env:UserName -ne $name) {
$userInfo = @{
name = $name;
msAccount = $msAccount;
};
New-ValhallaUser @userInfo;
if ($msAccount) {
logoff;
} else {
Restart-Intermediate;
}
exit;
} else {
if ($msAccount) {
if (-not (Test-Admin)) {
Invoke-OneShot DisableUAC;
Restart-Intermediate -NoRegister;
exit;
}
Clear-SetupRegistration;
Disable-OneShotListener;
}
Set-UserStage ([UserStage]::Configure);
}
}
([UserStage]::Configure) {
$displayName = Get-UserConfig -UserName $name "displayName";
$userInfo = @{
name = $name;
};
if ($displayName) {
$userInfo.fullName = $displayName;
}
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
Set-LocalUser @userInfo;
Deploy-SoftwareAction -Action ConfigureUser;
Remove-LocalGroupMember -Member "$name" @adminGroup -ErrorAction SilentlyContinue;
foreach ($group in Get-UserConfig "groups") {
Add-LocalGroupMember -Member "$name" -Name "$group";
}
Set-UserStage ([UserStage]::Cleanup);
}
([UserStage]::Cleanup) {
$user = Get-SetupUser;
Disable-LocalUser $name;
Enable-LocalUser $user;
Set-AutologinUser $user;
Unregister-WslDistribution;
Set-UserStage ([UserStage]::Completed);
Restart-Intermediate;
}
}
}
}
foreach ($user in $users) {
Enable-LocalUser $user;
}
}
<# <#
.SYNOPSIS .SYNOPSIS
Creates a new user for the PortValhalla setup. Creates a new user for the PortValhalla setup.
.PARAMETER Name .PARAMETER Name
The name of the user to create. The name of the user to create.
.PARAMETER MSAccount
A value indicating whether the user should be created as a Microsoft Account.
#> #>
function New-ValhallaUser { function New-ValhallaUser {
param( param(
[string] $Name [string] $Name,
[switch] $MSAccount
) )
function Add-MicrosoftAccount { function Add-MicrosoftAccount {
@ -83,9 +185,7 @@ $null = New-Module {
Set-MSAccountName ([string]$newUser); Set-MSAccountName ([string]$newUser);
} }
$msAccount = Get-UserConfig -UserName $Name "microsoftAccount"; if ($MSAccount) {
if ($msAccount) {
if (Test-Admin) { if (Test-Admin) {
Write-Host "Preparing environment for creating MS Account"; Write-Host "Preparing environment for creating MS Account";
Register-Setup -DefaultUser; Register-Setup -DefaultUser;
@ -104,7 +204,7 @@ $null = New-Module {
Write-Host "Creating personal user ``$Name``"; Write-Host "Creating personal user ``$Name``";
if ($msAccount) { if ($MSAccount) {
Add-MicrosoftAccount $Name; Add-MicrosoftAccount $Name;
Set-SetupOption $loggedInUserOption $env:UserName; Set-SetupOption $loggedInUserOption $env:UserName;
Invoke-OneShot ([OneShotTask]::InitializeMSAccount); Invoke-OneShot ([OneShotTask]::InitializeMSAccount);

View file

@ -3,13 +3,81 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../Scripts/AppAssociations.ps1";
$null = New-Module {
param ($Parameters)
$configPath = "$env:LocalAppData/LGHUB";
Export-ModuleMember -Function @();
<#
.SYNOPSIS
Stops the running Logitech G Hub instance.
#>
function Stop-LGHub {
[OutputType([string])]
param()
$hubName = "lghub_system_tray.exe";
$lghubPath = $(Get-Process | Where-Object { $_.Path -and ((Split-Path -Leaf $_.Path) -eq $hubName) })[0].Path;
$mainProcesses = Get-Process | Where-Object {
$_.Path -and
(@("lghub.exe", "lghub_agent.exe", $hubName) -contains (Split-Path -Leaf $_.Path)) -and
(($_.Parent.ProcessName -eq "explorer") -or ($null -eq $_.Parent))
};
$null = $mainProcesses | ForEach-Object { $_.Kill($true) };
return $lghubPath;
}
<#
.SYNOPSIS
Edits the Logitech G Hub configuration.
#>
function Edit-LGHubConfig {
param(
[scriptblock] $Action
)
Write-Host "Stopping Logitech G Hub";
$path = Stop-LGHub;
& $Action;
if ($path) {
Write-Host "Restarting Logitech G Hub";
Start-Process $path;
}
}
Start-SoftwareInstaller @Parameters `
-Installer {
Install-ChocoPackage lghub;
Remove-DesktopIcon "*G HUB*";
} `
-UserBackup {
param(
[hashtable] $Arguments
)
Edit-LGHubConfig {
Add-BackupArtifacts -User $Arguments.Name -Source $configPath -Path "LGHub" `
-Include @("settings.db", "icon_cache")
};
} `
-UserConfigurator {
param(
[hashtable] $Arguments
)
Edit-LGHubConfig {
Expand-BackupArtifacts -User $Arguments.Name -Path "LGHub" -Target $configPath;
};
};
} $PSBoundParameters;
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `
-Installer {
Install-ChocoPackage lghub;
Remove-DesktopIcon "*G HUB*";
};
# ToDo: Add restoration # ToDo: Add restoration

View file

@ -0,0 +1,37 @@
Pictures/Feedback
Documents/BeamNG.drive
Documents/Default.rdp
Documents/den4b/ReNamer
Documents/Dolphin Emulator
Documents/eFisc
Documents/IISExpress
Documents/KINGDOM HEARTS HD 1.5+2.5 ReMIX
Documents/ManiaPlanet
Documents/MetaX
Documents/MuseScore3
Documents/My Web Sites
Documents/OneNote-Notizbücher
Documents/PCSX2
Documents/PowerShell
Documents/PPSSPP
Documents/PS Vita
Documents/PSV Packages
Documents/PSV Updates
Documents/Repositories
Documents/Rise of the Tomb Raider
Documents/S2
Documents/SEGA
Documents/SEGA Mega Drive Classics
Documents/SQL Server Management Studio
Documents/Square Enix
Documents/TI-Nspire CX
Documents/TmForever
Documents/TrackMania
Documents/UltraVNC
Documents/Visual Studio 2017
Documents/Visual Studio 2019
Documents/Visual Studio 2022
Documents/Viwizard M4V Converter
Documents/WindowsPowerShell
Documents/Zoom
Music/iTunes

View file

@ -5,13 +5,41 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/Registry.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
Start-SoftwareInstaller @PSBoundParameters ` $null = New-Module {
param($Parameters)
. "$PSScriptRoot/../../Scripts/Registry.ps1";
. "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1";
$userFolders = @(
"Pictures",
"Documents",
"Downloads",
"Music",
"Videos"
);
$userExclusions = @(
"Documents/Eigene*",
"Documents/My Games",
"Documents/My Music",
"Documents/My Pictures",
"Documents/My Videos"
);
[string[]] $homeExclusions = Get-Content "$PSScriptRoot/Home.exclude.txt";
Start-SoftwareInstaller @Parameters `
-Backup {
Add-BackupArtifacts -Source "$env:PUBLIC" -Path "Public" `
-Include ($userFolders) `
-Exclude ($userExclusions + @("Documents/Hyper-V", "Documents/reWASD"));
} `
-Configurator { -Configurator {
$dir = New-TemporaryDirectory; $dir = New-TemporaryDirectory;
Push-Location $dir; Push-Location $dir;
@ -54,7 +82,7 @@ Start-SoftwareInstaller @PSBoundParameters `
) )
$path = "$($Key.PSPath)\Software\Microsoft\Lighting"; $path = "$($Key.PSPath)\Software\Microsoft\Lighting";
$null = New-Item $path; $null = New-Item $path -ErrorAction SilentlyContinue;
Set-ItemProperty $path -Name "AmbientLightingEnabled" -Value 0 -Type "DWord"; Set-ItemProperty $path -Name "AmbientLightingEnabled" -Value 0 -Type "DWord";
}; };
} }
@ -136,4 +164,20 @@ Start-SoftwareInstaller @PSBoundParameters `
Pop-Location; Pop-Location;
Remove-Item -Recurse $dir; Remove-Item -Recurse $dir;
Expand-BackupArtifacts -Path "Public" -Target $env:PUBLIC;
} `
-UserBackup {
param(
[hashtable] $Arguments
)
Add-BackupArtifacts -User $Arguments.Name -Source $HOME -Path "Home" -Include ($userFolders) -Exclude ($userExclusions + $homeExclusions);
} `
-UserConfigurator {
param(
[hashtable] $Arguments
)
Expand-BackupArtifacts -User $Arguments.Name -Path "Home" -Target $HOME;
}; };
} $PSBoundParameters;

View file

@ -0,0 +1,4 @@
enum WindowsInstallerAction {
Backup
Install
}