Add files via upload

This commit is contained in:
freedbygrace
2020-06-18 10:46:56 -04:00
committed by GitHub
parent 557fcba6f5
commit f4c486c938
8 changed files with 894 additions and 0 deletions
@@ -0,0 +1 @@
###
+1
View File
@@ -0,0 +1 @@
###
@@ -0,0 +1 @@
###
Binary file not shown.
+564
View File
@@ -0,0 +1,564 @@
$Script:TaskSequenceEnvironment = $null
$Script:TaskSequenceProgressUi = $null
function Confirm-TSEnvironmentSetup()
{
<#
.SYNOPSIS
Verifies the TSEnvironment Com Object is initiated into an object.
.DESCRIPTION
Verifies the TSEnvironment Com Object is initiated into an object.
.INPUTS
None
.OUTPUTS
None
.NOTE
This module can be used statically to initiate the TSEnvironment module, however, simply running one of the commands will initate it for you.
#>
if ($Script:TaskSequenceEnvironment -eq $null)
{
try
{
$Script:TaskSequenceEnvironment = New-Object -ComObject Microsoft.SMS.TSEnvironment
}
catch
{
throw "Unable to connect to the Task Sequence Environment! Please verify you are in a running Task Sequence Environment.`n`nErrorDetails:`n$_"
}
}
}
function Get-TSVariables()
{
<#
.SYNOPSIS
Get all Task Sequence Variable Names
.DESCRIPTION
Returns a string array of all Task Sequence Variable Names (not values).
.INPUT
None
.OUTPUTS
String[]
.EXAMPLE
$arrayOfVariableNames = Get-TSVariables
#>
Confirm-TSEnvironmentSetup
$allVar = @()
foreach ($variable in $Script:TaskSequenceEnvironment.GetVariables())
{
$allVar += $variable
}
return $allVar
}
function Get-TSValue()
{
<#
.SYNOPSIS
Get a Task Sequence Variables Value
.DESCRIPTION
Obtains the value of a specific Task Sequence Variable.
.PARAMETER Name
Specifies the variable name to resolve.
.INPUTS
String
.OUTPUTS
String
.EXAMPLE
$OsdComputerName = Get-TSValue -Name "OSDComputerName"
#>
param(
[Parameter(Mandatory=$true)]
[string] $Name
)
Confirm-TSEnvironmentSetup
return $Script:TaskSequenceEnvironment.Value($Name)
}
function Set-TSVariable()
{
<#
.SYNOPSIS
Set or Create a Task Sequence Variables Value
.DESCRIPTION
Sets or Creates a Task Sequence Variables Value.
Will return a boolean value indicating success or failure.
.PARAMETER Name
Specifies the variable name to set or create.
.PARAMETER Value
Specifies the variable value
.INPUTS
- Name: String
- Value: System.Boolean
.OUTPUTS
System.Boolean
.EXAMPLE
Sets the OSDComputerName task sequence variable to "MyComputer123"
$didSet = Set-TSVariable -Name "OSDComputerName" -Value "MyComputer123"
.EXAMPLE
Creates a new Task Sequence Variable, and sets its value
$didSet = Set-TSVariable -Name "MyNewVar" -Value 'MyNewVarsValue"
#>
param(
[Parameter(Mandatory=$true)]
[string] $Name,
[Parameter(Mandatory=$true)]
[string] $Value
)
Confirm-TSEnvironmentSetup
try
{
$Script:TaskSequenceEnvironment.Value($Name) = $Value
return $true
}
catch
{
return $false
}
}
function Get-TSAllValues()
{
<#
.SYNOPSIS
Gets all Task Sequence Variables and Values
.DESCRIPTION
Gets all Task Sequence Variables with their associated values.
.INPUTS
None
.OUTPUTS
System.Object
.EXAMPLE
$TSVariableObject = Get-TSAllValues
#>
Confirm-TSEnvironmentSetup
$Values = New-Object -TypeName System.Object
foreach ($Variable in $Script:TaskSequenceEnvironment.GetVariables())
{
$Values | Add-Member -MemberType NoteProperty -Name $Variable -Value "$($Script:TaskSequenceEnvironment.Value($Variable))"
}
return $Values
}
function Confirm-TSProgressUISetup()
{
<#
.SYNOPSIS
Verifies the TSProgresUI Com Object is initiated into an object.
.DESCRIPTION
Verifies the TSProgresUI Com Object is initiated into an object.
.INPUTS
None
.OUTPUTS
None
.NOTE
This module can be used statically but is intended to be used by other functions.
#>
if ($Script:TaskSequenceProgressUi -eq $null)
{
try
{
$Script:TaskSequenceProgressUi = New-Object -ComObject Microsoft.SMS.TSProgressUI
}
catch
{
throw "Unable to connect to the Task Sequence Progress UI! Please verify you are in a running Task Sequence Environment. Please note: TSProgressUI cannot be loaded during a prestart command.`n`nErrorDetails:`n$_"
}
}
}
function Show-TSActionProgress()
{
<#
.SYNOPSIS
Shows task sequence secondary progress of a specific step
.DESCRIPTION
Adds a second progress bar to the existing Task Sequence Progress UI.
This progress bar can be updated to allow for a real-time progress of
a specific task sequence sub-step.
The Step and Max Step parameters are calculated when passed. This allows
you to have a "max steps" of 400, and update the step parameter. 100%
would be achieved when step is 400 and max step is 400. The percentages
are calculated behind the scenes by the Com Object.
.PARAMETER Message
The message to display the progress
.PARAMETER Step
Integer indicating current step
.PARAMETER MaxStep
Integer indicating 100%. A number other than 100 can be used.
.INPUTS
- Message: String
- Step: Long
- MaxStep: Long
.OUTPUTS
None
.EXAMPLE
Set's "Custom Step 1" at 30 percent complete
Show-TSActionProgress -Message "Running Custom Step 1" -Step 100 -MaxStep 300
.EXAMPLE
Set's "Custom Step 1" at 50 percent complete
Show-TSActionProgress -Message "Running Custom Step 1" -Step 150 -MaxStep 300
.EXAMPLE
Set's "Custom Step 1" at 100 percent complete
Show-TSActionProgress -Message "Running Custom Step 1" -Step 300 -MaxStep 300
#>
param(
[Parameter(Mandatory=$true)]
[string] $Message,
[Parameter(Mandatory=$true)]
[long] $Step,
[Parameter(Mandatory=$true)]
[long] $MaxStep
)
Confirm-TSProgressUISetup
Confirm-TSEnvironmentSetup
$Script:TaskSequenceProgressUi.ShowActionProgress(`
$Script:TaskSequenceEnvironment.Value("_SMSTSOrgName"),`
$Script:TaskSequenceEnvironment.Value("_SMSTSPackageName"),`
$Script:TaskSequenceEnvironment.Value("_SMSTSCustomProgressDialogMessage"),`
$Script:TaskSequenceEnvironment.Value("_SMSTSCurrentActionName"),`
[Convert]::ToUInt32($Script:TaskSequenceEnvironment.Value("_SMSTSNextInstructionPointer")),`
[Convert]::ToUInt32($Script:TaskSequenceEnvironment.Value("_SMSTSInstructionTableSize")),`
$Message,`
$Step,`
$MaxStep)
}
function Close-TSProgressDialog()
{
<#
.SYNOPSIS
Hides the Task Sequence Progress Dialog
.DESCRIPTION
Hides the Task Sequence Progress Dialog
.INPUTS
None
.OUTPUTS
None
.EXAMPLE
Close-TSProgressDialog
#>
Confirm-TSProgressUISetup
$Script:TaskSequenceProgressUi.CloseProgressDialog()
}
function Show-TSProgress()
{
<#
.SYNOPSIS
Shows task sequence progress of a specific step
.DESCRIPTION
Manipulates the Task Sequence progress UI; top progress bar only.
This progress bar can be updated to allow for a real-time progress of
a specific task sequence step.
The Step and Max Step parameters are calculated when passed. This allows
you to have a "max steps" of 400, and update the step parameter. 100%
would be achieved when step is 400 and max step is 400. The percentages
are calculated behind the scenes by the Com Object.
.PARAMETER CurrentAction
Step Title. Modifies the "Running action: " Message
.PARAMETER Step
Integer indicating current step
.PARAMETER MaxStep
Integer indicating 100%. A number other than 100 can be used.
.INPUTS
- CurrentAction: String
- Step: Long
- MaxStep: Long
.OUTPUTS
None
.EXAMPLE
Set's "Custom Step 1" at 30 percent complete
Show-TSProgress -CurrentAction "Running Custom Step 1" -Step 100 -MaxStep 300
.EXAMPLE
Set's "Custom Step 1" at 50 percent complete
Show-TSProgress -CurrentAction "Running Custom Step 1" -Step 150 -MaxStep 300
.EXAMPLE
Set's "Custom Step 1" at 100 percent complete
Show-TSProgress -CurrentAction "Running Custom Step 1" -Step 300 -MaxStep 300
#>
param(
[Parameter(Mandatory=$true)]
[string] $CurrentAction,
[Parameter(Mandatory=$true)]
[long] $Step,
[Parameter(Mandatory=$true)]
[long] $MaxStep
)
Confirm-TSProgressUISetup
Confirm-TSEnvironmentSetup
$Script:TaskSequenceProgressUi.ShowTSProgress(`
$Script:TaskSequenceEnvironment.Value("_SMSTSOrgName"), `
$Script:TaskSequenceEnvironment.Value("_SMSTSPackageName"), `
$Script:TaskSequenceEnvironment.Value("_SMSTSCustomProgressDialogMessage"), `
$CurrentAction, `
$Step, `
$MaxStep)
}
function Show-TSErrorDialog()
{
<#
.SYNOPSIS
Shows the Task Sequence Error Dialog
.DESCRIPTION
Shows a task sequence error dialog allowing for custom failure pages.
.PARAMETER OrganizationName
Name of your Organization
.PARAMETER CustomTitle
Custom Error Title
.PARAMETER ErrorMessage
Message details of the error
.PARAMETER ErrorCode
Error Code the Task sequence will exit with
.PARAMETER TimeoutInSeconds
Timout for the Reboot Prompt
.PARAMETER ForceReboot
Indicates whether a reboot will be forced or not
.INPUTS
- OrganizationName: String
- CustomTitle: String
- ErrorMessage: String
- ErrorCode: Long
- TimeoutInSeconds: Long
- ForceReboot: System.Boolean
.OUTPUTS
None
.EXAMPLE
Sets an Error but does not force a reboot
Show-TSErrorDialog -OrganizationName "My Organization" -CustomTitle "An Error occured during the things" -ErrorMessage "That thing you tried...it didnt work" -ErrorCode 123456 -TimeoutInSeconds 90 -ForceReboot $false
.EXAMPLE
Sets an Error and forces a reboot
Show-TSErrorDialog -OrganizationName "My Organization" -CustomTitle "An Error occured during the things" -ErrorMessage "He's dead Jim!" -ErrorCode 123456 -TimeoutInSeconds 90 -ForceReboot $true
#>
param(
[Parameter(Mandatory=$true)]
[string] $OrganizationName,
[Parameter(Mandatory=$true)]
[string] $CustomTitle,
[Parameter(Mandatory=$true)]
[string] $ErrorMessage,
[Parameter(Mandatory=$true)]
[long] $ErrorCode,
[Parameter(Mandatory=$true)]
[long] $TimeoutInSeconds,
[Parameter(Mandatory=$true)]
[bool] $ForceReboot
)
Confirm-TSProgressUISetup
Confirm-TSEnvironmentSetup
if ($ForceReboot)
{
$Script:TaskSequenceProgressUi.ShowErrorDialog($OrganizationName, $Script:TaskSequenceEnvironment.Value("_SMSTSPackageName"), $CustomTitle, $ErrorMessage, $ErrorCode, $TimeoutInSeconds, 1)
}
else
{
$Script:TaskSequenceProgressUi.ShowErrorDialog($OrganizationName, $Script:TaskSequenceEnvironment.Value("_SMSTSPackageName"), $CustomTitle, $ErrorMessage, $ErrorCode, $TimeoutInSeconds, 0)
}
}
function Show-TSMessage()
{
<#
.SYNOPSIS
Shows a Windows Forms Message Box
.DESCRIPTION
Shows a Windows Forms Message Box, but does not return the response.
This will halt any current operations while the prompt is shown.
.PARAMETER Message
Message to be displayed
.PARAMETER Title
Title of the message box
.PARAMETER Type
Button Style for the MessageBox
0 = OK
1 = OK, Cancel
2 = Abort, Retry, Ignore
3 = Yes, No, Cancel
4 = Yes, No
5 = Retry, Cancel
6 = Cancel, Try Again, Continue
.INPUTS
- Message: String
- Title: String
- Type: Long
.OUTPUTS
None
.EXAMPLE
Sets an Error but does not force a reboot
Show-TSErrorDialog -OrganizationName "My Organization" -CustomTitle "An Error occured during the things" -ErrorMessage "That thing you tried...it didnt work" -ErrorCode 123456 -TimeoutInSeconds 90 -ForceReboot $false
.EXAMPLE
Sets an Error and forces a reboot
Show-TSErrorDialog -OrganizationName "My Organization" -CustomTitle "An Error occured during the things" -ErrorMessage "He's dead Jim!" -ErrorCode 123456 -TimeoutInSeconds 90 -ForceReboot $true
#>
param(
[Parameter(Mandatory=$true)]
[string] $Message,
[Parameter(Mandatory=$true)]
[string] $Title,
[Parameter(Mandatory=$true)]
[ValidateRange(0,6)]
[long] $Type
)
Confirm-TSProgressUISetup
$Script:TaskSequenceProgressUi.ShowMessage($Message, $Title, $Type)
}
function Show-TSRebootDialog()
{
<#
.SYNOPSIS
Shows the Reboot Dialog
.DESCRIPTION
Shows the Task Sequence "System Restart" Dialog. This allows you
to trigger custom Task Sequence Reboot Messages.
.PARAMETER OrganizationName
Name of your Organization
.PARAMETER CustomTitle
Custom Title for the Reboot Dialog
.PARAMETER Message
Detailed Message regarding the reboot
.PARAMETER TimeoutInSeconds
Timout before the system reboots
.INPUTS
- OrganizationName: String
- CustomTitle: String
- Message: String
- TimeoutInSeconds: Long
.OUTPUTS
None
.EXAMPLE
Show's a Reboot Dialog
Show-TSRebootDialog -OrganizationName "My Organization" -CustomTitle "I need a reboot!" -Message "I need to reboot to complete something..." -TimeoutInSeconds 90
#>
param(
[Parameter(Mandatory=$true)]
[string] $OrganizationName,
[Parameter(Mandatory=$true)]
[string] $CustomTitle,
[Parameter(Mandatory=$true)]
[string] $Message,
[Parameter(Mandatory=$true)]
[long] $TimeoutInSeconds
)
Confirm-TSProgressUISetup
Confirm-TSEnvironmentSetup
$Script:TaskSequenceProgressUi.ShowRebootDialog($OrganizationName, $Script:TaskSequenceEnvironment.Value("_SMSTSPackageName"), $CustomTitle, $Message, $TimeoutInSeconds)
}
function Show-TSSwapMediaDialog()
{
<#
.SYNOPSIS
Shows Task Sequence Swap Media Dialog.
.DESCRIPTION
Shows Task Sequence Swap Media Dialog.
.PARAMETER TaskSequenceName
Name of the Task Sequence
.PARAMETER MediaNumber
Media Number to insert
.INPUTS
- TaskSequenceName: String
- CustomTitle: Long
.OUTPUTS
None
.EXAMPLE
Prompts to insert media #2 for the Task Sequence "My Task Sequence"
Show-TSSwapMediaDialog -TaskSequenceName "My Task Sequence" -MediaNumber 2
#>
param(
[Parameter(Mandatory=$true)]
[string] $TaskSequenceName,
[Parameter(Mandatory=$true)]
[long] $MediaNumber
)
Confirm-TSProgressUISetup
$Script:TaskSequenceProgressUi.ShowSwapMediaDialog($TaskSequenceName, $MediaNumber)
}
#Encode a plain text string to a Base64 string
Function ConvertTo-Base64
{
[CmdletBinding(SupportsShouldProcess=$False)]
Param
(
[Parameter(Mandatory=$True, ValueFromPipeline=$True)]
[ValidateNotNullOrEmpty()]
[String]$String
)
$EncodedString = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($String))
Write-Verbose -Message "$($NewLine)`"$($String)`" has been converted to the following Base64 encoded string `"$($EncodedString)`"$($NewLine)"
Return $EncodedString
}
#Decode a Base64 string to a plain text string
Function ConvertFrom-Base64
{
[CmdletBinding(SupportsShouldProcess=$False)]
Param
(
[Parameter(Mandatory=$True, ValueFromPipeline=$True)]
[ValidateNotNullOrEmpty()]
[ValidatePattern('^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$')]
[String]$String
)
$DecodedString = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($String))
Write-Verbose -Message "$($NewLine)`"$($String)`" has been converted from the following Base64 encoded string `"$($DecodedString)`"$($NewLine)"
Return $DecodedString
}
+325
View File
@@ -0,0 +1,325 @@
#Requires -Version 3
<#
.SYNOPSIS
Removes an app package (.appx) from a Windows image using a regular expression that can be modified from the command line without changing the script code.
.DESCRIPTION
Slightly more detailed description of what your function does
.PARAMETER ImagePath
The directory path to the mounted windows image or the drive letter of a windows image that has been expanded onto a disk while in WindowsPE.
.PARAMETER PackagesToRemove
A valid regular expression that matches the DisplayName(s) of the universal windows applications you wish to deprovision.
.PARAMETER LogDir
A valid folder path. If the folder does not exist, it will be created. This parameter can also be specified by the alias "LogPath".
.PARAMETER ContinueOnError
Ignore failures.
.EXAMPLE
powershell.exe -ExecutionPolicy Bypass -NoProfile -NoLogo -File "%FolderPathContainingScript%\%ScriptName%.ps1" -ImagePath "%OSDisk%\\" -PackagesToRemove '.*Xbox.*|.*Alarms.*|.*Bing.*|.*Skype.*|.*Communi.*'
.NOTES
Any useful tidbits
.LINK
https://docs.microsoft.com/en-us/powershell/module/dism/remove-appxprovisionedpackage?view=win10-ps#:~:text=The%20Remove%2DAppxProvisionedPackage%20cmdlet%20removes,removed%20from%20existing%20user%20accounts.
#>
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[ValidateScript({($_ -imatch '^[a-zA-Z][\:]\\{1,}$') -or ($_ -imatch '^[a-zA-Z][\:]\\.*?[^\\]$')})]
[System.IO.DirectoryInfo]$ImagePath,
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[Regex]$PackagesToRemove = '.*Xbox.*|.*Alarms.*|.*Bing.*|.*Skype.*|.*Communi.*|.*Zune.*|.*Solit.*|.*Games.*|.*3D.*|.*Camera.*|.*Phone.*|.*Soundrec.*|.*Xboxapp.*|.*Feedback.*|.*Message.*|.*Messaging.*|.*Gethelp.*|.*Mobile.*|.*Mixed.*|.*Microsoft\.MicrosoftOfficeHub.*|.*OneNote.*|.*Microsoft\.People.*|.*Windows.*Defender.*|.*Movies.*|.*Microsoft\.ZuneMusic.*|.*Microsoft\.Windows\.HolographicFirstRun.*|.*Microsoft\.Oneconnect.*|.*Microsoft\.WindowsStore.*|.*Microsoft\.Getstarted.*|.*Microsoft\.MSPaint.*|.*Microsoft\.ZuneVideo.*|.*Microsoft\.PPIProjection.*|.*Microsoft\.WindowsMaps.*',
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[ValidateScript({($_ -imatch '^[a-zA-Z][\:]\\.*?[^\\]$') -or ($_ -imatch "^\\(?:\\[^<>:`"/\\|?*]+)+$")})]
[Alias('LogPath')]
[System.IO.DirectoryInfo]$LogDir,
[Parameter(Mandatory=$False)]
[Switch]$ContinueOnError
)
#Define Default Action Preferences
$Script:DebugPreference = 'SilentlyContinue'
$Script:ErrorActionPreference = 'Stop'
$Script:VerbosePreference = 'SilentlyContinue'
$Script:WarningPreference = 'Continue'
$Script:ConfirmPreference = 'None'
#Load WMI Classes
$Baseboard = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_Baseboard" -Property * | Select-Object -Property *
$Bios = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_Bios" -Property * | Select-Object -Property *
$ComputerSystem = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_ComputerSystem" -Property * | Select-Object -Property *
$OperatingSystem = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_OperatingSystem" -Property * | Select-Object -Property *
#Retrieve property values
$OSArchitecture = $($OperatingSystem.OSArchitecture).Replace("-bit", "").Replace("32", "86").Insert(0,"x").ToUpper()
#Define variable(s)
$DateTimeLogFormat = 'dddd, MMMM dd, yyyy hh:mm:ss tt' ###Monday, January 01, 2019 10:15:34 AM###
[ScriptBlock]$GetCurrentDateTimeLogFormat = {(Get-Date).ToString($DateTimeLogFormat)}
$DateTimeFileFormat = 'yyyyMMdd_hhmmsstt' ###20190403_115354AM###
[ScriptBlock]$GetCurrentDateTimeFileFormat = {(Get-Date).ToString($DateTimeFileFormat)}
[System.IO.FileInfo]$ScriptPath = "$($MyInvocation.MyCommand.Definition)"
[System.IO.DirectoryInfo]$ScriptDirectory = "$($ScriptPath.Directory.FullName)"
[System.IO.DirectoryInfo]$FunctionsDirectory = "$($ScriptDirectory.FullName)\Functions"
[System.IO.DirectoryInfo]$ModulesDirectory = "$($ScriptDirectory.FullName)\Modules"
[System.IO.DirectoryInfo]$ToolsDirectory = "$($ScriptDirectory.FullName)\Tools"
[System.IO.DirectoryInfo]$ToolsDirectory_OSAll = "$($ToolsDirectory.FullName)\All"
[System.IO.DirectoryInfo]$ToolsDirectory_OSArchSpecific = "$($ToolsDirectory.FullName)\$($OSArchitecture)"
$IsWindowsPE = Test-Path -Path 'HKLM:\SYSTEM\ControlSet001\Control\MiniNT' -ErrorAction SilentlyContinue
#Log task sequence variables if debug mode is enabled within the task sequence
Try
{
[System.__ComObject]$TSEnvironment = New-Object -ComObject "Microsoft.SMS.TSEnvironment"
If ($TSEnvironment -ine $Null)
{
$IsRunningTaskSequence = $True
}
}
Catch
{
$IsRunningTaskSequence = $False
}
#Determine the default logging path if the parameter is not specified and is not assigned a default value
If (($PSBoundParameters.ContainsKey('LogDir') -eq $False) -and ($LogDir -ieq $Null))
{
If ($IsRunningTaskSequence -eq $True)
{
[String]$_SMSTSLogPath = "$($TSEnvironment.Value('_SMSTSLogPath'))"
If ([String]::IsNullOrEmpty($_SMSTSLogPath) -eq $False)
{
[System.IO.DirectoryInfo]$TSLogDirectory = "$($_SMSTSLogPath)"
}
Else
{
[System.IO.DirectoryInfo]$TSLogDirectory = "$($Env:Windir)\Temp\SMSTSLog"
}
[System.IO.DirectoryInfo]$LogDir = "$($TSLogDirectory.FullName)\$($ScriptPath.BaseName)"
}
ElseIf ($IsRunningTaskSequence -eq $False)
{
[System.IO.DirectoryInfo]$LogDir = "$($Env:Windir)\Logs\Software\$($ScriptPath.BaseName)"
}
}
#Start transcripting (Logging)
Try
{
[System.IO.FileInfo]$ScriptLogPath = "$($LogDir.FullName)\$($ScriptPath.BaseName)_$($GetCurrentDateTimeFileFormat.Invoke()).log"
If ($ScriptLogPath.Directory.Exists -eq $False) {[Void][System.IO.Directory]::CreateDirectory($ScriptLogPath.Directory.FullName)}
Start-Transcript -Path "$($ScriptLogPath.FullName)" -IncludeInvocationHeader -Force -Verbose
}
Catch
{
If ([String]::IsNullOrEmpty($_.Exception.Message)) {$ExceptionMessage = "$($_.Exception.Errors.Message)"} Else {$ExceptionMessage = "$($_.Exception.Message)"}
$ErrorMessage = "[Error Message: $($ExceptionMessage)][ScriptName: $($_.InvocationInfo.ScriptName)][Line Number: $($_.InvocationInfo.ScriptLineNumber)][Line Position: $($_.InvocationInfo.OffsetInLine)][Code: $($_.InvocationInfo.Line.Trim())]"
Write-Error -Message "$($ErrorMessage)"
}
#Log any useful information
$LogMessage = "IsWindowsPE = $($IsWindowsPE.ToString())"
Write-Verbose -Message "$($LogMessage)" -Verbose
$LogMessage = "Script Path = $($ScriptPath.FullName)"
Write-Verbose -Message "$($LogMessage)" -Verbose
$LogMessage = "Packages To Remove = $($PackagesToRemove.ToString())"
Write-Verbose -Message "$($LogMessage)" -Verbose
$DirectoryVariables = Get-Variable | Where-Object {($_.Value -ine $Null) -and (($_.Value -is [System.IO.DirectoryInfo]) -or ($_.Value -is [System.IO.DirectoryInfo[]]))}
ForEach ($DirectoryVariable In $DirectoryVariables)
{
$LogMessage = "$($DirectoryVariable.Name) = $($DirectoryVariable.Value.FullName -Join ', ')"
Write-Verbose -Message "$($LogMessage)" -Verbose
}
#region Import Dependency Modules
$Modules = Get-Module -Name "$($ModulesDirectory.FullName)\*" -ListAvailable -ErrorAction Stop
$ModuleGroups = $Modules | Group-Object -Property @('Name')
ForEach ($ModuleGroup In $ModuleGroups)
{
$LatestModuleVersion = $ModuleGroup.Group | Sort-Object -Property @('Version') -Descending | Select-Object -First 1
If ($LatestModuleVersion -ine $Null)
{
$LogMessage = "Attempting to import dependency powershell module `"$($LatestModuleVersion.Name) [Version: $($LatestModuleVersion.Version.ToString())]`". Please Wait..."
Write-Verbose -Message "$($LogMessage)" -Verbose
Import-Module -Name "$($LatestModuleVersion.Path)" -Global -DisableNameChecking -Force -ErrorAction Stop
}
}
#endregion
#region Dot Source Dependency Scripts
#Dot source any additional script(s) from the functions directory. This will provide flexibility to add additional functions without adding complexity to the main script and to maintain function consistency.
Try
{
If ($FunctionsDirectory.Exists -eq $True)
{
[String[]]$AdditionalFunctionsFilter = "*.ps1"
$AdditionalFunctionsToImport = Get-ChildItem -Path "$($FunctionsDirectory.FullName)" -Include ($AdditionalFunctionsFilter) -Recurse -Force | Where-Object {($_ -is [System.IO.FileInfo])}
$AdditionalFunctionsToImportCount = $AdditionalFunctionsToImport | Measure-Object | Select-Object -ExpandProperty Count
If ($AdditionalFunctionsToImportCount -gt 0)
{
ForEach ($AdditionalFunctionToImport In $AdditionalFunctionsToImport)
{
Try
{
$LogMessage = "Attempting to dot source dependency script `"$($AdditionalFunctionToImport.Name)`". Please Wait...`r`n`r`nScript Path: `"$($AdditionalFunctionToImport.FullName)`""
Write-Verbose -Message "$($LogMessage)" -Verbose
. "$($AdditionalFunctionToImport.FullName)"
}
Catch
{
$ErrorMessage = "[Error Message: $($_.Exception.Message)]`r`n`r`n[ScriptName: $($_.InvocationInfo.ScriptName)]`r`n[Line Number: $($_.InvocationInfo.ScriptLineNumber)]`r`n[Line Position: $($_.InvocationInfo.OffsetInLine)]`r`n[Code: $($_.InvocationInfo.Line.Trim())]"
Write-Error -Message "$($ErrorMessage)" -Verbose
}
}
}
}
}
Catch
{
$ErrorMessage = "[Error Message: $($_.Exception.Message)]`r`n`r`n[ScriptName: $($_.InvocationInfo.ScriptName)]`r`n[Line Number: $($_.InvocationInfo.ScriptLineNumber)]`r`n[Line Position: $($_.InvocationInfo.OffsetInLine)]`r`n[Code: $($_.InvocationInfo.Line.Trim())]"
Write-Error -Message "$($ErrorMessage)" -Verbose
}
#endregion
#Perform script action(s)
Try
{
#Tasks defined within this block will only execute if a task sequence is running
If (($IsRunningTaskSequence -eq $True))
{
If (($PSBoundParameters.ContainsKey('ImagePath') -eq $False) -and ($ImagePath -eq $Null))
{
[System.IO.DirectoryInfo]$ImagePath = "$($TSEnvironment.Value('OSDisk'))\"
}
}
#Tasks defined here will execute whether only if a task sequence is not running
If ($IsRunningTaskSequence -eq $False)
{
$WarningMessage = "There is no task sequence running.`r`n"
Write-Warning -Message "$($WarningMessage)" -Verbose
}
#Remove Metro Application(s)
If ($ImagePath -ine $Null)
{
$LogMessage = "ImagePath = $($ImagePath.FullName)"
Write-Verbose -Message "$($LogMessage)" -Verbose
$AppXProvisionedPackages = (Get-AppxProvisionedPackage -Path "$($ImagePath.FullName)" | Select-Object * | Sort-Object DisplayName)
$AppXProvisionedPackagesToRemove = $AppXProvisionedPackages | Where-Object {($_.DisplayName -imatch $PackagesToRemove.ToString())}
$AppXProvisionedPackagesToRemoveCount = $AppXProvisionedPackagesToRemove | Measure-Object | Select-Object -ExpandProperty Count
$LogMessage = "Found $($AppXProvisionedPackagesToRemoveCount.ToString()) Appx provisioned package(s) to remove."
Write-Verbose -Message "$($LogMessage)" -Verbose
$Counter = 1
ForEach ($AppXProvisionedPackageToRemove In $AppXProvisionedPackagesToRemove)
{
Try
{
[Int]$ProgressID = 1
[String]$ActivityMessage = "Remove-AppxProvisionedPackage $($AppXProvisionedPackageToRemove.DisplayName) [Version: $($AppXProvisionedPackageToRemove.Version)]"
[String]$StatusMessage = "Attempting to remove $($AppXProvisionedPackageToRemove.DisplayName) $($AppXProvisionedPackageToRemove.Version) ($($Counter.ToString()) of $($AppXProvisionedPackagesToRemoveCount.ToString()))"
[Int]$PercentComplete = (($Counter / $AppXProvisionedPackagesToRemoveCount) * 100)
$LogMessage = "$($StatusMessage). Please Wait..."
Write-Verbose -Message "$($LogMessage)" -Verbose
Write-Progress -ID ($ProgressID) -Activity ($ActivityMessage) -Status ($StatusMessage) -PercentComplete ($PercentComplete)
[System.IO.FileInfo]$AppXProvisionedPackageToRemoveLogPath = "$($LogDir.FullName)\Remove-AppxProvisionedPackage\$($AppXProvisionedPackageToRemove.DisplayName).log"
If ($AppXProvisionedPackageToRemoveLogPath.Directory.Exists -eq $False) {$Null = [System.IO.Directory]::CreateDirectory($AppXProvisionedPackageToRemoveLogPath.Directory.FullName)}
$LogMessage = "Log Path = `"$($AppXProvisionedPackageToRemoveLogPath.FullName)`""
Write-Verbose -Message "$($LogMessage)" -Verbose
$RemoveAppXProvisionedPackage = Remove-AppxProvisionedPackage -PackageName "$($AppXProvisionedPackageToRemove.PackageName)" -Path "$($ImagePath.FullName)" -LogPath "$($AppXProvisionedPackageToRemoveLogPath.FullName)" -LogLevel 'Errors' -Verbose
If ($? -eq $True)
{
$LogMessage = "Removal of the `"$($AppXProvisionedPackageToRemove.DisplayName)`" AppX provisioned package was successful!"
Write-Verbose -Message "$($LogMessage)" -Verbose
}
ElseIf ($? -eq $False)
{
$LogMessage = "Removal of the `"$($AppXProvisionedPackageToRemove.DisplayName)`" AppX provisioned package was unsuccessful!"
Write-Error -Message "$($LogMessage)" -Verbose
}
}
Catch
{
If ([String]::IsNullOrEmpty($_.Exception.Message)) {$ExceptionMessage = "$($_.Exception.Errors.Message)"} Else {$ExceptionMessage = "$($_.Exception.Message)"}
$ErrorMessage = "[Error Message: $($ExceptionMessage)][ScriptName: $($_.InvocationInfo.ScriptName)][Line Number: $($_.InvocationInfo.ScriptLineNumber)][Line Position: $($_.InvocationInfo.OffsetInLine)][Code: $($_.InvocationInfo.Line.Trim())]"
Write-Error -Message "$($ErrorMessage)" -Verbose
}
$Counter++
}
}
Else
{
$ErrorMessage = "[Error Message: A valid image path was either not specified or contains an invalid value.]"
Throw "$($ErrorMessage)"
}
#Stop transcripting (Logging)
Try
{
Stop-Transcript -Verbose
}
Catch
{
If ([String]::IsNullOrEmpty($_.Exception.Message)) {$ExceptionMessage = "$($_.Exception.Errors.Message)"} Else {$ExceptionMessage = "$($_.Exception.Message)"}
$ErrorMessage = "[Error Message: $($ExceptionMessage)][ScriptName: $($_.InvocationInfo.ScriptName)][Line Number: $($_.InvocationInfo.ScriptLineNumber)][Line Position: $($_.InvocationInfo.OffsetInLine)][Code: $($_.InvocationInfo.Line.Trim())]"
Write-Error -Message "$($ErrorMessage)"
}
}
Catch
{
If ([String]::IsNullOrEmpty($_.Exception.Message)) {$ExceptionMessage = "$($_.Exception.Errors.Message -Join "`r`n`r`n")"} Else {$ExceptionMessage = "$($_.Exception.Message)"}
$ErrorMessage = "[Error Message: $($ExceptionMessage)]`r`n`r`n[ScriptName: $($_.InvocationInfo.ScriptName)]`r`n[Line Number: $($_.InvocationInfo.ScriptLineNumber)]`r`n[Line Position: $($_.InvocationInfo.OffsetInLine)]`r`n[Code: $($_.InvocationInfo.Line.Trim())]`r`n"
Write-Error -Message "$($ErrorMessage)"
Stop-Transcript -Verbose
If ($ContinueOnError.IsPresent -eq $False)
{
[System.Environment]::Exit(50)
}
}
@@ -0,0 +1 @@
###
@@ -0,0 +1 @@
###