Restructure the project

This commit is contained in:
Manuel Thalmann 2024-09-23 03:33:17 +02:00
parent 3c1c4f2710
commit 78fc179bf2
37 changed files with 959 additions and 930 deletions

View file

@ -1,56 +1,18 @@
using namespace Microsoft.Win32; using namespace Microsoft.Win32;
using namespace System.Management.Automation.Host; using namespace System.Management.Automation.Host;
using namespace System.Security.AccessControl;
using namespace System.Security.Principal;
enum WindowsInstallerStage {
Initialize
Run
Cleanup
Completed
}
enum SetupStage {
Initialize
Configure
Install
CreateUser
}
enum BackupStage {
Initialize
Backup
BackupUsers
}
enum UserStage {
Create
Configure
Cleanup
Completed
}
$null = New-Module { $null = New-Module {
[string] $configRoot = "HKLM:\Software\PortValhalla"; . "$PSScriptRoot/SoftwareManagement.ps1";
[string] $stageOption = "Stage"; . "$PSScriptRoot/../../Windows/Scripts/Registry.ps1";
[string] $setupStageOption = "SetupStage"; . "$PSScriptRoot/../../Windows/Types/WindowsInstallerAction.ps1";
[string] $backupStageOption = "BackupStage";
[string] $userOption = "SetupUser";
[string] $userStageOption = "UserStage";
[string] $accountOption = "MSAccount";
[string] $finishedOption = "Finished";
[RegistryKey] $key = $null;
<# <#
.SYNOPSIS .SYNOPSIS
Prompts the user to select a profile to act on. Prompts the user to select a profile to act on.
#> #>
function Show-ProfileNamePrompt { function Show-ProfileNamePrompt {
. "$PSScriptRoot/../../Windows/Types/WindowsInstallerAction.ps1";
$profiles = & { $profiles = & {
. "$PSScriptRoot/SoftwareManagement.ps1";
if (-not $IsWindows -or (Test-Command "wsl")) { if (-not $IsWindows -or (Test-Command "wsl")) {
return Invoke-ConfigScript "getProfiles"; return Invoke-ConfigScript "getProfiles";
} else { } else {
@ -93,75 +55,6 @@ $null = New-Module {
} }
} }
<#
.SYNOPSIS
Converts the specified path to linux and escapes it for the use in a script.
.PARAMETER Path
The path to convert.
#>
function ConvertTo-LinuxPath {
param(
[string] $Path
)
& {
$ErrorActionPreference = 'Continue';
$completed = $false;
while (-not $completed) {
$job = Start-Job {
$env:Value = Resolve-Path $Using:Path;
$env:WSLENV = "Value/p";
$result = wsl -- bash -c 'echo "$Value"';
wsl -e printf "%q" "$result";
};
$result = Receive-Job -Wait $job;
if ((Split-Path -Leaf $Path) -ne (Split-Path -Leaf $result)) {
Write-Error "The result of the path conversion of ``$Path`` was unexpected: ``$result``";
continue;
}
if ($job.State -ne ([System.Management.Automation.JobState]::Completed)) {
Write-Error "An error occurred while converting ``$Path`` to a Linux path.`nOutput: ``$result``";
continue;
}
$completed = $true;
}
$result;
};
}
<#
.SYNOPSIS
Gets the registry key containing options related to the setup.
#>
function Get-SetupConfigKey {
if (-not (Test-Path $configRoot)) {
$key = New-Item $configRoot;
$acl = Get-Acl $configRoot;
$acl.AddAccessRule(
[RegistryAccessRule]::new(
[SecurityIdentifier]::new([WellKnownSidType]::BuiltinUsersSid, $null),
[RegistryRights]::FullControl,
[InheritanceFlags]::ObjectInherit -bor [InheritanceFlags]::ContainerInherit,
[PropagationFlags]::None,
[AccessControlType]::Allow));
Set-Acl $configRoot $acl;
} else {
$key = Get-Item $configRoot;
}
return $key;
}
<# <#
.SYNOPSIS .SYNOPSIS
Runs a script based on the `config.fish` script. Runs a script based on the `config.fish` script.
@ -174,6 +67,7 @@ $null = New-Module {
[string] $Script [string] $Script
) )
. "$PSScriptRoot/../../Windows/Scripts/WSL.ps1";
$scriptPath = "$PSScriptRoot/../../Common/Scripts/config.fish"; $scriptPath = "$PSScriptRoot/../../Common/Scripts/config.fish";
if ($env:CONFIG_NAME -or ($Script -eq "getProfiles")) { if ($env:CONFIG_NAME -or ($Script -eq "getProfiles")) {
@ -335,273 +229,4 @@ $null = New-Module {
param() param()
Get-OSConfig "setupUser.name"; Get-OSConfig "setupUser.name";
} }
<#
.SYNOPSIS
Gets the value of an option related to the setup.
.PARAMETER Name
The name of the option value to get.
#>
function Get-SetupOption {
param(
[string] $Name
)
$key = Get-SetupConfigKey;
if ($key.GetValueNames().Contains($Name)) {
return $key.GetValue($Name);
} else {
return $null;
}
}
<#
.SYNOPSIS
Sets the value of an option related to the setup.
.PARAMETER Name
The name of the option to set.
.PARAMETER Value
The value to set the option to.
#>
function Set-SetupOption {
param(
[string] $Name,
$Value
)
$key = (Get-SetupConfigKey).PSPath;
if ($null -eq $Value) {
Remove-ItemProperty $key -Name $Name;
} else {
$null = Set-ItemProperty $key -Name $Name -Value $Value;
}
}
<#
.SYNOPSIS
Gets the name of the current stage of the Windows install script action.
#>
function Get-Stage {
$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) {
$stage = [SetupStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the current stage.
.PARAMETER Name
The name to set the current stage to.
#>
function Set-SetupStage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([SetupStage]$Name).ToString();
}
$null = Set-SetupOption $setupStageOption $Name;
}
<#
.SYNOPSIS
Gets the name of the current stage of the backup.
#>
function Get-BackupStage {
$stage = Get-SetupOption $backupStageOption;
if ($null -ne $stage) {
$stage = [BackupStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the current stage of the backup.
.PARAMETER Name
The name to set the current stage to.
#>
function Set-BackupStage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([BackupStage]$Name).ToString();
}
$null = Set-SetupOption $backupStageOption $Name;
}
<#
.SYNOPSIS
Gets the current user to set up.
#>
function Get-CurrentUser {
return (Get-SetupOption $userOption) ?? 0;
}
<#
.SYNOPSIS
Sets the index of the current user to set up.
.PARAMETER Value
The index of the user to set up.
#>
function Set-CurrentUser {
param(
[int] $Value
)
Set-SetupOption $userOption $value;
}
<#
.SYNOPSIS
Gets the name of the current stage of the user setup.
#>
function Get-UserStage {
$stage = Get-SetupOption $userStageOption;
if ($null -ne $stage) {
$stage = [UserStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the current stage of the user setup.
.PARAMETER Name
The name of the stage to set.
#>
function Set-UserStage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([UserStage]$Name).ToString();
}
$null = Set-SetupOption $userStageOption $Name;
}
<#
.SYNOPSIS
Gets the name of the microsoft account to create.
#>
function Get-MSAccountName {
return Get-SetupOption $accountOption;
}
<#
.SYNOPSIS
Sets the name of the microsoft account to create.
.PARAMETER Name
The name of the microsoft account to create.
#>
function Set-MSAccountName {
param(
[string] $Name
)
Set-SetupOption $accountOption $Name;
}
<#
.SYNOPSIS
Gets a value indicating whether the setup has finished.
#>
function Get-IsFinished {
return [bool](Get-SetupOption $finishedOption);
}
<#
.SYNOPSIS
Sets a value indicating whether the setup has finished.
#>
function Set-IsFinished {
param(
$Value
)
Set-SetupOption $finishedOption $true;
}
<#
.SYNOPSIS
Checks whether the running system is a QEMU virtual machine.
#>
function Test-Qemu {
((Get-WmiObject win32_computersystem).Manufacturer) -eq "QEMU";
}
<#
.SYNOPSIS
Checks whether the current user is the setup user.
#>
function Test-SetupUser {
($IsWindows ? $env:UserName : $env:USER) -eq (Get-SetupUser);
}
<#
.SYNOPSIS
Checks whether the active session is executed with admin rights.
#>
function Test-Admin {
net session 2> $null | Out-Null;
return $?;
}
} }

View file

@ -1,35 +1,17 @@
using namespace System.Management.Automation.Host; using namespace System.Management.Automation.Host;
. "$PSScriptRoot/../Types/OneShotTask.ps1";
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/Config.ps1";
. "$PSScriptRoot/Scripting.ps1"; . "$PSScriptRoot/Scripting.ps1";
. "$PSScriptRoot/../Scripts/SoftwareManagement.ps1"; . "$PSScriptRoot/SoftwareManagement.ps1";
. "$PSScriptRoot/../Types/OneShotTask.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Constants.ps1"; . "$PSScriptRoot/../../Windows/Scripts/Constants.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Hooks.ps1"; . "$PSScriptRoot/../../Windows/Scripts/Hooks.ps1";
. "$PSScriptRoot/../../Windows/Scripts/PowerManagement.ps1"; . "$PSScriptRoot/../../Windows/Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Registry.ps1"; . "$PSScriptRoot/../../Windows/Scripts/Registry.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Security.ps1"; . "$PSScriptRoot/../../Windows/Scripts/Security.ps1";
. "$PSScriptRoot/../../Windows/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Windows/Scripts/System.ps1";
. "$PSScriptRoot/../../Windows/Scripts/Tasks.ps1";
. "$PSScriptRoot/../../Windows/Scripts/WSL.ps1"; . "$PSScriptRoot/../../Windows/Scripts/WSL.ps1";
$oneShotTaskName = "PortValhalla OneShot";
$logName = "Application";
$oneShotTrigger = 1337;
$taskOption = "OneShotTask";
$getErrorPath = {
Join-Path (Get-ArtifactRoot) "error.txt";
};
$getUserName = {
"$(Get-SetupUser)OneShot";
};
$taskSetter = {
param([Nullable[OneShotTask]] $Task)
Set-SetupOption $taskOption ([string]$Task);
};
<# <#
.SYNOPSIS .SYNOPSIS
@ -289,141 +271,6 @@ $null = New-Module {
& $cleanup; & $cleanup;
} }
<#
.SYNOPSIS
Gets the current OneShot task.
#>
function Get-OneShotTask {
$task = Get-SetupOption $taskOption;
if ($task) {
return [OneShotTask]$task;
} else {
return $null;
}
}
<#
.SYNOPSIS
Registers a task for listening to OneShot invocations.
#>
function Enable-OneShotListener {
$tempTask = "PortValhalla Temp";
$user = & $getUserName;
$password = [string]([guid]::NewGuid());
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
$null = New-LocalUser -Name $user -Password (ConvertTo-SecureString -AsPlainText $password);
Add-LocalGroupMember -Member $user @adminGroup;
$logPath = Join-Path (Get-ArtifactRoot) "OneShotTask.log";
$path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList";
$null = New-Item -Force -ErrorAction SilentlyContinue $path;
Set-ItemProperty $path -Name $user -Value 0;
$action = New-ScheduledTaskAction -Execute "pwsh" -Argument "-Command & { $([string](Get-StartupCommand)) } 2>&1 | Tee-Object -FilePath $(ConvertTo-Injection $logPath)";
schtasks /Create /SC ONEVENT /EC $logName /MO "*[System[Provider[@Name='$logName'] and EventID=$($oneShotTrigger)]]" /TR cmd.exe /TN $tempTask;
$trigger = (Get-ScheduledTask $tempTask).Triggers;
$null = Register-ScheduledTask -Force $oneShotTaskName -Action $action -Trigger $trigger -RunLevel Highest -User $user -Password $password;
$null = Unregister-ScheduledTask -Confirm:$false $tempTask;
}
<#
.SYNOPSIS
Removes the OneShot task.
#>
function Disable-OneShotListener {
Unregister-ScheduledTask -Confirm:$false $oneShotTaskName;
$user = Get-LocalUser (& $getUserName);
[string] $sid = $user.SID;
Remove-LocalUser $user;
Get-CimInstance Win32_UserProfile | Where-Object { $_.SID -eq $sid } | Remove-CimInstance;
}
<#
.SYNOPSIS
Invokes a one-shot task.
.PARAMETER Task
The task to run.
#>
function Invoke-OneShot {
param(
[OneShotTask] $Task
)
$errorPath = & $getErrorPath;
& $taskSetter $Task;
& {
$identifier = "EventLog$oneShotTrigger";
$log = [System.Diagnostics.EventLog]::new($logName);
$log.EnableRaisingEvents = $true;
$null = Register-ObjectEvent -InputObject $log -EventName EntryWritten -Action {
$entry = $Event.SourceEventArgs.Entry;
$trigger = $Event.MessageData.Trigger;
$identifier = $Event.MessageData.Identifier;
if ($entry.EventID -eq $trigger) {
$null = New-Event -SourceIdentifier $identifier;
}
} `
-MessageData @{
Trigger = $oneShotTrigger;
Identifier = $identifier;
};
Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "Starting OneShot task ``$(Get-OneShotTask)``";
for ($i = 0; $i -lt 2; $i++) {
Remove-Event -EventIdentifier (Wait-Event -SourceIdentifier $identifier).EventIdentifier;
}
};
if (Test-Path $errorPath) {
$errorMessage = Get-Content $errorPath;
Remove-Item $errorPath;
if ($errorMessage) {
Write-Error $errorMessage;
}
}
}
# ToDo: Store Run-OneShot and Receive-OneShot somewhere else in Windows folder
<#
.SYNOPSIS
Executes the specified action and notifies the OneShot task executor.
#>
function Start-OneShot {
try {
Write-Host "Running OneShot task ``$(Get-OneShotTask)``";
switch (Get-OneShotTask) {
([OneShotTask]::InitializeMSAccount) {
Initialize-UserCreation;
}
([OneShotTask]::DisableUAC) {
Disable-UAC;
Register-Setup;
}
}
}
catch {
$errorPath = & $getErrorPath;
Set-Content -Path $errorPath -Value $Error;
Set-UserPermissions $errorPath;
}
finally {
& $taskSetter $null;
Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "The OneShot task ``$(Get-OneShotTask)`` finished.";
}
}
<# <#
.SYNOPSIS .SYNOPSIS
Clears resources allocated during the operation. Clears resources allocated during the operation.

View file

@ -1,297 +1,11 @@
. "$PSScriptRoot/Config.ps1";
. "$PSScriptRoot/Operations.ps1"; . "$PSScriptRoot/Operations.ps1";
. "$PSScriptRoot/System.ps1"; . "$PSScriptRoot/System.ps1";
. "$PSScriptRoot/../Types/InstallerAction.ps1"; . "$PSScriptRoot/../Types/InstallerAction.ps1";
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/BrowserAutomation.ps1";
. "$PSScriptRoot/SoftwareManagement.ps1";
. "$PSScriptRoot/../Types/InstallerAction.ps1"; . "$PSScriptRoot/../Types/InstallerAction.ps1";
$userArgument = "name"; $userArgument = "name";
$chocoRunner = {
param(
[string] $Action = 'install',
[string[]] $ArgumentList,
[scriptblock] $Guard = { $true },
[Parameter(Position = 0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
[System.Collections.ArrayList] $Names = @();
$null = $Names.Add($Name);
$Names.AddRange($AdditionalNames);
if (-not ($Force.IsPresent)) {
for ($i = $Names.Count - 1; $i -ge 0; $i--) {
$name = $Names[$i];
if (-not (& $Guard $name)) {
$Names.RemoveAt($i);
}
}
}
if ($Names.Count -ge 1) {
choco $Action -y @ArgumentList @Names;
}
};
$wingetRunner = {
param(
[string] $Action = 'install',
[string[]] $ArgumentList,
[scriptblock] $Guard = { $true },
[Parameter(Position = 0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
[System.Collections.ArrayList] $Names = @();
$null = $Names.Add($Name);
$Names.AddRange($AdditionalNames);
[string[]] $arguments = $ArgumentList + (& {
if ($Action -eq 'install') {
@("--accept-package-agreements")
};
});
foreach ($name in $Names) {
if ($Force.IsPresent -or (& $Guard $name $PSBoundParameters)) {
winget $Action `
--accept-source-agreements `
--source winget `
@arguments `
--exact --id $name ;
} else {
Write-Host "Package ``$name`` is already installed"
}
}
};
<#
.SYNOPSIS
Installs the specified packages using chocolatey.
.PARAMETER Names
The names of the packages to install.
#>
function Install-ChocoPackage {
param(
[switch] $Force,
[string[]] $ArgumentList,
[Parameter(Position=0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
& $chocoRunner @PSBoundParameters -Guard {
param($Name)
if (Test-ChocoPackage $Name) {
Write-Host "Package ``$Name`` is already installed"
$false;
} else {
$true;
}
};
}
<#
.SYNOPSIS
Uninstalls the specified packages using chocolatey.
#>
function Uninstall-ChocoPackage {
param(
[string[]] $ArgumentList,
[Parameter(Position=0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
& $chocoRunner @PSBoundParameters -Action 'uninstall' -Guard {
param($Name)
if (Test-ChocoPackage $Name) {
$true;
} else {
Write-Host "Package ``$Name`` is not installed";
$false;
}
};
}
<#
.SYNOPSIS
Installs the specified packages using `winget`.
.PARAMETER Names
The names of the packages to install.
#>
function Install-WingetPackage {
param(
[switch] $Force,
[string[]] $ArgumentList,
[Parameter(Position=0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
& $wingetRunner @PSBoundParameters `
-Guard {
param($Name, $Parameters)
if (Test-WingetPackage -Name $Name @Parameters) {
Write-Host "Package ``$Name`` is already installed"
$false;
} else {
$true;
}
};
}
<#
.SYNOPSIS
Uninstalls the specified packages using `winget`.
#>
function Uninstall-WingetPackage {
param(
[string[]] $ArgumentList,
[Parameter(Position=0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
& $wingetRunner @PSBoundParameters -Action 'uninstall' -Guard {
param($Name, $Parameters)
if (Test-WingetPackage -Name $Name @Parameters) {
$true;
} else {
Write-Host "Package ``$Name`` is not installed"
$false;
}
};
}
<#
.SYNOPSIS
Installs a setup package from the specified source.
.PARAMETER Source
The location of the setup package.
.PARAMETER ArgumentList
The arguments to pass to the setup package.
.PARAMETER Local
A value indicating whether the setup package is stored locally.
#>
function Install-SetupPackage {
param(
[string] $Source,
[string[]] $ArgumentList = @("/S"),
[switch] $Local
)
[string] $dir = $null;
[string] $filePath = $null;
if (-not ($Local.IsPresent)) {
$dir = New-TemporaryDirectory;
Write-Host "Determining the file name of ``$Source``";
$fileName = ([uri]$Source).Segments[-1];
Write-Host "Found name ``$fileName``";
$filePath = Join-Path $dir $fileName;
Write-Host "Downloading setup file from ``$Source``";
Invoke-WebRequest $Source -OutFile $filePath;
} else {
$filePath = $Source;
}
Write-Host "Starting installation of ``$(Split-Path -Leaf $filePath)``";
Start-Process -Wait -WorkingDirectory (Split-Path -Parent $filePath) -FilePath $filePath -ArgumentList $ArgumentList;
if ($dir) {
Remove-Item -Recurse $dir;
}
}
<#
.SYNOPSIS
Installs a package downloaded from ASUS.
.PARAMETER URL
The URL to download the package from.
#>
function Install-AsusPackage {
param(
[string] $URL
)
$file = "AsusPackage.zip";
$dir = New-TemporaryDirectory;
$unpackDir = New-TemporaryDirectory;
$null = Push-Location $dir;
Invoke-WebRequest $URL -OutFile $file;
Expand-Archive $file $unpackDir;
$null = Pop-Location;
Remove-Item -Recurse $dir;
$null = Start-Process -Wait -WorkingDirectory $unpackDir -FilePath (Join-Path $unpackDir "AsusSetup.exe") -ArgumentList "/S";
Remove-Item -Recurse $unpackDir;
}
<#
.SYNOPSIS
Downloads and installs a package from the AMD website.
.PARAMETER URL
The URL to download the package from.
#>
function Install-AmdPackage {
param(
[string] $URL
)
$dir = New-TemporaryDirectory;
$cookieBannerSelector = "#onetrust-consent-sdk";
$osSelector = "div[id$='oscategory']>div[id$='-0']";
$downloadSelector = "$osSelector div[id$='panel'] .button a";
$file = Start-CustomBrowserDownload @PSBoundParameters -OutDir $dir -Action {
param(
[OpenQA.Selenium.Firefox.FirefoxDriver] $Browser
)
$osContainer = $Browser.FindElement([OpenQA.Selenium.By]::CssSelector($osSelector));
if (-not ([bool] $osContainer.GetAttribute("cmp-expanded"))) {
$osContainer.Click();
}
$download = {
$browser.FindElement([OpenQA.Selenium.By]::CssSelector($downloadSelector)).Click();
};
try {
& $download;
} catch {
$null = $Browser.ExecuteScript("document.querySelector('$cookieBannerSelector').remove()");
& $download;
}
};
Start-Process -Wait -WorkingDirectory (Split-Path -Parent "$file") -FilePath "$file" -ArgumentList "/S";
Remove-Item -Recurse $dir;
}
function Start-SoftwareInstaller { function Start-SoftwareInstaller {
param( param(
[string] $Name, [string] $Name,

View file

@ -1,36 +1,3 @@
<#
.SYNOPSIS
Checks whether the specified package has been installed using Chocolatey.
.PARAMETER Name
The name of the package to check.
#>
function Test-ChocoPackage {
[OutputType([bool])]
param(
[string] $Name
);
-not [string]::IsNullOrEmpty((choco list --limit-output --exact $name));
}
<#
.SYNOPSIS
Checks whether a `winget` package with the specified id is installed.
.PARAMETER ID
The id of the package to check.
#>
function Test-WingetPackage {
[OutputType([bool])]
param(
[string] $Name,
[string[]] $ArgumentList
)
& { $null = winget list --accept-source-agreements -e --id $Name @ArgumentList; $?; };
}
<# <#
.SYNOPSIS .SYNOPSIS
Checks whether a command with the specified name exists. Checks whether a command with the specified name exists.
@ -46,21 +13,6 @@ function Test-Command {
[bool] (Get-Command $Name -ErrorAction SilentlyContinue); [bool] (Get-Command $Name -ErrorAction SilentlyContinue);
} }
<#
.SYNOPSIS
Checks whether `winget` is working properly.
#>
function Test-Winget {
(Test-Command winget) -and (
& {
$output = winget source update winget;
$? -and -not ([System.Linq.Enumerable]::Any(
[string[]]($output),
[System.Func[string,bool]]{ param($line) $line -eq "Cancelled"; }));
});
}
<# <#
.SYNOPSIS .SYNOPSIS
Checks whether a package with the specified name is installed. Checks whether a package with the specified name is installed.

View file

@ -9,60 +9,8 @@ function New-TemporaryDirectory {
<# <#
.SYNOPSIS .SYNOPSIS
Removes desktop icons which apply to the specified pattern. Checks whether the current user is the setup user.
.PARAMETER Pattern
The pattern to match the icons to delete.
#> #>
function Remove-DesktopIcon { function Test-SetupUser {
param( ($IsWindows ? $env:UserName : $env:USER) -eq (Get-SetupUser);
[string] $Pattern
)
$path = "Desktop/$Pattern";
foreach ($userDir in @("~", $env:PUBLIC, "$env:SystemDrive/Users/Default")) {
$fullName = "$userDir/$path";
if (Test-Path -PathType Leaf $fullName) {
Remove-Item $fullName;
}
}
}
<#
.SYNOPSIS
Adds a new shortcut to the start menu.
.PARAMETER Name
The name of the icon to create.
.PARAMETER Target
The file to link to.
#>
function Add-StartMenuIcon {
param(
[string] $Name,
[string] $Target
)
Import-Module KnownFolders;
Import-Module "$env:ChocolateyInstall/helpers/chocolateyInstaller.psm1";
Install-ChocolateyShortcut -ShortcutFilePath "$((Get-KnownFolder "Common Programs").Path)/$Name.lnk" -TargetPath ((Get-Item $Target).FullName);
}
<#
.SYNOPSIS
Removes icons from the task bar.
.PARAMETER Pattern
The pattern of the icon names to remove.
#>
function Remove-TaskbarItem {
param(
[string] $Pattern
)
Import-Module -UseWindowsPowerShell PinnedItem;
Get-PinnedItem -Type TaskBar | Where-Object { $_.Name -like "$Pattern" } | ForEach-Object { Remove-PinnedItem $_ };
} }

View file

@ -6,6 +6,7 @@ param(
& { & {
param($parameters); param($parameters);
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
$softwarePath = "$PSScriptRoot/../../Software"; $softwarePath = "$PSScriptRoot/../../Software";

View file

@ -10,13 +10,14 @@ $null = New-Module {
. "$PSScriptRoot/../Scripts/PowerManagement.ps1"; . "$PSScriptRoot/../Scripts/PowerManagement.ps1";
. "$PSScriptRoot/../Scripts/Registry.ps1"; . "$PSScriptRoot/../Scripts/Registry.ps1";
. "$PSScriptRoot/../Scripts/Security.ps1"; . "$PSScriptRoot/../Scripts/Security.ps1";
. "$PSScriptRoot/../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../Scripts/System.ps1";
. "$PSScriptRoot/../Scripts/Update.ps1"; . "$PSScriptRoot/../Scripts/Update.ps1";
. "$PSScriptRoot/../Scripts/Users.ps1"; . "$PSScriptRoot/../Scripts/Users.ps1";
. "$PSScriptRoot/../Types/WindowsInstallerAction.ps1"; . "$PSScriptRoot/../Types/WindowsInstallerAction.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1"; . "$PSScriptRoot/../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../Common/Scripts/Operations.ps1"; . "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
. "$PSScriptRoot/../../Common/Scripts/Scripting.ps1"; . "$PSScriptRoot/../../Common/Scripts/Scripting.ps1";
. "$PSScriptRoot/../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1"; . "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../Common/Types/InstallerAction.ps1";

View file

@ -1,5 +1,5 @@
. "$PSScriptRoot/PowerManagement.ps1"; . "$PSScriptRoot/PowerManagement.ps1";
. "$PSScriptRoot/../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1"; . "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../Common/Types/InstallerAction.ps1";

View file

@ -2,7 +2,6 @@ using namespace Microsoft.Win32;
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/../Scripts/Registry.ps1"; . "$PSScriptRoot/../Scripts/Registry.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../Common/Scripts/Scripting.ps1"; . "$PSScriptRoot/../../Common/Scripts/Scripting.ps1";
[RegistryKey] $key = $null; [RegistryKey] $key = $null;
$runOncePath = "Software\Microsoft\Windows\CurrentVersion\RunOnce"; $runOncePath = "Software\Microsoft\Windows\CurrentVersion\RunOnce";

View file

@ -1,6 +1,45 @@
using namespace Microsoft.Win32; using namespace Microsoft.Win32;
using namespace System.Security.AccessControl;
using namespace System.Security.Principal;
enum WindowsInstallerStage {
Initialize
Run
Cleanup
Completed
}
enum SetupStage {
Initialize
Configure
Install
CreateUser
}
enum BackupStage {
Initialize
Backup
BackupUsers
}
enum UserStage {
Create
Configure
Cleanup
Completed
}
$null = New-Module { $null = New-Module {
[string] $configRoot = "HKLM:\Software\PortValhalla";
[string] $stageOption = "Stage";
[string] $setupStageOption = "SetupStage";
[string] $backupStageOption = "BackupStage";
[string] $userOption = "SetupUser";
[string] $userStageOption = "UserStage";
[string] $accountOption = "MSAccount";
[string] $finishedOption = "Finished";
[RegistryKey] $key = $null;
function Edit-DefaultUserKey { function Edit-DefaultUserKey {
param( param(
[scriptblock] $Action [scriptblock] $Action
@ -17,6 +56,31 @@ $null = New-Module {
& reg unload $regRootPath; & reg unload $regRootPath;
} }
<#
.SYNOPSIS
Gets the registry key containing options related to the setup.
#>
function Get-SetupConfigKey {
if (-not (Test-Path $configRoot)) {
$key = New-Item $configRoot;
$acl = Get-Acl $configRoot;
$acl.AddAccessRule(
[RegistryAccessRule]::new(
[SecurityIdentifier]::new([WellKnownSidType]::BuiltinUsersSid, $null),
[RegistryRights]::FullControl,
[InheritanceFlags]::ObjectInherit -bor [InheritanceFlags]::ContainerInherit,
[PropagationFlags]::None,
[AccessControlType]::Allow));
Set-Acl $configRoot $acl;
} else {
$key = Get-Item $configRoot;
}
return $key;
}
<# <#
.SYNOPSIS .SYNOPSIS
Sets a message to show on the login screen. Sets a message to show on the login screen.
@ -53,4 +117,248 @@ $null = New-Module {
function Disable-BootMessage { function Disable-BootMessage {
Set-BootMessage; Set-BootMessage;
} }
<#
.SYNOPSIS
Gets the value of an option related to the setup.
.PARAMETER Name
The name of the option value to get.
#>
function Get-SetupOption {
param(
[string] $Name
)
$key = Get-SetupConfigKey;
if ($key.GetValueNames().Contains($Name)) {
return $key.GetValue($Name);
} else {
return $null;
}
}
<#
.SYNOPSIS
Sets the value of an option related to the setup.
.PARAMETER Name
The name of the option to set.
.PARAMETER Value
The value to set the option to.
#>
function Set-SetupOption {
param(
[string] $Name,
$Value
)
$key = (Get-SetupConfigKey).PSPath;
if ($null -eq $Value) {
Remove-ItemProperty $key -Name $Name;
} else {
$null = Set-ItemProperty $key -Name $Name -Value $Value;
}
}
<#
.SYNOPSIS
Gets the name of the current stage of the Windows install script action.
#>
function Get-Stage {
$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) {
$stage = [SetupStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the current stage.
.PARAMETER Name
The name to set the current stage to.
#>
function Set-SetupStage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([SetupStage]$Name).ToString();
}
$null = Set-SetupOption $setupStageOption $Name;
}
<#
.SYNOPSIS
Gets the name of the current stage of the backup.
#>
function Get-BackupStage {
$stage = Get-SetupOption $backupStageOption;
if ($null -ne $stage) {
$stage = [BackupStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the current stage of the backup.
.PARAMETER Name
The name to set the current stage to.
#>
function Set-BackupStage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([BackupStage]$Name).ToString();
}
$null = Set-SetupOption $backupStageOption $Name;
}
<#
.SYNOPSIS
Gets the current user to set up.
#>
function Get-CurrentUser {
return (Get-SetupOption $userOption) ?? 0;
}
<#
.SYNOPSIS
Sets the index of the current user to set up.
.PARAMETER Value
The index of the user to set up.
#>
function Set-CurrentUser {
param(
[int] $Value
)
Set-SetupOption $userOption $value;
}
<#
.SYNOPSIS
Gets the name of the current stage of the user setup.
#>
function Get-UserStage {
$stage = Get-SetupOption $userStageOption;
if ($null -ne $stage) {
$stage = [UserStage]$stage;
}
return $stage;
}
<#
.SYNOPSIS
Sets the current stage of the user setup.
.PARAMETER Name
The name of the stage to set.
#>
function Set-UserStage {
param(
$Name
)
if (-not (($null -eq $Name) -or ($Name -is [string]))) {
$Name = ([UserStage]$Name).ToString();
}
$null = Set-SetupOption $userStageOption $Name;
}
<#
.SYNOPSIS
Gets the name of the microsoft account to create.
#>
function Get-MSAccountName {
return Get-SetupOption $accountOption;
}
<#
.SYNOPSIS
Sets the name of the microsoft account to create.
.PARAMETER Name
The name of the microsoft account to create.
#>
function Set-MSAccountName {
param(
[string] $Name
)
Set-SetupOption $accountOption $Name;
}
<#
.SYNOPSIS
Gets a value indicating whether the setup has finished.
#>
function Get-IsFinished {
return [bool](Get-SetupOption $finishedOption);
}
<#
.SYNOPSIS
Sets a value indicating whether the setup has finished.
#>
function Set-IsFinished {
param(
$Value
)
Set-SetupOption $finishedOption $true;
}
} }

View file

@ -0,0 +1,335 @@
$null = New-Module {
. "$PSScriptRoot/../../Common/Scripts/BrowserAutomation.ps1";
. "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
$chocoRunner = {
param(
[string] $Action = 'install',
[string[]] $ArgumentList,
[scriptblock] $Guard = { $true },
[Parameter(Position = 0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
[System.Collections.ArrayList] $Names = @();
$null = $Names.Add($Name);
$Names.AddRange($AdditionalNames);
if (-not ($Force.IsPresent)) {
for ($i = $Names.Count - 1; $i -ge 0; $i--) {
$name = $Names[$i];
if (-not (& $Guard $name)) {
$Names.RemoveAt($i);
}
}
}
if ($Names.Count -ge 1) {
choco $Action -y @ArgumentList @Names;
}
};
$wingetRunner = {
param(
[string] $Action = 'install',
[string[]] $ArgumentList,
[scriptblock] $Guard = { $true },
[Parameter(Position = 0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
[System.Collections.ArrayList] $Names = @();
$null = $Names.Add($Name);
$Names.AddRange($AdditionalNames);
[string[]] $arguments = $ArgumentList + (& {
if ($Action -eq 'install') {
@("--accept-package-agreements")
};
});
foreach ($name in $Names) {
if ($Force.IsPresent -or (& $Guard $name $PSBoundParameters)) {
winget $Action `
--accept-source-agreements `
--source winget `
@arguments `
--exact --id $name ;
} else {
Write-Host "Package ``$name`` is already installed"
}
}
};
<#
.SYNOPSIS
Checks whether `winget` is working properly.
#>
function Test-Winget {
(Test-Command winget) -and (
& {
$output = winget source update winget;
$? -and -not ([System.Linq.Enumerable]::Any(
[string[]]($output),
[System.Func[string,bool]]{ param($line) $line -eq "Cancelled"; }));
});
}
<#
.SYNOPSIS
Checks whether the specified package has been installed using Chocolatey.
.PARAMETER Name
The name of the package to check.
#>
function Test-ChocoPackage {
[OutputType([bool])]
param(
[string] $Name
);
-not [string]::IsNullOrEmpty((choco list --limit-output --exact $name));
}
<#
.SYNOPSIS
Checks whether a `winget` package with the specified id is installed.
.PARAMETER ID
The id of the package to check.
#>
function Test-WingetPackage {
[OutputType([bool])]
param(
[string] $Name,
[string[]] $ArgumentList
)
& { $null = winget list --accept-source-agreements -e --id $Name @ArgumentList; $?; };
}
<#
.SYNOPSIS
Installs the specified packages using chocolatey.
.PARAMETER Names
The names of the packages to install.
#>
function Install-ChocoPackage {
param(
[switch] $Force,
[string[]] $ArgumentList,
[Parameter(Position=0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
& $chocoRunner @PSBoundParameters -Guard {
param($Name)
if (Test-ChocoPackage $Name) {
Write-Host "Package ``$Name`` is already installed"
$false;
} else {
$true;
}
};
}
<#
.SYNOPSIS
Uninstalls the specified packages using chocolatey.
#>
function Uninstall-ChocoPackage {
param(
[string[]] $ArgumentList,
[Parameter(Position=0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
& $chocoRunner @PSBoundParameters -Action 'uninstall' -Guard {
param($Name)
if (Test-ChocoPackage $Name) {
$true;
} else {
Write-Host "Package ``$Name`` is not installed";
$false;
}
};
}
<#
.SYNOPSIS
Installs the specified packages using `winget`.
.PARAMETER Names
The names of the packages to install.
#>
function Install-WingetPackage {
param(
[switch] $Force,
[string[]] $ArgumentList,
[Parameter(Position=0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
& $wingetRunner @PSBoundParameters `
-Guard {
param($Name, $Parameters)
if (Test-WingetPackage -Name $Name @Parameters) {
Write-Host "Package ``$Name`` is already installed"
$false;
} else {
$true;
}
};
}
<#
.SYNOPSIS
Uninstalls the specified packages using `winget`.
#>
function Uninstall-WingetPackage {
param(
[string[]] $ArgumentList,
[Parameter(Position=0)]
[string] $Name,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $AdditionalNames = @()
)
& $wingetRunner @PSBoundParameters -Action 'uninstall' -Guard {
param($Name, $Parameters)
if (Test-WingetPackage -Name $Name @Parameters) {
$true;
} else {
Write-Host "Package ``$Name`` is not installed"
$false;
}
};
}
<#
.SYNOPSIS
Installs a setup package from the specified source.
.PARAMETER Source
The location of the setup package.
.PARAMETER ArgumentList
The arguments to pass to the setup package.
.PARAMETER Local
A value indicating whether the setup package is stored locally.
#>
function Install-SetupPackage {
param(
[string] $Source,
[string[]] $ArgumentList = @("/S"),
[switch] $Local
)
[string] $dir = $null;
[string] $filePath = $null;
if (-not ($Local.IsPresent)) {
$dir = New-TemporaryDirectory;
Write-Host "Determining the file name of ``$Source``";
$fileName = ([uri]$Source).Segments[-1];
Write-Host "Found name ``$fileName``";
$filePath = Join-Path $dir $fileName;
Write-Host "Downloading setup file from ``$Source``";
Invoke-WebRequest $Source -OutFile $filePath;
} else {
$filePath = $Source;
}
Write-Host "Starting installation of ``$(Split-Path -Leaf $filePath)``";
Start-Process -Wait -WorkingDirectory (Split-Path -Parent $filePath) -FilePath $filePath -ArgumentList $ArgumentList;
if ($dir) {
Remove-Item -Recurse $dir;
}
}
<#
.SYNOPSIS
Installs a package downloaded from ASUS.
.PARAMETER URL
The URL to download the package from.
#>
function Install-AsusPackage {
param(
[string] $URL
)
$file = "AsusPackage.zip";
$dir = New-TemporaryDirectory;
$unpackDir = New-TemporaryDirectory;
$null = Push-Location $dir;
Invoke-WebRequest $URL -OutFile $file;
Expand-Archive $file $unpackDir;
$null = Pop-Location;
Remove-Item -Recurse $dir;
$null = Start-Process -Wait -WorkingDirectory $unpackDir -FilePath (Join-Path $unpackDir "AsusSetup.exe") -ArgumentList "/S";
Remove-Item -Recurse $unpackDir;
}
<#
.SYNOPSIS
Downloads and installs a package from the AMD website.
.PARAMETER URL
The URL to download the package from.
#>
function Install-AmdPackage {
param(
[string] $URL
)
$dir = New-TemporaryDirectory;
$cookieBannerSelector = "#onetrust-consent-sdk";
$osSelector = "div[id$='oscategory']>div[id$='-0']";
$downloadSelector = "$osSelector div[id$='panel'] .button a";
$file = Start-CustomBrowserDownload @PSBoundParameters -OutDir $dir -Action {
param(
[OpenQA.Selenium.Firefox.FirefoxDriver] $Browser
)
$osContainer = $Browser.FindElement([OpenQA.Selenium.By]::CssSelector($osSelector));
if (-not ([bool] $osContainer.GetAttribute("cmp-expanded"))) {
$osContainer.Click();
}
$download = {
$browser.FindElement([OpenQA.Selenium.By]::CssSelector($downloadSelector)).Click();
};
try {
& $download;
} catch {
$null = $Browser.ExecuteScript("document.querySelector('$cookieBannerSelector').remove()");
& $download;
}
};
Start-Process -Wait -WorkingDirectory (Split-Path -Parent "$file") -FilePath "$file" -ArgumentList "/S";
Remove-Item -Recurse $dir;
}
};

View file

@ -0,0 +1,76 @@
<#
.SYNOPSIS
Checks whether the running system is a QEMU virtual machine.
#>
function Test-Qemu {
((Get-WmiObject win32_computersystem).Manufacturer) -eq "QEMU";
}
<#
.SYNOPSIS
Checks whether the active session is executed with admin rights.
#>
function Test-Admin {
net session 2> $null | Out-Null;
return $?;
}
<#
.SYNOPSIS
Removes desktop icons which apply to the specified pattern.
.PARAMETER Pattern
The pattern to match the icons to delete.
#>
function Remove-DesktopIcon {
param(
[string] $Pattern
)
$path = "Desktop/$Pattern";
foreach ($userDir in @("~", $env:PUBLIC, "$env:SystemDrive/Users/Default")) {
$fullName = "$userDir/$path";
if (Test-Path -PathType Leaf $fullName) {
Remove-Item $fullName;
}
}
}
<#
.SYNOPSIS
Adds a new shortcut to the start menu.
.PARAMETER Name
The name of the icon to create.
.PARAMETER Target
The file to link to.
#>
function Add-StartMenuIcon {
param(
[string] $Name,
[string] $Target
)
Import-Module KnownFolders;
Import-Module "$env:ChocolateyInstall/helpers/chocolateyInstaller.psm1";
Install-ChocolateyShortcut -ShortcutFilePath "$((Get-KnownFolder "Common Programs").Path)/$Name.lnk" -TargetPath ((Get-Item $Target).FullName);
}
<#
.SYNOPSIS
Removes icons from the task bar.
.PARAMETER Pattern
The pattern of the icon names to remove.
#>
function Remove-TaskbarItem {
param(
[string] $Pattern
)
Import-Module -UseWindowsPowerShell PinnedItem;
Get-PinnedItem -Type TaskBar | Where-Object { $_.Name -like "$Pattern" } | ForEach-Object { Remove-PinnedItem $_ };
}

View file

@ -0,0 +1,156 @@
$null = New-Module {
. "$PSScriptRoot/Constants.ps1";
. "$PSScriptRoot/Registry.ps1";
. "$PSScriptRoot/../Types/OneShotTask.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1";
$oneShotTaskName = "PortValhalla OneShot";
$logName = "Application";
$oneShotTrigger = 1337;
$taskOption = "OneShotTask";
$getErrorPath = {
Join-Path (Get-ArtifactRoot) "error.txt";
};
$getUserName = {
"$(Get-SetupUser)OneShot";
};
$taskSetter = {
param([Nullable[OneShotTask]] $Task)
Set-SetupOption $taskOption ([string]$Task);
};
<#
.SYNOPSIS
Gets the current OneShot task.
#>
function Get-OneShotTask {
$task = Get-SetupOption $taskOption;
if ($task) {
return [OneShotTask]$task;
} else {
return $null;
}
}
<#
.SYNOPSIS
Registers a task for listening to OneShot invocations.
#>
function Enable-OneShotListener {
$tempTask = "PortValhalla Temp";
$user = & $getUserName;
$password = [string]([guid]::NewGuid());
$adminGroup = @{
SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null);
};
$null = New-LocalUser -Name $user -Password (ConvertTo-SecureString -AsPlainText $password);
Add-LocalGroupMember -Member $user @adminGroup;
$logPath = Join-Path (Get-ArtifactRoot) "OneShotTask.log";
$path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList";
$null = New-Item -Force -ErrorAction SilentlyContinue $path;
Set-ItemProperty $path -Name $user -Value 0;
$action = New-ScheduledTaskAction -Execute "pwsh" -Argument "-Command & { $([string](Get-StartupCommand)) } 2>&1 | Tee-Object -FilePath $(ConvertTo-Injection $logPath)";
schtasks /Create /SC ONEVENT /EC $logName /MO "*[System[Provider[@Name='$logName'] and EventID=$($oneShotTrigger)]]" /TR cmd.exe /TN $tempTask;
$trigger = (Get-ScheduledTask $tempTask).Triggers;
$null = Register-ScheduledTask -Force $oneShotTaskName -Action $action -Trigger $trigger -RunLevel Highest -User $user -Password $password;
$null = Unregister-ScheduledTask -Confirm:$false $tempTask;
}
<#
.SYNOPSIS
Removes the OneShot task.
#>
function Disable-OneShotListener {
Unregister-ScheduledTask -Confirm:$false $oneShotTaskName;
$user = Get-LocalUser (& $getUserName);
[string] $sid = $user.SID;
Remove-LocalUser $user;
Get-CimInstance Win32_UserProfile | Where-Object { $_.SID -eq $sid } | Remove-CimInstance;
}
<#
.SYNOPSIS
Invokes a one-shot task.
.PARAMETER Task
The task to run.
#>
function Invoke-OneShot {
param(
[OneShotTask] $Task
)
$errorPath = & $getErrorPath;
& $taskSetter $Task;
& {
$identifier = "EventLog$oneShotTrigger";
$log = [System.Diagnostics.EventLog]::new($logName);
$log.EnableRaisingEvents = $true;
$null = Register-ObjectEvent -InputObject $log -EventName EntryWritten -Action {
$entry = $Event.SourceEventArgs.Entry;
$trigger = $Event.MessageData.Trigger;
$identifier = $Event.MessageData.Identifier;
if ($entry.EventID -eq $trigger) {
$null = New-Event -SourceIdentifier $identifier;
}
} `
-MessageData @{
Trigger = $oneShotTrigger;
Identifier = $identifier;
};
Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "Starting OneShot task ``$(Get-OneShotTask)``";
for ($i = 0; $i -lt 2; $i++) {
Remove-Event -EventIdentifier (Wait-Event -SourceIdentifier $identifier).EventIdentifier;
}
};
if (Test-Path $errorPath) {
$errorMessage = Get-Content $errorPath;
Remove-Item $errorPath;
if ($errorMessage) {
Write-Error $errorMessage;
}
}
}
<#
.SYNOPSIS
Executes the specified action and notifies the OneShot task executor.
#>
function Start-OneShot {
try {
Write-Host "Running OneShot task ``$(Get-OneShotTask)``";
switch (Get-OneShotTask) {
([OneShotTask]::InitializeMSAccount) {
Initialize-UserCreation;
}
([OneShotTask]::DisableUAC) {
Disable-UAC;
Register-Setup;
}
}
}
catch {
$errorPath = & $getErrorPath;
Set-Content -Path $errorPath -Value $Error;
Set-UserPermissions $errorPath;
}
finally {
& $taskSetter $null;
Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "The OneShot task ``$(Get-OneShotTask)`` finished.";
}
}
}

View file

@ -3,9 +3,11 @@ using namespace System.Security.Principal;
$null = New-Module { $null = New-Module {
. "$PSScriptRoot/Deployment.ps1"; . "$PSScriptRoot/Deployment.ps1";
. "$PSScriptRoot/Registry.ps1";
. "$PSScriptRoot/System.ps1";
. "$PSScriptRoot/../Types/OneShotTask.ps1";
. "$PSScriptRoot/../../Common/Scripts/Config.ps1"; . "$PSScriptRoot/../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../Common/Scripts/Operations.ps1"; . "$PSScriptRoot/../../Common/Scripts/Operations.ps1";
. "$PSScriptRoot/../../Common/Types/OneShotTask.ps1";
$loggedInUserOption = "LoggedInUser"; $loggedInUserOption = "LoggedInUser";
<# <#

View file

@ -1,5 +1,6 @@
. "$PSScriptRoot/Constants.ps1"; . "$PSScriptRoot/Constants.ps1";
. "$PSScriptRoot/../Scripts/Security.ps1"; . "$PSScriptRoot/../Scripts/Security.ps1";
. "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1";
<# <#
.SYNOPSIS .SYNOPSIS
@ -57,7 +58,6 @@ function Install-Wsl {
wsl --install --no-launch; wsl --install --no-launch;
# Microsoft broke WSL - Quelle surprise! # Microsoft broke WSL - Quelle surprise!
# ToDo: Remove this workaround once it's unbroken # ToDo: Remove this workaround once it's unbroken
. "$PSScriptRoot/../../Common/Scripts/Software.ps1";
Install-SetupPackage "https://github.com/microsoft/WSL/releases/download/2.3.17/wsl.2.3.17.0.x64.msi" -ArgumentList "/Quiet"; Install-SetupPackage "https://github.com/microsoft/WSL/releases/download/2.3.17/wsl.2.3.17.0.x64.msi" -ArgumentList "/Quiet";
} }
@ -125,3 +125,47 @@ function Unregister-WslDistribution {
Uninstall-WslDistribution; Uninstall-WslDistribution;
Move-Item $tempDisk $wslDisk; Move-Item $tempDisk $wslDisk;
} }
<#
.SYNOPSIS
Converts the specified path to linux and escapes it for the use in a script.
.PARAMETER Path
The path to convert.
#>
function ConvertTo-LinuxPath {
param(
[string] $Path
)
& {
$ErrorActionPreference = 'Continue';
$completed = $false;
while (-not $completed) {
$job = Start-Job {
$env:Value = Resolve-Path $Using:Path;
$env:WSLENV = "Value/p";
$result = wsl -- bash -c 'echo "$Value"';
wsl -e printf "%q" "$result";
};
$result = Receive-Job -Wait $job;
if ((Split-Path -Leaf $Path) -ne (Split-Path -Leaf $result)) {
Write-Error "The result of the path conversion of ``$Path`` was unexpected: ``$result``";
continue;
}
if ($job.State -ne ([System.Management.Automation.JobState]::Completed)) {
Write-Error "An error occurred while converting ``$Path`` to a Linux path.`nOutput: ``$result``";
continue;
}
$completed = $true;
}
$result;
};
}

View file

@ -3,6 +3,7 @@ param (
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";

View file

@ -4,6 +4,7 @@ param(
) )
. "$PSScriptRoot/../../Scripts/AppAssociations.ps1"; . "$PSScriptRoot/../../Scripts/AppAssociations.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `

View file

@ -6,6 +6,7 @@ param(
& { & {
param ($Parameters) param ($Parameters)
. "$PSScriptRoot/../../Scripts/Restoration.ps1"; . "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
$configPath = "$env:LocalAppData/LGHUB"; $configPath = "$env:LocalAppData/LGHUB";

View file

@ -3,6 +3,7 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `

View file

@ -6,6 +6,7 @@ param(
& { & {
param($Parameters) param($Parameters)
. "$PSScriptRoot/../../Scripts/Restoration.ps1"; . "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1"; . "$PSScriptRoot/../../../Common/Scripts/System.ps1";
$path = "$HOME/Documents/ManiaPlanet"; $path = "$HOME/Documents/ManiaPlanet";

View file

@ -3,6 +3,7 @@ param (
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";

View file

@ -6,6 +6,7 @@ param(
) )
. "$PSScriptRoot/../../Scripts/Restoration.ps1"; . "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1"; . "$PSScriptRoot/../../../Common/Scripts/System.ps1";

View file

@ -6,6 +6,7 @@ param(
& { & {
param($Parameters) param($Parameters)
. "$PSScriptRoot/../../Scripts/Restoration.ps1"; . "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1"; . "$PSScriptRoot/../../../Common/Scripts/System.ps1";
$path = "C:/tools/RetroArch-Win64"; $path = "C:/tools/RetroArch-Win64";

View file

@ -6,6 +6,7 @@ param(
) )
. "$PSScriptRoot/../../Scripts/AppAssociations.ps1"; . "$PSScriptRoot/../../Scripts/AppAssociations.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
Start-SoftwareInstaller @PSBoundParameters ` Start-SoftwareInstaller @PSBoundParameters `

View file

@ -5,6 +5,7 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1"; . "$PSScriptRoot/../../../Common/Scripts/System.ps1";

View file

@ -3,6 +3,7 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1"; . "$PSScriptRoot/../../../Common/Scripts/System.ps1";

View file

@ -7,6 +7,7 @@ param(
& { & {
param($Parameters) param($Parameters)
. "$PSScriptRoot/../../Scripts/Restoration.ps1"; . "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
$path = "$HOME/Documents/TmForever"; $path = "$HOME/Documents/TmForever";

View file

@ -3,6 +3,7 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1"; . "$PSScriptRoot/../../../Common/Scripts/System.ps1";

View file

@ -7,6 +7,7 @@ param(
param($parameters) param($parameters)
. "$PSScriptRoot/../../Scripts/Restoration.ps1"; . "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/BrowserAutomation.ps1"; . "$PSScriptRoot/../../../Common/Scripts/BrowserAutomation.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/SoftwareManagement.ps1"; . "$PSScriptRoot/../../../Common/Scripts/SoftwareManagement.ps1";

View file

@ -6,6 +6,7 @@ param(
) )
. "$PSScriptRoot/../../Scripts/AppAssociations.ps1"; . "$PSScriptRoot/../../Scripts/AppAssociations.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1"; . "$PSScriptRoot/../../../Common/Scripts/System.ps1";

View file

@ -3,6 +3,7 @@ param (
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";

View file

@ -3,6 +3,7 @@ param (
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Config.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Config.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";

View file

@ -3,6 +3,7 @@ param(
[hashtable] $Arguments [hashtable] $Arguments
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
& { & {

View file

@ -6,6 +6,7 @@ param(
& { & {
param($Parameters) param($Parameters)
. "$PSScriptRoot/../../Scripts/Restoration.ps1"; . "$PSScriptRoot/../../Scripts/Restoration.ps1";
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Scripts/System.ps1"; . "$PSScriptRoot/../../../Common/Scripts/System.ps1";
$path = "$env:AppData/osu"; $path = "$env:AppData/osu";

View file

@ -8,6 +8,7 @@ param(
[hashtable] $Parameters [hashtable] $Parameters
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";
$base = "$PSScriptRoot/../../../Common/Software/vscode/Main.ps1"; $base = "$PSScriptRoot/../../../Common/Software/vscode/Main.ps1";

View file

@ -8,6 +8,7 @@ param(
[hashtable] $Parameters [hashtable] $Parameters
) )
. "$PSScriptRoot/../../Scripts/SoftwareManagement.ps1";
. "$PSScriptRoot/../../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../../Common/Scripts/Software.ps1";
. "$PSScriptRoot/../../../Common/Software/PowerShell/Profile.ps1"; . "$PSScriptRoot/../../../Common/Software/PowerShell/Profile.ps1";
. "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1"; . "$PSScriptRoot/../../../Common/Types/InstallerAction.ps1";