Files
ProjectTools/PSUtilities/ScriptTemplate.ps1
2025-02-28 23:38:24 -06:00

166 lines
6.2 KiB
PowerShell

<#
.SYNOPSIS
Provide a brief description of script purpose
.DESCRIPTION
Provide a more detailed description of script purpose
.EXAMPLE
Provide an example usage for the script
.NOTES
NAME:
AUTHOR:
LASTEDIT:
VERSION:
#>
#region Parameters
param (
# Allows modules required by the script to be predefined, and loaded or installed as needed
[Parameter(DontShow = $true)] [Array] $ModuleNames = @(),
# Sets the script storage location
[Parameter(DontShow = $true)] [ValidateSet('System', 'User', 'Custom')] [String] $ScriptType = "System",
# Allows adding verbose logging and what-if command simulation to the script
[Parameter(DontShow = $true)] [Switch] $Dev,
# Allows for the script logs to output to a nonstandard location. Overrides user/computer script paths
[Parameter(Mandatory = $false)] [String] $ScriptDir,
# Flag to disable log file output
[Parameter(Mandatory = $false)] [Switch] $NoLog,
# Allows for uninstallation of script
[Parameter(Mandatory = $false)] [Switch] $Uninstall
#TODO: Add additional parameters, if appropriate
)
#endregion Parameters
#region Architecture Check
# Verifies script is running in 64-bit PowerShell, if available. Allows for parameters to be passed to relaunched script
# Origin: https://z-nerd.com/blog/2020/03/31-intune-win32-apps-powershell-script-installer/
If ($Env:PROCESSOR_ARCHITECTURE -ne "AMD64") {
If (Test-Path -Path "$Env:WinDir\SysNative\WindowsPowerShell\v1.0\powershell.exe" -PathType Leaf) {
$ArgsString = ""
Try {
ForEach ($Key in $MyInvocation.BoundParameters.Keys) {
Switch ($MyInvocation.BoundParameters[$Key].GetType().Name) {
"SwitchParameter" { if ($MyInvocation.BoundParameters[$Key].IsPresent) { $ArgsString += "-$Key " } }
"String" { $ArgsString += "-$Key `"$($MyInvocation.BoundParameters[$Key])`" " }
"Int32" { $ArgsString += "-$Key $($MyInvocation.BoundParameters[$Key]) " }
"Boolean" { $ArgsString += "-$Key `$$($MyInvocation.BoundParameters[$Key]) " }
}
}
Start-Process -FilePath "$ENV:WINDIR\SysNative\WindowsPowershell\v1.0\PowerShell.exe" -ArgumentList `
"-ExecutionPolicy Bypass -NoProfile -File $PSCommandPath $ArgsString" -Wait -NoNewWindow
}
Catch {
Throw "Failed to start `"$PSCommandPath`" in 64-bit PowerShell"
}
Exit $LASTEXITCODE
}
}
#endregion Architecture Check
#region Imports
# Import Test-CommandExists, Add-LogEntry, Add-ListItem, Import-JSONConfig, Import-YAMLConfig, Set-RegistryKey, Test-AsAdmin, Format-Hyperlink
Invoke-WebRequest "https://gitea.taco.quest/Mindfang/ProjectTools/raw/branch/main/PSUtilities/ScriptTools.ps1" -OutFile "$Env:Temp\ScriptTools.ps1"
Import-Module -Name "$Env:Temp\ScriptTools.ps1" -Force
#endregion Imports
#region Functions
#endregion Functions
#region Prep
# Set the working directory for logs and additional files
$ThisScript = ([IO.FileInfo]$MyInvocation.MyCommand.Definition).BaseName
Switch ($ScriptType) {
"System" { $AppDir = "$Env:AppData\Mindfang\$ThisScript" }
"User" { $AppDir = "$Env:ProgramData\Mindfang\$ThisScript" }
"Custom" {
If ($ScriptDir) { $AppDir = $ScriptDir }
Else { $AppDir = $PWD }
}
}
# Create specified appdir if it does not already exist
If (-Not (Test-Path $AppDir)) {
New-Item $AppDir -ItemType Directory
}
# Begin recording transcript file
If (-Not $NoLog) {
If (-not $LogDir) {
$LogDir = $AppDir
}
Add-LogEntry (Start-Transcript "$AppDir\$ThisScript.log" -Append)
}
# Load any modules required by script
If ($ModuleNames) {
If ([Net.ServicePointManager]::SecurityProtocol -ne [Net.SecurityProtocolType]::SystemDefault) {
Add-LogEntry "Upgrading TLS security protocol to 1.2"
Try { [Net.ServicePointManager]::SecurityProtocol = @([Net.SecurityProtocolType]::Tls, [Net.SecurityProtocolType]::Tls11, [Net.SecurityProtocolType]::Tls12) }
Catch {
Add-LogEntry "TLS upgrade failed, script is exiting" -As Error
Exit
}
}
If ((Get-PackageProvider).Name -notcontains "NuGet") {
Add-LogEntry "Installing NuGet package provider"
Try { Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -ErrorAction Stop | Out-Null }
Catch {
Add-LogEntry "Installation failed, script is exiting" -As Error
Exit
}
}
If ((Get-PSRepository).Name -notcontains "PSGallery") {
Add-LogEntry "Registering PSGallery as script source"
Try { Register-PSRepository -Default -InstallationPolicy Trusted -ErrorAction Stop }
Catch {
Add-LogEntry "Unable to register PSGallery, script is exiting" -As Error
Exit
}
}
ElseIf (Get-PSRepository | Where-Object { $_.Name -eq "PSGallery" -and $_.InstallationPolicy -ne "Trusted" }) {
Add-LogEntry "Trusting packages from PSGallery"
Try { Set-PSRepository PSGallery -InstallationPolicy Trusted -ErrorAction Stop }
Catch {
Add-LogEntry "Unable to set PSGallery as trusted, script is exiting" -As Error
Exit
}
}
ForEach ($Module in $ModuleNames) {
If (-Not (Get-Module -ListAvailable -Name $Module)) {
Try {
Add-LogEntry "Module `"$Module`" not found, installing"
Install-Module -Name $Module -Scope CurrentUser -Force -AllowClobber
}
Catch {
Add-LogEntry "Module failed to install automatically! Manaully install the module, then re-run the script." -As Error
Exit 1
}
}
Import-Module $Module
}
}
#endregion Prep
#region Execution
Try {
If (-Not $Uninstall) {
#TODO: "Install actions" for the script go here
}
Else {
#TODO: "Uninstall actions" for the script go here
}
}
Catch {
# Write error to logs, if an exception is caught
Write-Host "Script execution failed!"
Write-Host $_
Write-Host $_.InvocationInfo
Write-Host $_.ScriptStackTrace
Exit 1
}
Finally {
# Stop transcript, even if an error has occurred
If (-Not $NoLog) {
Stop-Transcript
}
}
#endregion Execution