mirror of
https://github.com/freedbygrace/Dynamic-OSD-Application-List.git
synced 2026-07-26 11:28:20 +00:00
Initial Upload
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0"?>
|
||||
<sequence version="3.00" name="Post OS Installation Task Sequence" description="A task sequence for configuring an Operating System after install">
|
||||
<group expand="true" name="Applications" description="" disable="false" continueOnError="false">
|
||||
<action />
|
||||
<step type="BDD_RunPowerShellAction" name="Determine Application List" description="Uses a powershell script to determine which of the enabled applications within enabled folders should be installed on the device currently being deployed." disable="false" continueOnError="false" successCodeList="0 3010">
|
||||
<defaultVarList>
|
||||
<variable name="ScriptName" property="ScriptName">%CustomContentPath%\Invoke-OSDApplicationList\Invoke-OSDApplicationList.ps1</variable>
|
||||
<variable name="Parameters" property="Parameters"></variable>
|
||||
<variable name="PackageID" property="PackageID" />
|
||||
</defaultVarList>
|
||||
<action>cscript.exe "%SCRIPTROOT%\ZTIPowerShell.wsf</action>
|
||||
</step>
|
||||
<step type="BDD_InstallApplication" name="Install Application List" description="" disable="false" continueOnError="true" runIn="WinPEandFullOS" successCodeList="0 3010">
|
||||
<defaultVarList>
|
||||
<variable name="ApplicationGUID" property="ApplicationGUID"></variable>
|
||||
<variable name="ApplicationSuccessCodes" property="ApplicationSuccessCodes">0 1 3010</variable>
|
||||
</defaultVarList>
|
||||
<action>cscript.exe "%SCRIPTROOT%\ZTIApplications.wsf"</action>
|
||||
</step>
|
||||
</group>
|
||||
</sequence>
|
||||
@@ -0,0 +1,450 @@
|
||||
## Microsoft Function Naming Convention: http://msdn.microsoft.com/en-us/library/ms714428(v=vs.85).aspx
|
||||
|
||||
#region Function Get-InstalledSoftware
|
||||
Function Get-InstalledSoftware
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves a list of software installed on the current device.
|
||||
|
||||
.DESCRIPTION
|
||||
Supports filtering the resulting list of software by using regular expressions.
|
||||
|
||||
.PARAMETER FilterInclusionExpression
|
||||
Includes software based on their display name.
|
||||
|
||||
.PARAMETER FilterInclusionExpression
|
||||
Excludes software based on their display name.
|
||||
|
||||
.PARAMETER ContinueOnError
|
||||
Continues processing even if an error has occured.
|
||||
|
||||
.EXAMPLE
|
||||
Get-InstalledSoftware
|
||||
|
||||
.EXAMPLE
|
||||
Get-InstalledSoftware -Verbose
|
||||
|
||||
.EXAMPLE
|
||||
$GetInstalledSoftwareParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$GetInstalledSoftwareParameters.FilterInclusionExpression = "(.*)"
|
||||
$GetInstalledSoftwareParameters.FilterExclusionExpression = "(^.{0,0}$)"
|
||||
$GetInstalledSoftwareParameters.ContinueOnError = $False
|
||||
$GetInstalledSoftwareParameters.Verbose = $True
|
||||
|
||||
$GetInstalledSoftwareResult = Get-InstalledSoftware @GetInstalledSoftwareParameters
|
||||
|
||||
Write-Output -InputObject ($GetInstalledSoftwareResult)
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('FIE')]
|
||||
[Regex]$FilterInclusionExpression,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('FEE')]
|
||||
[Regex]$FilterExclusionExpression,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[Alias('COE')]
|
||||
[Switch]$ContinueOnError
|
||||
)
|
||||
|
||||
Begin
|
||||
{
|
||||
Try
|
||||
{
|
||||
$DateTimeLogFormat = 'dddd, MMMM dd, yyyy @ hh:mm:ss.FFF tt' ###Monday, January 01, 2019 @ 10:15:34.000 AM###
|
||||
[ScriptBlock]$GetCurrentDateTimeLogFormat = {(Get-Date).ToString($DateTimeLogFormat)}
|
||||
$DateTimeMessageFormat = 'MM/dd/yyyy HH:mm:ss.FFF' ###03/23/2022 11:12:48.347###
|
||||
[ScriptBlock]$GetCurrentDateTimeMessageFormat = {(Get-Date).ToString($DateTimeMessageFormat)}
|
||||
$DateFileFormat = 'yyyyMMdd' ###20190403###
|
||||
[ScriptBlock]$GetCurrentDateFileFormat = {(Get-Date).ToString($DateFileFormat)}
|
||||
$DateTimeFileFormat = 'yyyyMMdd_HHmmss' ###20190403_115354###
|
||||
[ScriptBlock]$GetCurrentDateTimeFileFormat = {(Get-Date).ToString($DateTimeFileFormat)}
|
||||
$TextInfo = (Get-Culture).TextInfo
|
||||
$LoggingDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$LoggingDetails.Add('LogMessage', $Null)
|
||||
$LoggingDetails.Add('WarningMessage', $Null)
|
||||
$LoggingDetails.Add('ErrorMessage', $Null)
|
||||
$CommonParameterList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::CommonParameters)
|
||||
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::OptionalCommonParameters)
|
||||
|
||||
[ScriptBlock]$ErrorHandlingDefinition = {
|
||||
$ErrorMessageList = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$ErrorMessageList.Add('Message', $_.Exception.Message)
|
||||
$ErrorMessageList.Add('Category', $_.Exception.ErrorRecord.FullyQualifiedErrorID)
|
||||
$ErrorMessageList.Add('Script', $_.InvocationInfo.ScriptName)
|
||||
$ErrorMessageList.Add('LineNumber', $_.InvocationInfo.ScriptLineNumber)
|
||||
$ErrorMessageList.Add('LinePosition', $_.InvocationInfo.OffsetInLine)
|
||||
$ErrorMessageList.Add('Code', $_.InvocationInfo.Line.Trim())
|
||||
|
||||
ForEach ($ErrorMessage In $ErrorMessageList.GetEnumerator())
|
||||
{
|
||||
$LoggingDetails.ErrorMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - ERROR: $($ErrorMessage.Key): $($ErrorMessage.Value)"
|
||||
Write-Warning -Message ($LoggingDetails.ErrorMessage)
|
||||
}
|
||||
|
||||
Switch (($ContinueOnError.IsPresent -eq $False) -or ($ContinueOnError -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Determine the date and time we executed the function
|
||||
$FunctionStartTime = (Get-Date)
|
||||
|
||||
[String]$FunctionName = $MyInvocation.MyCommand
|
||||
[System.IO.FileInfo]$InvokingScriptPath = $MyInvocation.PSCommandPath
|
||||
[System.IO.DirectoryInfo]$InvokingScriptDirectory = $InvokingScriptPath.Directory.FullName
|
||||
[System.IO.FileInfo]$FunctionPath = "$($InvokingScriptDirectory.FullName)\Functions\$($FunctionName).ps1"
|
||||
[System.IO.DirectoryInfo]$FunctionDirectory = "$($FunctionPath.Directory.FullName)"
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function `'$($FunctionName)`' is beginning. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
#Define Default Action Preferences
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
[String[]]$AvailableScriptParameters = (Get-Command -Name ($FunctionName)).Parameters.GetEnumerator() | Where-Object {($_.Value.Name -inotin $CommonParameterList)} | ForEach-Object {"-$($_.Value.Name):$($_.Value.ParameterType.Name)"}
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Available Function Parameter(s) = $($AvailableScriptParameters -Join ', ')"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
[String[]]$SuppliedScriptParameters = $PSBoundParameters.GetEnumerator() | ForEach-Object {"-$($_.Key):$($_.Value.GetType().Name)"}
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Supplied Function Parameter(s) = $($SuppliedScriptParameters -Join ', ')"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of $($FunctionName) began on $($FunctionStartTime.ToString($DateTimeLogFormat))"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
#region Set Default Parameter Values
|
||||
Switch ($True)
|
||||
{
|
||||
{([String]::IsNullOrEmpty($FilterInclusionExpression) -eq $True) -or ([String]::IsNullOrWhiteSpace($FilterInclusionExpression) -eq $True)}
|
||||
{
|
||||
[Regex]$FilterInclusionExpression = '(.*)'
|
||||
}
|
||||
|
||||
{([String]::IsNullOrEmpty($FilterExclusionExpression) -eq $True) -or ([String]::IsNullOrWhiteSpace($FilterExclusionExpression) -eq $True)}
|
||||
{
|
||||
[Regex]$FilterExclusionExpression = '(^.{0,0}$)'
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#Create a table for the conversion of dates
|
||||
$DateTimeProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$DateTimeProperties.FormatList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$DateTimeProperties.FormatList.AddRange(([System.Globalization.DateTimeFormatInfo]::CurrentInfo.GetAllDateTimePatterns()))
|
||||
$DateTimeProperties.FormatList.AddRange(([System.Globalization.DateTimeFormatInfo]::InvariantInfo.GetAllDateTimePatterns()))
|
||||
$DateTimeProperties.FormatList.Add('yyyyMM')
|
||||
$DateTimeProperties.FormatList.Add('yyyyMMdd')
|
||||
$DateTimeProperties.Culture = $Null
|
||||
$DateTimeProperties.Styles = New-Object -TypeName 'System.Collections.Generic.List[System.Globalization.DateTimeStyles]'
|
||||
$DateTimeProperties.Styles.Add([System.Globalization.DateTimeStyles]::AssumeLocal)
|
||||
$DateTimeProperties.Styles.Add([System.Globalization.DateTimeStyles]::AllowWhiteSpaces)
|
||||
|
||||
#Create an object that will contain the functions output.
|
||||
$OutputObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
Finally
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Process
|
||||
{
|
||||
Try
|
||||
{
|
||||
$DateTimeLogFormat = 'dddd, MMMM dd, yyyy @ hh:mm:ss.FFF tt' ###Monday, January 01, 2019 @ 10:15:34.000 AM###
|
||||
[ScriptBlock]$GetCurrentDateTimeLogFormat = {(Get-Date).ToString($DateTimeLogFormat)}
|
||||
$DateTimeMessageFormat = 'MM/dd/yyyy HH:mm:ss.FFF' ###03/23/2022 11:12:48.347###
|
||||
[ScriptBlock]$GetCurrentDateTimeMessageFormat = {(Get-Date).ToString($DateTimeMessageFormat)}
|
||||
$DateFileFormat = 'yyyyMMdd' ###20190403###
|
||||
[ScriptBlock]$GetCurrentDateFileFormat = {(Get-Date).ToString($DateFileFormat)}
|
||||
$DateTimeFileFormat = 'yyyyMMdd_HHmmss' ###20190403_115354###
|
||||
[ScriptBlock]$GetCurrentDateTimeFileFormat = {(Get-Date).ToString($DateTimeFileFormat)}
|
||||
$TextInfo = (Get-Culture).TextInfo
|
||||
$LoggingDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$LoggingDetails.Add('LogMessage', $Null)
|
||||
$LoggingDetails.Add('WarningMessage', $Null)
|
||||
$LoggingDetails.Add('ErrorMessage', $Null)
|
||||
$CommonParameterList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::CommonParameters)
|
||||
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::OptionalCommonParameters)
|
||||
$RegularExpressionTable = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$RegularExpressionTable.Base64 = '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$' -As [Regex]
|
||||
$RegularExpressionTable.GUID = '(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}' -As [Regex]
|
||||
$RegexOptionList = New-Object -TypeName 'System.Collections.Generic.List[System.Text.RegularExpressions.RegexOptions[]]'
|
||||
$RegexOptionList.Add([System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
|
||||
$RegexOptionList.Add([System.Text.RegularExpressions.RegexOptions]::Multiline)
|
||||
|
||||
[ScriptBlock]$ErrorHandlingDefinition = {
|
||||
$ErrorMessageList = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$ErrorMessageList.Add('Message', $_.Exception.Message)
|
||||
$ErrorMessageList.Add('Category', $_.Exception.ErrorRecord.FullyQualifiedErrorID)
|
||||
$ErrorMessageList.Add('Script', $_.InvocationInfo.ScriptName)
|
||||
$ErrorMessageList.Add('LineNumber', $_.InvocationInfo.ScriptLineNumber)
|
||||
$ErrorMessageList.Add('LinePosition', $_.InvocationInfo.OffsetInLine)
|
||||
$ErrorMessageList.Add('Code', $_.InvocationInfo.Line.Trim())
|
||||
|
||||
ForEach ($ErrorMessage In $ErrorMessageList.GetEnumerator())
|
||||
{
|
||||
$LoggingDetails.ErrorMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - ERROR: $($ErrorMessage.Key): $($ErrorMessage.Value)"
|
||||
Write-Warning -Message ($LoggingDetails.ErrorMessage)
|
||||
}
|
||||
|
||||
Switch (($ContinueOnError.IsPresent -eq $False) -or ($ContinueOnError -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$OutputObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
||||
|
||||
$OutputObjectValueList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$OutputObjectValueList.Add('DisplayName')
|
||||
$OutputObjectValueList.Add('DisplayVersion')
|
||||
$OutputObjectValueList.Add('UninstallString')
|
||||
$OutputObjectValueList.Add('InstallLocation')
|
||||
$OutputObjectValueList.Add('Publisher')
|
||||
$OutputObjectValueList.Add('InstallDate')
|
||||
|
||||
$RegistryHiveList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
||||
|
||||
$RegistryHiveProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$RegistryHiveProperties.Add('Type', [Microsoft.Win32.RegistryHive]::LocalMachine)
|
||||
$RegistryHiveProperties.Add('KeyList', (New-Object -TypeName 'System.Collections.Generic.List[String]'))
|
||||
$RegistryHiveProperties.KeyList.Add('Software\Microsoft\Windows\CurrentVersion\Uninstall')
|
||||
$RegistryHiveProperties.KeyList.Add('Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
|
||||
$RegistryHiveObject = New-Object -TypeName 'PSObject' -Property ($RegistryHiveProperties)
|
||||
$RegistryHiveList.Add($RegistryHiveObject)
|
||||
|
||||
$RegistryHiveProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$RegistryHiveProperties.Add('Type', [Microsoft.Win32.RegistryHive]::CurrentUser)
|
||||
$RegistryHiveProperties.Add('KeyList', (New-Object -TypeName 'System.Collections.Generic.List[String]'))
|
||||
$RegistryHiveProperties.KeyList.Add('Software\Microsoft\Windows\CurrentVersion\Uninstall')
|
||||
$RegistryHiveObject = New-Object -TypeName 'PSObject' -Property ($RegistryHiveProperties)
|
||||
$RegistryHiveList.Add($RegistryHiveObject)
|
||||
|
||||
For ($RegistryHiveListIndex = 0; $RegistryHiveListIndex -lt $RegistryHiveList.Count; $RegistryHiveListIndex++)
|
||||
{
|
||||
$RegistryHive = $RegistryHiveList[$RegistryHiveListIndex]
|
||||
|
||||
$RegistryHiveObject = [Microsoft.Win32.RegistryKey]::OpenBaseKey($RegistryHive.Type, [Microsoft.Win32.RegistryView]::Default)
|
||||
|
||||
For ($KeyListIndex = 0; $KeyListIndex -lt $RegistryHive.KeyList.Count; $KeyListIndex++)
|
||||
{
|
||||
$RegistryKey = $RegistryHive.KeyList[$KeyListIndex]
|
||||
|
||||
$RegistryKeyObject = $RegistryHiveObject.OpenSubKey($RegistryKey)
|
||||
|
||||
Switch ($Null -ine $RegistryKeyObject)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$SubKeyNameList = $RegistryKeyObject.GetSubKeyNames() | Sort-Object
|
||||
|
||||
For ($SubKeyNameListIndex = 0; $SubKeyNameListIndex -lt $SubKeyNameList.Count; $SubKeyNameListIndex++)
|
||||
{
|
||||
Try
|
||||
{
|
||||
$SubKeyName = $SubKeyNameList[$SubKeyNameListIndex]
|
||||
|
||||
$SubKeyObject = $RegistryKeyObject.OpenSubKey($SubKeyName)
|
||||
|
||||
$SubKeyObjectSegments = $SubKeyObject.Name.Split('\')
|
||||
|
||||
$OutputObjectProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$OutputObjectProperties.Path = $SubKeyObject.Name
|
||||
$OutputObjectProperties.Hive = $SubKeyObjectSegments[0]
|
||||
$OutputObjectProperties.Location = ($SubKeyObjectSegments[1..$($SubKeyObjectSegments.GetUpperBound(0))]) -Join '\'
|
||||
|
||||
|
||||
|
||||
ForEach ($OutputObjectValueName In $OutputObjectValueList)
|
||||
{
|
||||
$OutputObjectProperties.$($OutputObjectValueName) = $Null
|
||||
}
|
||||
|
||||
$ValueNameList = $SubKeyObject.GetValueNames() | Sort-Object
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Now processing entry `"$($OutputObjectProperties.Path)`" [ValueCount: $($ValueNameList.Count)]. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Value Name List: $(($ValueNameList | Sort-Object) -Join '; ')"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
||||
|
||||
Switch ($ValueNameList.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
For ($ValueNameListIndex = 0; $ValueNameListIndex -lt $ValueNameList.Count; $ValueNameListIndex++)
|
||||
{
|
||||
$ValueName = $ValueNameList[$ValueNameListIndex]
|
||||
|
||||
$ValueKind = $SubKeyObject.GetValueKind($ValueName)
|
||||
|
||||
Switch ($ValueKind)
|
||||
{
|
||||
{($_ -ieq 'PlaceHolder')}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$Value = $SubKeyObject.GetValue($ValueName)
|
||||
}
|
||||
}
|
||||
|
||||
$OutputObjectProperties.$ValueName = $Value
|
||||
}
|
||||
|
||||
$OutputObjectProperties.ProductCode = Try {[Regex]::Match($OutputObjectProperties.Location, $RegularExpressionTable.GUID.ToString(), $RegexOptionList.ToArray()).Value.Trim()} Catch {$Null}
|
||||
|
||||
Switch (($OutputObjectProperties.DisplayName -imatch $FilterInclusionExpression.ToString()) -and ($OutputObjectProperties.DisplayName -inotmatch $FilterExclusionExpression.ToString()))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
ForEach ($OutputObjectProperty In ($OutputObjectProperties.Keys | Sort-Object))
|
||||
{
|
||||
$OutputObjectPropertyName = $OutputObjectProperty
|
||||
|
||||
$OutputObjectPropertyValue = $OutputObjectProperties.$($OutputObjectPropertyName)
|
||||
|
||||
Switch ($OutputObjectPropertyName)
|
||||
{
|
||||
{($_ -iin @('DisplayVersion'))}
|
||||
{
|
||||
$OutputObjectPropertyValue = Try {New-Object -TypeName 'System.Version' -ArgumentList ($OutputObjectPropertyValue)} Catch {$OutputObjectPropertyValue}
|
||||
}
|
||||
|
||||
{($_ -iin @('InstallDate'))}
|
||||
{
|
||||
$DateTime = New-Object -TypeName 'DateTime'
|
||||
|
||||
$DateTimeProperties.Input = $OutputObjectPropertyValue
|
||||
$DateTimeProperties.Successful = [DateTime]::TryParseExact($DateTimeProperties.Input, $DateTimeProperties.FormatList, $DateTimeProperties.Culture, $DateTimeProperties.Styles.ToArray(), [Ref]$DateTime)
|
||||
$DateTimeProperties.DateTime = $DateTime
|
||||
|
||||
$DateTimeObject = New-Object -TypeName 'PSObject' -Property ($DateTimeProperties)
|
||||
|
||||
Switch ($DateTimeObject.Successful)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$OutputObjectPropertyValue = $DateTimeObject.DateTime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
Switch ($OutputObjectPropertyValue)
|
||||
{
|
||||
{($_ -imatch '(^\d+$)')}
|
||||
{
|
||||
$OutputObjectPropertyValue = $OutputObjectPropertyValue -As [Int32]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$OutputObjectProperties.Remove($OutputObjectPropertyName)
|
||||
|
||||
$OutputObjectProperties.$($OutputObjectPropertyName) = $OutputObjectPropertyValue
|
||||
}
|
||||
|
||||
$OutputObject = New-Object -TypeName 'PSObject' -Property ($OutputObjectProperties)
|
||||
|
||||
$OutputObjectList.Add($OutputObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Try {$Null = $SubKeyObject.Close()} Catch {}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
|
||||
}
|
||||
Finally
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Try {$Null = $RegistryKeyObject.Close()} Catch {}
|
||||
}
|
||||
|
||||
Try {$Null = $RegistryHiveObject.Close()} Catch {}
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
Finally
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
End
|
||||
{
|
||||
Try
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Found $($OutputObjectList.Count) instances of software matching the specified regular expression(s)."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
#Determine the date and time the function completed execution
|
||||
$FunctionEndTime = (Get-Date)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of $($FunctionName) ended on $($FunctionEndTime.ToString($DateTimeLogFormat))"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
#Log the total script execution time
|
||||
$FunctionExecutionTimespan = New-TimeSpan -Start ($FunctionStartTime) -End ($FunctionEndTime)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function execution took $($FunctionExecutionTimespan.Hours.ToString()) hour(s), $($FunctionExecutionTimespan.Minutes.ToString()) minute(s), $($FunctionExecutionTimespan.Seconds.ToString()) second(s), and $($FunctionExecutionTimespan.Milliseconds.ToString()) millisecond(s)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function `'$($FunctionName)`' is completed."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
Finally
|
||||
{
|
||||
#Write the object to the powershell pipeline
|
||||
$OutputObjectList = $OutputObjectList.ToArray()
|
||||
|
||||
Write-Output -InputObject ($OutputObjectList)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -0,0 +1,288 @@
|
||||
#region Start-ProcessWithOutput
|
||||
Function Start-ProcessWithOutput
|
||||
{
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$True)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]$FilePath,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[AllowEmptyCollection()]
|
||||
[AllowNull()]
|
||||
[String[]]$ArgumentList,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[AllowEmptyCollection()]
|
||||
[AllowNull()]
|
||||
[String[]]$AcceptableExitCodeList,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[Switch]$CreateNoWindow,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
#[Regex]$StandardOutputParsingExpression = "(?:\s+)(?<PropertyName>.+)(?:\s+\:\s+)(?<PropertyValue>.+)",
|
||||
[Regex]$StandardOutputParsingExpression,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[Switch]$LogOutput
|
||||
)
|
||||
|
||||
Try
|
||||
{
|
||||
$DateTimeLogFormat = 'dddd, MMMM dd, yyyy @ hh:mm:ss.FFF tt' ###Monday, January 01, 2019 @ 10:15:34.000 AM###
|
||||
[ScriptBlock]$GetCurrentDateTimeLogFormat = {(Get-Date).ToString($DateTimeLogFormat)}
|
||||
|
||||
$DateTimeMessageFormat = 'MM/dd/yyyy HH:mm:ss.FFF' ###03/23/2022 11:12:48.347###
|
||||
[ScriptBlock]$GetCurrentDateTimeMessageFormat = {(Get-Date).ToString($DateTimeMessageFormat)}
|
||||
|
||||
$DateFileFormat = 'yyyyMMdd' ###20190403###
|
||||
[ScriptBlock]$GetCurrentDateFileFormat = {(Get-Date).ToString($DateFileFormat)}
|
||||
|
||||
$DateTimeFileFormat = 'yyyyMMdd_HHmmss' ###20190403_115354###
|
||||
[ScriptBlock]$GetCurrentDateTimeFileFormat = {(Get-Date).ToString($DateTimeFileFormat)}
|
||||
|
||||
$LoggingDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$LoggingDetails.LogMessage = $Null
|
||||
$LoggingDetails.WarningMessage = $Null
|
||||
$LoggingDetails.ErrorMessage = $Null
|
||||
|
||||
$OutputObjectProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$OutputObjectProperties.ExitCode = $Null
|
||||
$OutputObjectProperties.ExitCodeAsHex = $Null
|
||||
$OutputObjectProperties.ExitCodeAsInteger = $Null
|
||||
$OutputObjectProperties.ExitCodeAsDecimal = $Null
|
||||
$OutputObjectProperties.StandardOutput = $Null
|
||||
$OutputObjectProperties.StandardOutputObject = $Null
|
||||
$OutputObjectProperties.StandardError = $Null
|
||||
$OutputObjectProperties.StandardErrorObject = $Null
|
||||
|
||||
$Process = New-Object -TypeName 'System.Diagnostics.Process'
|
||||
$Process.StartInfo.FileName = $FilePath
|
||||
$Process.StartInfo.UseShellExecute = $False
|
||||
$Process.StartInfo.CreateNoWindow = ($CreateNoWindow.IsPresent)
|
||||
$Process.StartInfo.RedirectStandardOutput = $True
|
||||
$Process.StartInfo.RedirectStandardError = $True
|
||||
|
||||
Switch (($Null -ieq $AcceptableExitCodeList) -or ($AcceptableExitCodeList.Count -eq 0))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$AcceptableExitCodeList += '0'
|
||||
}
|
||||
}
|
||||
|
||||
Switch (($Null -ine $ArgumentList) -and ($ArgumentList.Count -gt 0))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$Process.StartInfo.Arguments = $ArgumentList -Join ' '
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to execute the following command: `"$($Process.StartInfo.FileName)`" $($Process.StartInfo.Arguments)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to execute the following command: `"$($Process.StartInfo.FileName)`""
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
||||
}
|
||||
}
|
||||
|
||||
$Null = $Process.Start()
|
||||
|
||||
$OutputObjectProperties.StandardOutput = $Process.StandardOutput.ReadToEnd()
|
||||
$OutputObjectProperties.StandardError = $Process.StandardError.ReadToEnd()
|
||||
|
||||
$Null = $Process.WaitForExit()
|
||||
|
||||
$OutputObjectProperties.ExitCode = $Process.ExitCode
|
||||
$OutputObjectProperties.ExitCodeAsHex = Try {'0x' + [System.Convert]::ToString($OutputObjectProperties.ExitCode, 16).PadLeft(8, '0').ToUpper()} Catch {$Null}
|
||||
$OutputObjectProperties.ExitCodeAsInteger = Try {$OutputObjectProperties.ExitCodeAsHex -As [Int]} Catch {$Null}
|
||||
$OutputObjectProperties.ExitCodeAsDecimal = Try {[System.Convert]::ToString($OutputObjectProperties.ExitCodeAsHex, 10)} Catch {$Null}
|
||||
|
||||
$ExitCodeMessageList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
|
||||
$Null = $OutputObjectProperties.GetEnumerator() | Where-Object {($_.Key -imatch '(^ExitCode.*$)')} | Sort-Object -Property @('Key') | ForEach-Object {$ExitCodeMessageList.Add("[$($_.Key): $($_.Value)]")}
|
||||
|
||||
$StartProcessExecutionTimespan = New-TimeSpan -Start ($Process.StartTime) -End ($Process.ExitTime)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The command execution took $($StartProcessExecutionTimespan.Hours.ToString()) hour(s), $($StartProcessExecutionTimespan.Minutes.ToString()) minute(s), $($StartProcessExecutionTimespan.Seconds.ToString()) second(s), and $($StartProcessExecutionTimespan.Milliseconds.ToString()) millisecond(s)."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
||||
|
||||
Switch (($OutputObjectProperties.ExitCode.ToString() -iin $AcceptableExitCodeList) -or ($OutputObjectProperties.ExitCodeAsHex.ToString() -iin $AcceptableExitCodeList) -or ($OutputObjectProperties.ExitCodeAsInteger.ToString() -iin $AcceptableExitCodeList) -or ($OutputObjectProperties.ExitCodeAsDecimal.ToString() -iin $AcceptableExitCodeList))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The command execution was successful. $($ExitCodeMessageList -Join ' ')"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage)
|
||||
}
|
||||
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The command execution was unsuccessful. $($ExitCodeMessageList -Join ' ')"
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
|
||||
$ErrorMessage = "$($LoggingDetails.WarningMessage)"
|
||||
$Exception = [System.Exception]::New($ErrorMessage)
|
||||
$ErrorRecord = [System.Management.Automation.ErrorRecord]::New($Exception, [System.Management.Automation.ErrorCategory]::InvalidResult.ToString(), [System.Management.Automation.ErrorCategory]::InvalidResult, $Process)
|
||||
|
||||
$PSCmdlet.ThrowTerminatingError($ErrorRecord)
|
||||
}
|
||||
}
|
||||
|
||||
Switch (($OutputObjectProperties.ExitCode.ToString() -iin $AcceptableExitCodeList) -or ($OutputObjectProperties.ExitCodeAsHex.ToString() -iin $AcceptableExitCodeList) -or ($OutputObjectProperties.ExitCodeAsInteger.ToString() -iin $AcceptableExitCodeList) -or ($OutputObjectProperties.ExitCodeAsDecimal.ToString() -iin $AcceptableExitCodeList))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
[String]$CommandContents = $OutputObjectProperties.StandardOutput
|
||||
|
||||
Switch (([String]::IsNullOrEmpty($StandardOutputParsingExpression) -eq $False) -and ([String]::IsNullOrWhiteSpace($StandardOutputParsingExpression) -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$RegexOptions = New-Object -TypeName 'System.Collections.Generic.List[System.Text.RegularExpressions.RegexOptions]'
|
||||
$RegexOptions.Add([System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
|
||||
$RegexOptions.Add([System.Text.RegularExpressions.RegexOptions]::Multiline)
|
||||
|
||||
[System.Text.RegularExpressions.Regex]$RegularExpression = [System.Text.RegularExpressions.Regex]::New($StandardOutputParsingExpression, $RegexOptions.ToArray())
|
||||
|
||||
[String[]]$RegularExpressionGroups = $RegularExpression.GetGroupNames() | Where-Object {($_ -notin @('0'))}
|
||||
|
||||
[System.Text.RegularExpressions.MatchCollection]$RegularExpressionMatches = $RegularExpression.Matches($CommandContents)
|
||||
|
||||
$StandardOutputObjectProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
|
||||
For ($RegularExpressionMatchIndex = 0; $RegularExpressionMatchIndex -lt $RegularExpressionMatches.Count; $RegularExpressionMatchIndex++)
|
||||
{
|
||||
[System.Text.RegularExpressions.Match]$RegularExpressionMatch = $RegularExpressionMatches[$RegularExpressionMatchIndex]
|
||||
|
||||
For ($RegularExpressionGroupIndex = 0; $RegularExpressionGroupIndex -lt $RegularExpressionGroups.Count; $RegularExpressionGroupIndex++)
|
||||
{
|
||||
[String]$RegularExpressionGroup = $RegularExpressionGroups[$RegularExpressionGroupIndex]
|
||||
|
||||
Switch ($RegularExpressionGroup)
|
||||
{
|
||||
{($_ -imatch '(^PropertyName$)')}
|
||||
{
|
||||
$PropertyDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$PropertyDetails.Add('Name', $Null)
|
||||
$PropertyDetails.Add('Value', $Null)
|
||||
|
||||
$PropertyDetails.Name = ($RegularExpressionMatch.Groups[$($RegularExpressionGroup)].Value) -ireplace '(\s+)|(\-)|(_)', ''
|
||||
}
|
||||
|
||||
{($_ -imatch '(^PropertyValue$)')}
|
||||
{
|
||||
$PropertyDetails.Value = $RegularExpressionMatch.Groups[$($RegularExpressionGroup)].Value
|
||||
|
||||
Switch ($True)
|
||||
{
|
||||
{($PropertyDetails.Value -imatch '\+(\-){1,}\+')}
|
||||
{
|
||||
$PropertyDetails.Value = $Null
|
||||
}
|
||||
|
||||
{($PropertyDetails.Value -imatch '(.+\,\s+.+){1,}')}
|
||||
{
|
||||
#$PropertyDetails.Value = $PropertyDetails.Value.Split(',').Trim()
|
||||
}
|
||||
|
||||
{($PropertyDetails.Value -imatch '.+\(.+\).+')}
|
||||
{
|
||||
#$PropertyDetails.Value = ($PropertyDetails.Value.Split('()', [System.StringSplitOptions]::RemoveEmptyEntries) -ireplace 'bytes', '')[1]
|
||||
}
|
||||
}
|
||||
|
||||
Switch ($Null -ine $PropertyDetails.Value)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$PropertyDetails.Value = $PropertyDetails.Value.Trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Switch ($StandardOutputObjectProperties.Contains($PropertyDetails.Name))
|
||||
{
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
$Null = $StandardOutputObjectProperties.Add($PropertyDetails.Name, $PropertyDetails.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$OutputObjectProperties.StandardOutputObject = New-Object -TypeName 'PSObject' -Property ($StandardOutputObjectProperties)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorMessageList = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$ErrorMessageList.Add('Message', $_.Exception.Message)
|
||||
$ErrorMessageList.Add('Category', $_.Exception.ErrorRecord.FullyQualifiedErrorID)
|
||||
$ErrorMessageList.Add('Script', $_.InvocationInfo.ScriptName)
|
||||
$ErrorMessageList.Add('LineNumber', $_.InvocationInfo.ScriptLineNumber)
|
||||
$ErrorMessageList.Add('LinePosition', $_.InvocationInfo.OffsetInLine)
|
||||
$ErrorMessageList.Add('Code', $_.InvocationInfo.Line.Trim())
|
||||
|
||||
ForEach ($ErrorMessage In $ErrorMessageList.GetEnumerator())
|
||||
{
|
||||
$LoggingDetails.ErrorMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - ERROR: $($ErrorMessage.Key): $($ErrorMessage.Value)"
|
||||
Write-Warning -Message ($LoggingDetails.ErrorMessage) -Verbose
|
||||
}
|
||||
|
||||
Throw "$($_.Exception.Message)"
|
||||
}
|
||||
Finally
|
||||
{
|
||||
$OutputObject = New-Object -TypeName 'PSObject' -Property ($OutputObjectProperties)
|
||||
|
||||
Switch (($LogOutput.IsPresent -eq $True) -or ($LogOutput -eq $True))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
ForEach ($Property In $OutputObject.PSObject.Properties)
|
||||
{
|
||||
Switch ($Property.Name)
|
||||
{
|
||||
{($_ -iin @('StandardOutput', 'StandardError'))}
|
||||
{
|
||||
Switch (([String]::IsNullOrEmpty($Property.Value) -eq $False) -and ([String]::IsNullOrWhiteSpace($Property.Value) -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($Property.Name): $($Property.Value)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($Property.Name): N/A"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output -InputObject ($OutputObject)
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
<#
|
||||
$ProcessOutput = Start-ProcessWithOutput -FilePath 'dsregcmd.exe' -ArgumentList '/status' -CreateNoWindow -Verbose
|
||||
|
||||
$ProcessOutput.StandardOutputObject | ConvertTo-JSON -Depth 10 -OutVariable 'AzureADDetails'
|
||||
|
||||
$ProcessOutput
|
||||
#>
|
||||
@@ -0,0 +1 @@
|
||||
###
|
||||
@@ -0,0 +1,944 @@
|
||||
#Requires -Version 3
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Dynamically creates 'MandatoryApplicationXXX' task sequence variables with the GUIDs of MDT application objects to install on a device during operating system deployment.
|
||||
|
||||
.DESCRIPTION
|
||||
Individual applications or entire application folders can be disabled to exclude the application(s) from being considered by the script during deployment.
|
||||
|
||||
Application(s) that have already been installed by the task sequence whose GUID is stored within a 'InstalledApplicationsXXX' variable will be skipped if this script is executed multiple times during a task sequence.
|
||||
|
||||
.PARAMETER ApplicationFolderDefinitionPath
|
||||
A valid path to the ApplicationGroups.xml file stored within the 'Control' folder within a MDT deployment share.
|
||||
|
||||
.PARAMETER ApplicationDefinitionPath
|
||||
A valid path to the Applications.xml file stored within the 'Control' folder within a MDT deployment share.
|
||||
|
||||
.PARAMETER TaskSequenceVariables
|
||||
One or more task sequence variable(s) to retrieve during task sequence execution.
|
||||
If this parameter is not specified, all task sequence variable(s) will be stored into the variable 'TSVariableTable'.
|
||||
Any task sequence variables that are new or have been updated will be saved back to the task sequence engine for futher usage.
|
||||
|
||||
$TSVariable.MyCustomVariableName = "MyCustomVariableValue"
|
||||
$TSVariable.Make = "MyDeviceModel"
|
||||
|
||||
.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.
|
||||
|
||||
.PARAMETER DebugMode
|
||||
Allows for testing to see which applications would be deployed without running a task sequence.
|
||||
|
||||
.EXAMPLE
|
||||
Use this command to execute a VBSCript that will launch this powershell script automatically with the specified parameters. This is useful to avoid powershell execution complexities.
|
||||
|
||||
cscript.exe /nologo "%FolderPathContainingScript%\%ScriptName%.vbs" /SwitchParameter /ScriptParameter:"%ScriptParameterValue%" /ScriptParameterArray:"%ScriptParameterValue1%,%ScriptParameterValue2%"
|
||||
|
||||
wscript.exe /nologo "%FolderPathContainingScript%\%ScriptName%.vbs" /SwitchParameter /ScriptParameter:"%ScriptParameterValue%" /ScriptParameterArray:"%ScriptParameterValue1%,%ScriptParameterValue2%"
|
||||
|
||||
.EXAMPLE
|
||||
powershell.exe -ExecutionPolicy Bypass -NoProfile -NoLogo -File "%FolderPathContainingScript%\%ScriptName%.ps1" -SwitchParameter -ScriptParameter "%ScriptParameterValue%"
|
||||
|
||||
.EXAMPLE
|
||||
powershell.exe -ExecutionPolicy Bypass -NonInteractive -NoProfile -NoLogo -WindowStyle Hidden -Command "& '%FolderPathContainingScript%\%ScriptName%.ps1' -ScriptParameter1 '%ScriptParameter1Value%' -ScriptParameter2 %ScriptParameter2Value% -SwitchParameter"
|
||||
|
||||
.NOTES
|
||||
Came up with this concept to keep task sequence modification to an absolute minimum.
|
||||
|
||||
.LINK
|
||||
Place any useful link here where your function or cmdlet can be referenced
|
||||
#>
|
||||
|
||||
[CmdletBinding(SupportsShouldProcess=$True)]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('AFDP')]
|
||||
[System.IO.FileInfo]$ApplicationFolderDefinitionPath,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('ADP')]
|
||||
[System.IO.FileInfo]$ApplicationDefinitionPath,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('TSVars', 'TSVs')]
|
||||
[String[]]$TaskSequenceVariables,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('LogDir', 'LogPath')]
|
||||
[System.IO.DirectoryInfo]$LogDirectory,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[Switch]$ContinueOnError,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[Switch]$DebugMode
|
||||
)
|
||||
|
||||
Function Get-AdministrativePrivilege
|
||||
{
|
||||
$Identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$Principal = New-Object System.Security.Principal.WindowsPrincipal($Identity)
|
||||
Write-Output -InputObject ($Principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))
|
||||
}
|
||||
|
||||
If ((Get-AdministrativePrivilege) -eq $False)
|
||||
{
|
||||
[System.IO.FileInfo]$ScriptPath = "$($MyInvocation.MyCommand.Path)"
|
||||
|
||||
$ArgumentList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$ArgumentList.Add('-ExecutionPolicy Bypass')
|
||||
$ArgumentList.Add('-NoProfile')
|
||||
$ArgumentList.Add('-NoExit')
|
||||
$ArgumentList.Add('-NoLogo')
|
||||
$ArgumentList.Add("-File `"$($ScriptPath.FullName)`"")
|
||||
|
||||
$Null = Start-Process -FilePath "$([System.Environment]::SystemDirectory)\WindowsPowershell\v1.0\powershell.exe" -WorkingDirectory "$([System.Environment]::SystemDirectory)" -ArgumentList ($ArgumentList.ToArray()) -WindowStyle Normal -Verb RunAs -PassThru
|
||||
}
|
||||
Else
|
||||
{
|
||||
#Determine the date and time we executed the function
|
||||
$ScriptStartTime = (Get-Date)
|
||||
|
||||
#Define Default Action Preferences
|
||||
$Script:DebugPreference = 'SilentlyContinue'
|
||||
$Script:ErrorActionPreference = 'Stop'
|
||||
$Script:VerbosePreference = 'SilentlyContinue'
|
||||
$Script:WarningPreference = 'Continue'
|
||||
$Script:ConfirmPreference = 'None'
|
||||
$Script:WhatIfPreference = $False
|
||||
|
||||
#Load WMI Classes
|
||||
$Baseboard = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_Baseboard" -Property *
|
||||
$Bios = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_Bios" -Property *
|
||||
$ComputerSystem = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_ComputerSystem" -Property *
|
||||
$OperatingSystem = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_OperatingSystem" -Property *
|
||||
$MSSystemInformation = Get-WmiObject -Namespace "root\WMI" -Class "MS_SystemInformation" -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.FFF tt' ###Monday, January 01, 2019 @ 10:15:34.000 AM###
|
||||
[ScriptBlock]$GetCurrentDateTimeLogFormat = {(Get-Date).ToString($DateTimeLogFormat)}
|
||||
$DateTimeMessageFormat = 'MM/dd/yyyy HH:mm:ss.FFF' ###03/23/2022 11:12:48.347###
|
||||
[ScriptBlock]$GetCurrentDateTimeMessageFormat = {(Get-Date).ToString($DateTimeMessageFormat)}
|
||||
$DateFileFormat = 'yyyyMMdd' ###20190403###
|
||||
[ScriptBlock]$GetCurrentDateFileFormat = {(Get-Date).ToString($DateFileFormat)}
|
||||
$DateTimeFileFormat = 'yyyyMMdd_HHmmss' ###20190403_115354###
|
||||
[ScriptBlock]$GetCurrentDateTimeFileFormat = {(Get-Date).ToString($DateTimeFileFormat)}
|
||||
[System.IO.FileInfo]$ScriptPath = "$($MyInvocation.MyCommand.Definition)"
|
||||
[System.IO.DirectoryInfo]$ScriptDirectory = "$($ScriptPath.Directory.FullName)"
|
||||
[System.IO.DirectoryInfo]$ContentDirectory = "$($ScriptDirectory.FullName)\Content"
|
||||
[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)"
|
||||
[System.IO.DirectoryInfo]$System32Directory = [System.Environment]::SystemDirectory
|
||||
[System.IO.DirectoryInfo]$ProgramFilesDirectory = "$($Env:SystemDrive)\Program Files"
|
||||
[System.IO.DirectoryInfo]$ProgramFilesx86Directory = "$($Env:SystemDrive)\Program Files (x86)"
|
||||
[System.IO.FileInfo]$PowershellPath = "$($System32Directory.FullName)\WindowsPowershell\v1.0\powershell.exe"
|
||||
[System.IO.DirectoryInfo]$System32Directory = "$([System.Environment]::SystemDirectory)"
|
||||
$IsWindowsPE = Test-Path -Path 'HKLM:\SYSTEM\ControlSet001\Control\MiniNT' -ErrorAction SilentlyContinue
|
||||
[System.Text.RegularExpressions.RegexOptions[]]$RegexOptions = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase, [System.Text.RegularExpressions.RegexOptions]::Multiline
|
||||
[ScriptBlock]$GetRandomGUID = {[System.GUID]::NewGUID().GUID.ToString().ToUpper()}
|
||||
[String]$ParameterSetName = "$($PSCmdlet.ParameterSetName)"
|
||||
$TextInfo = (Get-Culture).TextInfo
|
||||
$Script:LASTEXITCODE = 0
|
||||
$TerminationCodes = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$TerminationCodes.Add('Success', @(0))
|
||||
$TerminationCodes.Add('Warning', @(5000..5999))
|
||||
$TerminationCodes.Add('Error', @(6000..6999))
|
||||
$Script:WarningCodeIndex = 0
|
||||
[ScriptBlock]$GetAvailableWarningCode = {$TerminationCodes.Warning[$Script:WarningCodeIndex]; $Script:WarningCodeIndex++}
|
||||
$Script:ErrorCodeIndex = 0
|
||||
[ScriptBlock]$GetAvailableErrorCode = {$TerminationCodes.Error[$Script:ErrorCodeIndex]; $Script:ErrorCodeIndex++}
|
||||
$LoggingDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$LoggingDetails.Add('LogMessage', $Null)
|
||||
$LoggingDetails.Add('WarningMessage', $Null)
|
||||
$LoggingDetails.Add('ErrorMessage', $Null)
|
||||
$RegularExpressionTable = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$RegularExpressionTable.Base64 = '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$' -As [Regex]
|
||||
$CommonParameterList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::CommonParameters)
|
||||
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::OptionalCommonParameters)
|
||||
|
||||
#Define the error handling definition
|
||||
[ScriptBlock]$ErrorHandlingDefinition = {
|
||||
If (($Null -ieq $Script:LASTEXITCODE) -or ($Script:LASTEXITCODE -eq 0))
|
||||
{
|
||||
[Int]$Script:LASTEXITCODE = $GetAvailableErrorCode.InvokeReturnAsIs()
|
||||
}
|
||||
|
||||
$ErrorMessageList = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$ErrorMessageList.Add('Message', $_.Exception.Message)
|
||||
$ErrorMessageList.Add('Category', $_.Exception.ErrorRecord.FullyQualifiedErrorID)
|
||||
$ErrorMessageList.Add('ExitCode', $Script:LASTEXITCODE)
|
||||
$ErrorMessageList.Add('Script', $_.InvocationInfo.ScriptName)
|
||||
$ErrorMessageList.Add('LineNumber', $_.InvocationInfo.ScriptLineNumber)
|
||||
$ErrorMessageList.Add('LinePosition', $_.InvocationInfo.OffsetInLine)
|
||||
$ErrorMessageList.Add('Code', $_.InvocationInfo.Line.Trim())
|
||||
|
||||
ForEach ($ErrorMessage In $ErrorMessageList.GetEnumerator())
|
||||
{
|
||||
$LoggingDetails.ErrorMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - ERROR: $($ErrorMessage.Key): $($ErrorMessage.Value)"
|
||||
Write-Warning -Message ($LoggingDetails.ErrorMessage) -Verbose
|
||||
}
|
||||
|
||||
Switch (($ContinueOnError.IsPresent -eq $False) -or ($ContinueOnError -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Log task sequence variables if debug mode is enabled within the task sequence
|
||||
Try
|
||||
{
|
||||
[System.__ComObject]$TSEnvironment = New-Object -ComObject "Microsoft.SMS.TSEnvironment"
|
||||
|
||||
If ($Null -ine $TSEnvironment)
|
||||
{
|
||||
$IsRunningTaskSequence = $True
|
||||
|
||||
[Boolean]$IsConfigurationManagerTaskSequence = [String]::IsNullOrEmpty($TSEnvironment.Value("_SMSTSPackageID")) -eq $False
|
||||
|
||||
Switch ($IsConfigurationManagerTaskSequence)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - A Microsoft Endpoint Configuration Manager (MECM) task sequence was detected."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - A Microsoft Deployment Toolkit (MDT) task sequence was detected."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$IsRunningTaskSequence = $False
|
||||
}
|
||||
|
||||
#Determine default parameter value(s)
|
||||
Switch ($True)
|
||||
{
|
||||
{([String]::IsNullOrEmpty($LogDirectory) -eq $True) -or ([String]::IsNullOrWhiteSpace($LogDirectory) -eq $True)}
|
||||
{
|
||||
Switch ($IsRunningTaskSequence)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Switch ($IsConfigurationManagerTaskSequence)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
[String]$_SMSTSLogPath = "$($TSEnvironment.Value('_SMSTSLogPath'))"
|
||||
}
|
||||
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
[String]$_SMSTSLogPath = "$($TSEnvironment.Value('LogPath'))"
|
||||
}
|
||||
}
|
||||
|
||||
Switch ([String]::IsNullOrEmpty($_SMSTSLogPath))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
[System.IO.DirectoryInfo]$TSLogDirectory = "$($Env:Windir)\Temp\SMSTSLog"
|
||||
}
|
||||
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
Switch ($True)
|
||||
{
|
||||
{(Test-Path -Path ($_SMSTSLogPath) -PathType Container)}
|
||||
{
|
||||
[System.IO.DirectoryInfo]$TSLogDirectory = ($_SMSTSLogPath)
|
||||
}
|
||||
|
||||
{(Test-Path -Path ($_SMSTSLogPath) -PathType Leaf)}
|
||||
{
|
||||
[System.IO.DirectoryInfo]$TSLogDirectory = Split-Path -Path ($_SMSTSLogPath) -Parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[System.IO.DirectoryInfo]$LogDirectory = "$($TSLogDirectory.FullName)\$($ScriptPath.BaseName)"
|
||||
}
|
||||
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
Switch ($IsWindowsPE)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
[System.IO.FileInfo]$MDTBootImageDetectionPath = "$($Env:SystemDrive)\Deploy\Scripts\Litetouch.wsf"
|
||||
|
||||
[Boolean]$MDTBootImageDetected = Test-Path -Path ($MDTBootImageDetectionPath.FullName)
|
||||
|
||||
Switch ($MDTBootImageDetected)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
[System.IO.DirectoryInfo]$LogDirectory = "$($Env:SystemDrive)\MININT\SMSOSD\OSDLOGS\$($ScriptPath.BaseName)"
|
||||
}
|
||||
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
[System.IO.DirectoryInfo]$LogDirectory = "$($Env:Windir)\Temp\SMSTSLog"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
[System.IO.DirectoryInfo]$LogDirectory = "$($Env:Windir)\Logs\Software\$($ScriptPath.BaseName)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Start transcripting (Logging)
|
||||
[System.IO.FileInfo]$ScriptLogPath = "$($LogDirectory.FullName)\$($ScriptPath.BaseName)_$($GetCurrentDateFileFormat.Invoke()).log"
|
||||
If ($ScriptLogPath.Directory.Exists -eq $False) {$Null = [System.IO.Directory]::CreateDirectory($ScriptLogPath.Directory.FullName)}
|
||||
Start-Transcript -Path "$($ScriptLogPath.FullName)" -Force -WhatIf:$False
|
||||
|
||||
#Log any useful information
|
||||
[String]$CmdletName = $MyInvocation.MyCommand.Name
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of script `"$($CmdletName)`" began on $($ScriptStartTime.ToString($DateTimeLogFormat))"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Script Path = $($ScriptPath.FullName)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
[String[]]$AvailableScriptParameters = (Get-Command -Name ($ScriptPath.FullName)).Parameters.GetEnumerator() | Where-Object {($_.Value.Name -inotin $CommonParameterList)} | ForEach-Object {"-$($_.Value.Name):$($_.Value.ParameterType.Name)"}
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Available Script Parameter(s) = $($AvailableScriptParameters -Join ', ')"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
[String[]]$SuppliedScriptParameters = $PSBoundParameters.GetEnumerator() | ForEach-Object {"-$($_.Key):$($_.Value.GetType().Name)"}
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Supplied Script Parameter(s) = $($SuppliedScriptParameters -Join ', ')"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Switch ($True)
|
||||
{
|
||||
{([String]::IsNullOrEmpty($ParameterSetName) -eq $False)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Parameter Set Name = $($ParameterSetName)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Command Line: $((Get-WMIObject -Namespace 'Root\CIMv2' -Class 'Win32_Process' -Filter "ProcessID = $($PID)").CommandLine)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($PSBoundParameters.Count) command line parameter(s) were specified."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$OperatingSystemDetailsTable = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$OperatingSystemDetailsTable.ProductName = $OperatingSystem.Caption -ireplace '(Microsoft\s+)', ''
|
||||
$OperatingSystemDetailsTable.Version = $OperatingSystem.Version
|
||||
$OperatingSystemDetailsTable.Architecture = $OperatingSystem.OSArchitecture
|
||||
|
||||
$OperatingSystemRegistryDetails = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
||||
$OperatingSystemRegistryDetails.Add((New-Object -TypeName 'PSObject' -Property @{Alias = ''; Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'; ValueName = 'UBR'; Value = $Null}))
|
||||
$OperatingSystemRegistryDetails.Add((New-Object -TypeName 'PSObject' -Property @{Alias = 'ReleaseVersion'; Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'; ValueName = 'ReleaseID'; Value = $Null}))
|
||||
$OperatingSystemRegistryDetails.Add((New-Object -TypeName 'PSObject' -Property @{Alias = 'ReleaseID'; Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'; ValueName = 'DisplayVersion'; Value = $Null}))
|
||||
|
||||
ForEach ($OperatingSystemRegistryDetail In $OperatingSystemRegistryDetails)
|
||||
{
|
||||
$OperatingSystemRegistryDetail.Value = Try {(Get-Item -Path $OperatingSystemRegistryDetail.Path).GetValue($OperatingSystemRegistryDetail.ValueName)} Catch {}
|
||||
|
||||
:NextOSDetail Switch (([String]::IsNullOrEmpty($OperatingSystemRegistryDetail.Value) -eq $False) -and ([String]::IsNullOrWhiteSpace($OperatingSystemRegistryDetail.Value) -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Switch ($OperatingSystemRegistryDetail.ValueName)
|
||||
{
|
||||
{($_ -ieq 'UBR')}
|
||||
{
|
||||
$OperatingSystemDetailsTable.Version = $OperatingSystemDetailsTable.Version + '.' + $OperatingSystemRegistryDetail.Value
|
||||
|
||||
Break NextOSDetail
|
||||
}
|
||||
}
|
||||
|
||||
Switch (([String]::IsNullOrEmpty($OperatingSystemRegistryDetail.Alias) -eq $False) -and ([String]::IsNullOrWhiteSpace($OperatingSystemRegistryDetail.Alias) -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$OperatingSystemDetailsTable.$($OperatingSystemRegistryDetail.Alias) = $OperatingSystemRegistryDetail.Value
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$OperatingSystemDetailsTable.$($OperatingSystemRegistryDetail.ValueName) = $OperatingSystemRegistryDetail.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$OperatingSystemDetailsTable.$($OperatingSystemRegistryDetail.ValueName) = $OperatingSystemRegistryDetail.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ForEach ($OperatingSystemDetail In $OperatingSystemDetailsTable.GetEnumerator())
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($OperatingSystemDetail.Key): $($OperatingSystemDetail.Value)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Powershell Version: $($PSVersionTable.PSVersion.ToString())"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$ExecutionPolicyList = Get-ExecutionPolicy -List
|
||||
|
||||
For ($ExecutionPolicyListIndex = 0; $ExecutionPolicyListIndex -lt $ExecutionPolicyList.Count; $ExecutionPolicyListIndex++)
|
||||
{
|
||||
$ExecutionPolicy = $ExecutionPolicyList[$ExecutionPolicyListIndex]
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The powershell execution policy is currently set to `"$($ExecutionPolicy.ExecutionPolicy.ToString())`" for the `"$($ExecutionPolicy.Scope.ToString())`" scope."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
|
||||
#Log hardware information
|
||||
$MSSystemInformationMembers = $MSSystemInformation.PSObject.Properties | Where-Object {($_.MemberType -imatch '^NoteProperty$|^Property$') -and ($_.Name -imatch '^Base.*|Bios.*|System.*$') -and ($_.Name -inotmatch '^.*Major.*|.*Minor.*|.*Properties.*$')} | Sort-Object -Property @('Name')
|
||||
|
||||
Switch ($MSSystemInformationMembers.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to display device information properties from the `"$($MSSystemInformation.__CLASS)`" WMI class located within the `"$($MSSystemInformation.__NAMESPACE)`" WMI namespace. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
ForEach ($MSSystemInformationMember In $MSSystemInformationMembers)
|
||||
{
|
||||
[String]$MSSystemInformationMemberName = ($MSSystemInformationMember.Name)
|
||||
[String]$MSSystemInformationMemberValue = $MSSystemInformation.$($MSSystemInformationMemberName)
|
||||
|
||||
Switch ([String]::IsNullOrEmpty($MSSystemInformationMemberValue))
|
||||
{
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($MSSystemInformationMemberName) = $($MSSystemInformationMemberValue)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The `"MSSystemInformation`" WMI class could not be found."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
}
|
||||
}
|
||||
|
||||
#region Log Cleanup
|
||||
[Int]$MaximumLogHistory = 3
|
||||
|
||||
$LogList = Get-ChildItem -Path ($LogDirectory.FullName) -Filter "$($ScriptPath.BaseName)_*" -Recurse -Force | Where-Object {($_ -is [System.IO.FileInfo])}
|
||||
|
||||
$SortedLogList = $LogList | Sort-Object -Property @('LastWriteTime') -Descending | Select-Object -Skip ($MaximumLogHistory)
|
||||
|
||||
Switch ($SortedLogList.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - There are $($SortedLogList.Count) log file(s) requiring cleanup."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
|
||||
For ($SortedLogListIndex = 0; $SortedLogListIndex -lt $SortedLogList.Count; $SortedLogListIndex++)
|
||||
{
|
||||
Try
|
||||
{
|
||||
$Log = $SortedLogList[$SortedLogListIndex]
|
||||
|
||||
$LogAge = New-TimeSpan -Start ($Log.LastWriteTime) -End (Get-Date)
|
||||
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to cleanup log file `"$($Log.FullName)`". Please Wait... [Last Modified: $($Log.LastWriteTime.ToString($DateTimeMessageFormat))] [Age: $($LogAge.Days.ToString()) day(s); $($LogAge.Hours.ToString()) hours(s); $($LogAge.Minutes.ToString()) minute(s); $($LogAge.Seconds.ToString()) second(s)]."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
|
||||
$Null = [System.IO.File]::Delete($Log.FullName)
|
||||
}
|
||||
Catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - There are $($SortedLogList.Count) log file(s) requiring cleanup."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Import Dependency Modules
|
||||
If (($ModulesDirectory.Exists -eq $True) -and ($ModulesDirectory.GetDirectories().Count -gt 0))
|
||||
{
|
||||
$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 ($Null -ine $LatestModuleVersion)
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to import dependency powershell module `"$($LatestModuleVersion.Name)`" [Version: $($LatestModuleVersion.Version.ToString())]. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.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)
|
||||
{
|
||||
$AdditionalFunctionsFilter = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$AdditionalFunctionsFilter.Add('*.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
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to dot source the functions contained within the dependency script `"$($AdditionalFunctionToImport.Name)`". Please Wait... [Script Path: `"$($AdditionalFunctionToImport.FullName)`"]"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
. "$($AdditionalFunctionToImport.FullName)"
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Load any required libraries
|
||||
[System.IO.DirectoryInfo]$LibariesDirectory = "$($FunctionsDirectory.FullName)\Libraries"
|
||||
|
||||
Switch ([System.IO.Directory]::Exists($LibariesDirectory.FullName))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LibraryPatternList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
#$LibraryPatternList.Add('')
|
||||
|
||||
Switch ($LibraryPatternList.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LibraryList = Get-ChildItem -Path ($LibariesDirectory.FullName) -Include ($LibraryPatternList.ToArray()) -Recurse -Force | Where-Object {($_ -is [System.IO.FileInfo])}
|
||||
|
||||
$LibraryListCount = ($LibraryList | Measure-Object).Count
|
||||
|
||||
Switch ($LibraryListCount -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
For ($LibraryListIndex = 0; $LibraryListIndex -lt $LibraryListCount; $LibraryListIndex++)
|
||||
{
|
||||
$Library = $LibraryList[$LibraryListIndex]
|
||||
|
||||
[Byte[]]$LibraryBytes = [System.IO.File]::ReadAllBytes($Library.FullName)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to load assembly `"$($Library.FullName)`". Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$Null = [System.Reflection.Assembly]::Load($LibraryBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#Perform script action(s)
|
||||
Try
|
||||
{
|
||||
$GetInstalledSoftwareParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$GetInstalledSoftwareParameters.FilterInclusionExpression = "(.*)"
|
||||
$GetInstalledSoftwareParameters.FilterExclusionExpression = "(^.{0,0}$)"
|
||||
$GetInstalledSoftwareParameters.ContinueOnError = $True
|
||||
$GetInstalledSoftwareParameters.Verbose = $False
|
||||
|
||||
$InstalledSoftwareList = Get-InstalledSoftware @GetInstalledSoftwareParameters
|
||||
|
||||
#If necessary, create, get, and or set any task sequence variable(s).
|
||||
Switch (($IsRunningTaskSequence -eq $True) -or ($DebugMode.IsPresent -eq $True))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Try
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - A task sequence is currently running."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$TSVariableTable = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
|
||||
$TaskSequenceVariableRetrievalList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
|
||||
Switch ($TaskSequenceVariables.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
ForEach ($TaskSequenceVariable In $TaskSequenceVariables)
|
||||
{
|
||||
$TaskSequenceVariableRetrievalList.Add($TaskSequenceVariable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$TSVariableTable = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to retrieve the task sequence variable list. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Switch ($TaskSequenceVariableRetrievalList.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$TSVariableList = $TSEnvironment.GetVariables() | Where-Object {($_ -iin $TaskSequenceVariableRetrievalList)} | Sort-Object
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$TSVariableList = $TSEnvironment.GetVariables() | Sort-Object
|
||||
}
|
||||
}
|
||||
|
||||
ForEach ($TSVariable In $TSVariableList)
|
||||
{
|
||||
$TSVariableName = $TSVariable
|
||||
$TSVariableValue = $TSEnvironment.Value($TSVariableName)
|
||||
|
||||
Switch ($True)
|
||||
{
|
||||
{($TSVariableName -inotmatch '(^_SMSTSTaskSequence$)|(^TaskSequence$)|(^.*Pass.*word.*$)')}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to retrieve the value of task sequence variable `"$($TSVariableName)`". Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
|
||||
{($TSVariableTable.Contains($TSVariableName) -eq $False)}
|
||||
{
|
||||
$TSVariableTable.Add($TSVariableName, $TSVariableValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$InstalledApplicationDictionary = $TSVariableTable.GetEnumerator() | Where-Object {($_.Key -imatch '(^InstalledApplications\d{3,3}$)')}
|
||||
|
||||
$InstalledApplicationDictionaryCount = ($InstalledApplicationDictionary | Measure-Object).Count
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($InstalledApplicationDictionaryCount) application(s) have already been installed on `"$($Env:ComputerName.ToUpper())`" during task sequence `"$($TSVariableTable.TASKSEQUENCENAME)`"."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - [Error Message: $($_.Exception.Message)] [Code: $($_.InvocationInfo.Line.Trim())] [Line Number: $($_.InvocationInfo.ScriptLineNumber)] [Line Position: $($_.InvocationInfo.OffsetInLine)]"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
Finally
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Switch (($IsRunningTaskSequence -eq $True) -or ($DebugMode.IsPresent -eq $True))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
#Set default parameter values
|
||||
Switch ($True)
|
||||
{
|
||||
{([String]::IsNullOrEmpty($ApplicationFolderDefinitionPath) -eq $True) -or ([String]::IsNullOrWhiteSpace($ApplicationFolderDefinitionPath) -eq $True)}
|
||||
{
|
||||
[System.IO.FileInfo]$ApplicationFolderDefinitionPath = "$($TSVariableTable.DEPLOYROOT)\Control\ApplicationGroups.xml"
|
||||
}
|
||||
|
||||
{([String]::IsNullOrEmpty($ApplicationDefinitionPath) -eq $True) -or ([String]::IsNullOrWhiteSpace($ApplicationDefinitionPath) -eq $True)}
|
||||
{
|
||||
[System.IO.FileInfo]$ApplicationDefinitionPath = "$($TSVariableTable.DEPLOYROOT)\Control\Applications.xml"
|
||||
}
|
||||
}
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application Folder Defintion Path: $($ApplicationFolderDefinitionPath.FullName)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application Definition Path: $($ApplicationDefinitionPath.FullName)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Switch ([System.IO.File]::Exists($ApplicationFolderDefinitionPath.FullName))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Switch ([System.IO.File]::Exists($ApplicationDefinitionPath.FullName))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$ApplicationFolderDefinitionContents = [System.IO.File]::ReadAllText($ApplicationFolderDefinitionPath.FullName)
|
||||
|
||||
$ApplicationFolderDefinition = New-Object -TypeName 'System.Xml.XmlDocument'
|
||||
$ApplicationFolderDefinition.LoadXml($ApplicationFolderDefinitionContents)
|
||||
|
||||
$ApplicationFolderObjectList = $ApplicationFolderDefinition.groups.group | Where-Object {($_.Enable -eq $True)}
|
||||
|
||||
$ApplicationDefinitionContents = [System.IO.File]::ReadAllText($ApplicationDefinitionPath.FullName)
|
||||
|
||||
$ApplicationDefinition = New-Object -TypeName 'System.Xml.XmlDocument'
|
||||
$ApplicationDefinition.LoadXml($ApplicationDefinitionContents)
|
||||
|
||||
$AvailableApplicationList = $ApplicationDefinition.applications.application | Where-Object {($_.Enable -eq $True) -and ($ApplicationFolderObjectList.Member -icontains $_.GUID)} | Sort-Object -Property @{Expression = {Try {($_.Version -As [Int])} Catch {($_.Version)}}}
|
||||
|
||||
Switch ($InstalledApplicationDictionaryCount -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$InstalledApplicationList = $AvailableApplicationList | Where-Object {($InstalledApplicationList.Value -icontains $_.GUID)}
|
||||
|
||||
ForEach ($InstalledApplication In $InstalledApplicationList)
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application `"$($InstalledApplication.Name)`" [GUID: $($InstalledApplication.GUID.ToUpper())] has already been installed on `"$($Env:ComputerName.ToUpper())`" and will be removed from the available application list."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
|
||||
$AvailableApplicationList = $AvailableApplicationList | Where-Object {($InstalledApplicationDictionary.Value -inotcontains $_.GUID)}
|
||||
}
|
||||
}
|
||||
|
||||
$ApplicationObjectList = New-Object -TypeName 'System.Collections.Generic.List[Object]'
|
||||
|
||||
For ($AvailableApplicationListIndex = 0; $AvailableApplicationListIndex -lt $AvailableApplicationList.Count; $AvailableApplicationListIndex++)
|
||||
{
|
||||
$AvailableApplication = $AvailableApplicationList[$AvailableApplicationListIndex]
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Adding available application `"$($AvailableApplication.Name)`" to the available application list. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$ApplicationObjectList.Add($AvailableApplication)
|
||||
}
|
||||
|
||||
[Int]$ApplicationVariableCounter = 1
|
||||
|
||||
For ($ApplicationObjectListIndex = 0; $ApplicationObjectListIndex -lt $ApplicationObjectList.Count; $ApplicationObjectListIndex++)
|
||||
{
|
||||
Try
|
||||
{
|
||||
$ApplicationObject = $ApplicationObjectList[$ApplicationObjectListIndex]
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to determine the applicability of application object `"$($ApplicationObject.Name)`". Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$ApplicationObjectConfiguration = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$ApplicationObjectConfiguration.Applicable = $False
|
||||
|
||||
$ApplicationApplicabilityConditionContent = $ApplicationObject.Language
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application Applicability Condition: $($ApplicationApplicabilityConditionContent)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Switch ($ApplicationApplicabilityConditionContent -imatch '.*\$.*')
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$ApplicationApplicabilityCondition = [ScriptBlock]::Create($ApplicationApplicabilityConditionContent)
|
||||
|
||||
$ApplicationObjectConfiguration.Applicable = $ApplicationApplicabilityCondition.InvokeReturnAsIs()
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application Applicability Condition Result: `$$($ApplicationObjectConfiguration.Applicable)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Switch ($ApplicationObjectConfiguration.Applicable)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application object `"$($ApplicationObject.Name)`" is applicable and WILL be installed."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$ApplicationInstallationDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$ApplicationInstallationDetails.Number = $ApplicationVariableCounter++
|
||||
$ApplicationInstallationDetails.TSVariableName = 'MandatoryApplications' + $ApplicationInstallationDetails.Number.ToString('000')
|
||||
$ApplicationInstallationDetails.TSVariableValue = $ApplicationObject.GUID.ToUpper()
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to add `"$($ApplicationObject.Name)`" to the application installation list. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Task Sequence Variable: $($ApplicationInstallationDetails.TSVariableName)=$($ApplicationInstallationDetails.TSVariableValue)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$TSVariableTable."$($ApplicationInstallationDetails.TSVariableName)" = $ApplicationInstallationDetails.TSVariableValue
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application object `"$($ApplicationObject.Name)`" is NOT applicable and will NOT be installed."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The application applicability could not determined. Skipping..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application: `"$($ApplicationObject.Name)`" [Error Message: $($_.Exception.Message)] [Code: $($_.InvocationInfo.Line.Trim())] [Line Number: $($_.InvocationInfo.ScriptLineNumber)] [Line Position: $($_.InvocationInfo.OffsetInLine)]"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
Finally
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application definition file `"$($ApplicationDefinitionPath.FullName)`" does not exist."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application folder definition file `"$($ApplicationFolderDefinitionPath.FullName)`" does not exist."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#If necessary, create, get, and or set any task sequence variable(s).
|
||||
Switch (($IsRunningTaskSequence -eq $True) -or ($DebugMode.IsPresent -eq $True))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Try
|
||||
{
|
||||
ForEach ($TSVariable In $TSVariableTable.GetEnumerator())
|
||||
{
|
||||
[String]$TSVariableName = "$($TSVariable.Key)"
|
||||
[String]$TSVariableCurrentValue = $TSEnvironment.Value($TSVariableName)
|
||||
[String]$TSVariableNewValue = "$($TSVariable.Value -Join ',')"
|
||||
|
||||
Switch ($TSVariableCurrentValue -ine $TSVariableNewValue)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to set the task sequence variable of `"$($TSVariableName)`". Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$Null = $TSEnvironment.Value($TSVariableName) = "$($TSVariableNewValue)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$Null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($TSEnvironment)
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - [Error Message: $($_.Exception.Message)] [Code: $($_.InvocationInfo.Line.Trim())] [Line Number: $($_.InvocationInfo.ScriptLineNumber)] [Line Position: $($_.InvocationInfo.OffsetInLine)]"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
Finally
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - There is no task sequence running."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
}
|
||||
}
|
||||
|
||||
$Script:LASTEXITCODE = $TerminationCodes.Success[0]
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
Finally
|
||||
{
|
||||
Try
|
||||
{
|
||||
#Determine the date and time the function completed execution
|
||||
$ScriptEndTime = (Get-Date)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Script execution of `"$($CmdletName)`" ended on $($ScriptEndTime.ToString($DateTimeLogFormat))"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
#Log the total script execution time
|
||||
$ScriptExecutionTimespan = New-TimeSpan -Start ($ScriptStartTime) -End ($ScriptEndTime)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Script execution took $($ScriptExecutionTimespan.Hours.ToString()) hour(s), $($ScriptExecutionTimespan.Minutes.ToString()) minute(s), $($ScriptExecutionTimespan.Seconds.ToString()) second(s), and $($ScriptExecutionTimespan.Milliseconds.ToString()) millisecond(s)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Exiting script `"$($ScriptPath.FullName)`" with exit code $($Script:LASTEXITCODE)."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Stop-Transcript
|
||||
}
|
||||
Catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
'Set object values
|
||||
Set oArguments = WScript.Arguments.Named
|
||||
Set oFSO = CreateObject("Scripting.FileSystemObject")
|
||||
Set oShell = CreateObject("WScript.Shell")
|
||||
Set oCMD = oFSO.GetFile(oShell.ExpandEnvironmentStrings("%COMSPEC%"))
|
||||
Set oPowershell = oFSO.GetFile(oShell.ExpandEnvironmentStrings("%WINDIR%") & "\System32\WindowsPowershell\v1.0\powershell.exe")
|
||||
|
||||
'Define ASCII Characters
|
||||
chrSpace = Chr(32)
|
||||
chrSingleQuote = Chr(39)
|
||||
chrDoubleQuote = Chr(34)
|
||||
|
||||
'Define Variable(s)
|
||||
ScriptInterpreter = CreateObject("Scripting.FileSystemObject").GetFileName(WScript.FullName)
|
||||
If (oArguments.Exists("Debug") = True) Then DebugMode = True End If
|
||||
|
||||
'Dynamically convert named VBScript arguments to their eqivalent powershell format
|
||||
oArgumentCount = oArguments.Count
|
||||
|
||||
If (oArgumentCount > 0) Then
|
||||
StringBuilder = ""
|
||||
|
||||
oArgumentCounter = 1
|
||||
|
||||
Set ArgumentNameExpression = New RegExp
|
||||
|
||||
With ArgumentNameExpression
|
||||
.Pattern = "^Debug$"
|
||||
.IgnoreCase = True
|
||||
.Global = False
|
||||
.Multiline = False
|
||||
End With
|
||||
|
||||
Set ArgumentValueExpression = New RegExp
|
||||
|
||||
With ArgumentValueExpression
|
||||
.Pattern = "^.*True|.*False$"
|
||||
.IgnoreCase = True
|
||||
.Global = False
|
||||
.Multiline = False
|
||||
End With
|
||||
|
||||
For Each oArgument In oArguments
|
||||
ArgumentName = Trim(oArgument)
|
||||
ArgumentValue = oArguments.Item(oArgument)
|
||||
|
||||
If (Not(ArgumentNameExpression.Test(ArgumentName))) Then
|
||||
Select Case ((Len(ArgumentValue) > 0) And (Not(ArgumentValueExpression.Test(ArgumentValue))))
|
||||
Case True
|
||||
If (InStr(ArgumentValue, ",") > 0) Then
|
||||
ArgumentValueParts = Split(ArgumentValue, ",")
|
||||
|
||||
ArgumentValuePartsCount = UBound(ArgumentValueParts)
|
||||
|
||||
ArgumentValuePartStringBuilder = ""
|
||||
|
||||
ArgumentValuePartCounter = 0
|
||||
|
||||
For Each ArgumentValuePart In ArgumentValueParts
|
||||
ArgumentValuePartFormat = chrDoubleQuote & ArgumentValuePart & chrDoubleQuote
|
||||
|
||||
ArgumentValuePartStringBuilder = ArgumentValuePartStringBuilder & ArgumentValuePartFormat
|
||||
|
||||
If ((ArgumentValuePartsCount > 0) And (ArgumentValuePartCounter < ArgumentValuePartsCount)) Then
|
||||
ArgumentValuePartStringBuilder = ArgumentValuePartStringBuilder & ","
|
||||
ArgumentValuePartCounter = ArgumentValuePartCounter + 1
|
||||
End If
|
||||
Next
|
||||
|
||||
ParameterFormat = "-" & ArgumentName & chrSpace & ArgumentValuePartStringBuilder
|
||||
ElseIf (IsNumeric(ArgumentValue) = True) Then
|
||||
ParameterFormat = "-" & ArgumentName & chrSpace & ArgumentValue
|
||||
Else
|
||||
ParameterFormat = "-" & ArgumentName & chrSpace & chrDoubleQuote & ArgumentValue & chrDoubleQuote
|
||||
End If
|
||||
Case False
|
||||
ParameterFormat = "-" & ArgumentName
|
||||
End Select
|
||||
|
||||
If (Len(ParameterFormat) > 0) Then
|
||||
|
||||
If ((oArgumentCount > 1) And (oArgumentCounter < oArgumentCount)) Then
|
||||
StringBuilder = StringBuilder & chrSpace
|
||||
End If
|
||||
|
||||
StringBuilder = StringBuilder & ParameterFormat
|
||||
|
||||
ArgumentCounter = oArgumentCounter + 1
|
||||
|
||||
ParameterFormat = Null
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
|
||||
StringBuilderResult = Trim(StringBuilder)
|
||||
|
||||
If (Len(StringBuilderResult) > 0) Then
|
||||
PowershellScriptParameters = StringBuilderResult & ";" & chrSpace & "[System.Environment]::Exit(($LASTEXITCODE -Bor [Int](-Not $? -And -Not $LASTEXITCODE)))"
|
||||
Else
|
||||
If (DebugMode = True) Then
|
||||
WScript.Echo("Debug mode is enabled. The specified command will NOT be executed.")
|
||||
End If
|
||||
|
||||
PowershellScriptParameters = ";" & chrSpace & "[System.Environment]::Exit(($LASTEXITCODE -Bor [Int](-Not $? -And -Not $LASTEXITCODE)))"
|
||||
End If
|
||||
|
||||
Set ArgumentNameExpression = Nothing
|
||||
|
||||
Set ArgumentValueExpression = Nothing
|
||||
Else
|
||||
If (DebugMode = True) Then
|
||||
WScript.Echo(oArgumentCount & chrSpace & "arguments were specified.")
|
||||
End If
|
||||
End If
|
||||
|
||||
'Define Additional Variable(s)
|
||||
Set ScriptPath = oFSO.GetFile(WScript.ScriptFullName)
|
||||
ScriptDirectory = ScriptPath.ParentFolder
|
||||
System32Directory = oShell.ExpandEnvironmentStrings("%WINDIR%") & "\System32"
|
||||
CommandPromptExecutionParameters = oCMD.Name & chrSpace & "/c"
|
||||
PowershellExecutionParameters = chrDoubleQuote & oPowershell.Path & chrDoubleQuote & chrSpace & "-ExecutionPolicy Bypass -NonInteractive -NoProfile -NoLogo -WindowStyle Hidden -Command"
|
||||
PowershellScriptPath = ScriptDirectory & "\" & oFSO.GetBaseName(ScriptPath) & ".ps1"
|
||||
|
||||
'Execute Powershell Script
|
||||
If (Len(PowershellScriptParameters) > 0) Then
|
||||
Command = PowershellExecutionParameters & chrSpace & chrDoubleQuote & "&" & chrSpace & chrSingleQuote & PowershellScriptPath & chrSingleQuote & chrSpace & PowershellScriptParameters & chrDoubleQuote
|
||||
Else
|
||||
Command = PowershellExecutionParameters & chrSpace & chrDoubleQuote & "&" & chrSpace & chrSingleQuote & PowershellScriptPath & chrSingleQuote & chrDoubleQuote
|
||||
End If
|
||||
|
||||
If ((ScriptInterpreter = "cscript.exe") Or (DebugMode = True)) Then
|
||||
WScript.Echo("Command:" & chrSpace & Command)
|
||||
End If
|
||||
|
||||
If (DebugMode = False) Then
|
||||
RunCommand = oShell.Run(Command, 0, True)
|
||||
End If
|
||||
|
||||
If ((ScriptInterpreter = "cscript.exe") Or (DebugMode = True)) And (IsEmpty(RunCommand) = False) Then
|
||||
WScript.Echo("Exit Code:" & chrSpace & RunCommand)
|
||||
End If
|
||||
|
||||
If (DebugMode = False) Then
|
||||
WScript.Quit(RunCommand)
|
||||
End If
|
||||
@@ -1,2 +1,34 @@
|
||||
# Dynamic OSD Application List
|
||||
Allows for the dynamic installation of applications during a MDT task sequence.
|
||||
|
||||
Run the Update-MDTApplicationXML.ps1 and provide the path to the Applications.xml within the control folder inside the MDT deployment share.
|
||||
|
||||
This will make the application object specific adjustments to support the script that runs during the task sequence. It is totally safe and will not cause disruptive issues.
|
||||
|
||||
Updates the MDT Applications.xml file to support the functionality built into the Invoke-OSDApplicationList.ps1 powershell script.
|
||||
|
||||
Just refresh the 'Applications' view within the MDT Deployment Workbench after executing this script and make any application specific adjustments as needed.
|
||||
|
||||
Sort the application(s) by the version column within the MDT Deployment Workbench to see the order in which the applications would be installed by the task sequence.
|
||||
|
||||
|
||||
Updates the 'Version' property of each application with the installation order (Will be based on creation date initially, but can be adjusted according to any specific needs.
|
||||
Updates the 'Language' property of each application within the Applications.xml with a powershell based condition that will determine if the application will be installed during a task sequence.
|
||||
|
||||
To install in all cases, just simply use "$True" without the quotes.
|
||||
To skip in all cases, just simply use "$False" without the quotes.
|
||||
|
||||
Setting the right mixture of condition and installation order will provide a super smooth and consistent installation experience.
|
||||
|
||||
Example: VMWare Tools
|
||||
Installation Order = 1
|
||||
Condition = ($ComputerSystem.Manufacturer -imatch '.*VM.*Ware.*')
|
||||
This would ensure that VMWare Tools gets installed first only VMWare virtual machines.
|
||||
|
||||
Any variable that will be available during the execution of the Invoke-OSDApplicationList.ps1 powershell script can be used within a condition.
|
||||
|
||||
Dynamically creates 'MandatoryApplicationXXX' task sequence variables with the GUIDs of MDT application objects to install on a device during operating system deployment.
|
||||
|
||||
Individual applications or entire application folders can be disabled to exclude the application(s) from being considered by the script during deployment.
|
||||
|
||||
Application(s) that have already been installed by the task sequence whose GUID is stored within a 'InstalledApplicationsXXX' variable will be skipped if this script is executed multiple times during a task sequence.
|
||||
@@ -0,0 +1 @@
|
||||
###
|
||||
@@ -0,0 +1 @@
|
||||
###
|
||||
@@ -0,0 +1,569 @@
|
||||
#Requires -Version 3
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Updates the MDT Applications.xml to support the functionality built into the Invoke-OSDApplicationList.ps1 powershell script.
|
||||
|
||||
Just refresh the 'Applications' view within the MDT Deployment Workbench after executing this script and make any application specific adjustments as needed.
|
||||
|
||||
Sort the application(s) by the version column within the MDT Deployment Workbench to see the order in which the applications would be installed by the task sequence.
|
||||
|
||||
.DESCRIPTION
|
||||
Updates the 'Version' property of each application with the installation order (Will be based on creation date initially, but can be adjusted according to any specific needs.
|
||||
Updates the 'Language' property of each application within the Applications.xml with a powershell based condition that will determine if the application will be installed during a task sequence.
|
||||
|
||||
To install in all cases, just simply use "$True" without the quotes.
|
||||
To skip in all cases, just simply use "$False" without the quotes.
|
||||
|
||||
Setting the right mixture of condition and installation order will provide a super smooth and consistent installation experience.
|
||||
|
||||
Example: VMWare Tools
|
||||
Installation Order = 1
|
||||
Condition = ($ComputerSystem.Manufacturer -imatch '.*VM.*Ware.*')
|
||||
This would ensure that VMWare Tools gets installed first only VMWare virtual machines.
|
||||
|
||||
Any variable that will be available during the execution of the Invoke-OSDApplicationList.ps1 powershell script can be used within a condition.
|
||||
|
||||
.PARAMETER ApplicationFolderDefinitionPath
|
||||
A valid path to the ApplicationGroups.xml file stored within the 'Control' folder within a MDT deployment share.
|
||||
|
||||
.PARAMETER ApplicationDefinitionPath
|
||||
A valid path to the Applications.xml file stored within the 'Control' folder within a MDT deployment share.
|
||||
|
||||
.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.
|
||||
|
||||
.PARAMETER DebugMode
|
||||
Allows for testing to see which applications would be deployed without running a task sequence.
|
||||
|
||||
.EXAMPLE
|
||||
Use this command to execute a VBSCript that will launch this powershell script automatically with the specified parameters. This is useful to avoid powershell execution complexities.
|
||||
|
||||
cscript.exe /nologo "%FolderPathContainingScript%\%ScriptName%.vbs" /SwitchParameter /ScriptParameter:"%ScriptParameterValue%" /ScriptParameterArray:"%ScriptParameterValue1%,%ScriptParameterValue2%"
|
||||
|
||||
wscript.exe /nologo "%FolderPathContainingScript%\%ScriptName%.vbs" /SwitchParameter /ScriptParameter:"%ScriptParameterValue%" /ScriptParameterArray:"%ScriptParameterValue1%,%ScriptParameterValue2%"
|
||||
|
||||
.EXAMPLE
|
||||
powershell.exe -ExecutionPolicy Bypass -NoProfile -NoLogo -File "%FolderPathContainingScript%\%ScriptName%.ps1" -SwitchParameter -ScriptParameter "%ScriptParameterValue%"
|
||||
|
||||
.EXAMPLE
|
||||
powershell.exe -ExecutionPolicy Bypass -NonInteractive -NoProfile -NoLogo -WindowStyle Hidden -Command "& '%FolderPathContainingScript%\%ScriptName%.ps1' -ScriptParameter1 '%ScriptParameter1Value%' -ScriptParameter2 %ScriptParameter2Value% -SwitchParameter"
|
||||
|
||||
.NOTES
|
||||
Came up with this concept to keep task sequence modification to an absolute minimum.
|
||||
|
||||
.LINK
|
||||
Place any useful link here where your function or cmdlet can be referenced
|
||||
#>
|
||||
|
||||
[CmdletBinding(SupportsShouldProcess=$True)]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('ADP')]
|
||||
[System.IO.FileInfo]$ApplicationDefinitionPath,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias('LogDir', 'LogPath')]
|
||||
[System.IO.DirectoryInfo]$LogDirectory,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[Switch]$ContinueOnError
|
||||
)
|
||||
|
||||
Function Get-AdministrativePrivilege
|
||||
{
|
||||
$Identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$Principal = New-Object System.Security.Principal.WindowsPrincipal($Identity)
|
||||
Write-Output -InputObject ($Principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))
|
||||
}
|
||||
|
||||
If ((Get-AdministrativePrivilege) -eq $False)
|
||||
{
|
||||
[System.IO.FileInfo]$ScriptPath = "$($MyInvocation.MyCommand.Path)"
|
||||
|
||||
$ArgumentList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$ArgumentList.Add('-ExecutionPolicy Bypass')
|
||||
$ArgumentList.Add('-NoProfile')
|
||||
$ArgumentList.Add('-NoExit')
|
||||
$ArgumentList.Add('-NoLogo')
|
||||
$ArgumentList.Add("-File `"$($ScriptPath.FullName)`"")
|
||||
|
||||
$Null = Start-Process -FilePath "$([System.Environment]::SystemDirectory)\WindowsPowershell\v1.0\powershell.exe" -WorkingDirectory "$([System.Environment]::SystemDirectory)" -ArgumentList ($ArgumentList.ToArray()) -WindowStyle Normal -Verb RunAs -PassThru
|
||||
}
|
||||
Else
|
||||
{
|
||||
#Determine the date and time we executed the function
|
||||
$ScriptStartTime = (Get-Date)
|
||||
|
||||
#Define Default Action Preferences
|
||||
$Script:DebugPreference = 'SilentlyContinue'
|
||||
$Script:ErrorActionPreference = 'Stop'
|
||||
$Script:VerbosePreference = 'SilentlyContinue'
|
||||
$Script:WarningPreference = 'Continue'
|
||||
$Script:ConfirmPreference = 'None'
|
||||
$Script:WhatIfPreference = $False
|
||||
|
||||
#Load WMI Classes
|
||||
$Baseboard = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_Baseboard" -Property *
|
||||
$Bios = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_Bios" -Property *
|
||||
$ComputerSystem = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_ComputerSystem" -Property *
|
||||
$OperatingSystem = Get-WmiObject -Namespace "root\CIMv2" -Class "Win32_OperatingSystem" -Property *
|
||||
$MSSystemInformation = Get-WmiObject -Namespace "root\WMI" -Class "MS_SystemInformation" -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.FFF tt' ###Monday, January 01, 2019 @ 10:15:34.000 AM###
|
||||
[ScriptBlock]$GetCurrentDateTimeLogFormat = {(Get-Date).ToString($DateTimeLogFormat)}
|
||||
$DateTimeMessageFormat = 'MM/dd/yyyy HH:mm:ss.FFF' ###03/23/2022 11:12:48.347###
|
||||
[ScriptBlock]$GetCurrentDateTimeMessageFormat = {(Get-Date).ToString($DateTimeMessageFormat)}
|
||||
$DateFileFormat = 'yyyyMMdd' ###20190403###
|
||||
[ScriptBlock]$GetCurrentDateFileFormat = {(Get-Date).ToString($DateFileFormat)}
|
||||
$DateTimeFileFormat = 'yyyyMMdd_HHmmss' ###20190403_115354###
|
||||
[ScriptBlock]$GetCurrentDateTimeFileFormat = {(Get-Date).ToString($DateTimeFileFormat)}
|
||||
[System.IO.FileInfo]$ScriptPath = "$($MyInvocation.MyCommand.Definition)"
|
||||
[System.IO.DirectoryInfo]$ScriptDirectory = "$($ScriptPath.Directory.FullName)"
|
||||
[System.IO.DirectoryInfo]$ContentDirectory = "$($ScriptDirectory.FullName)\Content"
|
||||
[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)"
|
||||
[System.IO.DirectoryInfo]$System32Directory = [System.Environment]::SystemDirectory
|
||||
[System.IO.DirectoryInfo]$ProgramFilesDirectory = "$($Env:SystemDrive)\Program Files"
|
||||
[System.IO.DirectoryInfo]$ProgramFilesx86Directory = "$($Env:SystemDrive)\Program Files (x86)"
|
||||
[System.IO.FileInfo]$PowershellPath = "$($System32Directory.FullName)\WindowsPowershell\v1.0\powershell.exe"
|
||||
[System.IO.DirectoryInfo]$System32Directory = "$([System.Environment]::SystemDirectory)"
|
||||
$IsWindowsPE = Test-Path -Path 'HKLM:\SYSTEM\ControlSet001\Control\MiniNT' -ErrorAction SilentlyContinue
|
||||
[System.Text.RegularExpressions.RegexOptions[]]$RegexOptions = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase, [System.Text.RegularExpressions.RegexOptions]::Multiline
|
||||
[ScriptBlock]$GetRandomGUID = {[System.GUID]::NewGUID().GUID.ToString().ToUpper()}
|
||||
[String]$ParameterSetName = "$($PSCmdlet.ParameterSetName)"
|
||||
$TextInfo = (Get-Culture).TextInfo
|
||||
$Script:LASTEXITCODE = 0
|
||||
$TerminationCodes = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$TerminationCodes.Add('Success', @(0))
|
||||
$TerminationCodes.Add('Warning', @(5000..5999))
|
||||
$TerminationCodes.Add('Error', @(6000..6999))
|
||||
$Script:WarningCodeIndex = 0
|
||||
[ScriptBlock]$GetAvailableWarningCode = {$TerminationCodes.Warning[$Script:WarningCodeIndex]; $Script:WarningCodeIndex++}
|
||||
$Script:ErrorCodeIndex = 0
|
||||
[ScriptBlock]$GetAvailableErrorCode = {$TerminationCodes.Error[$Script:ErrorCodeIndex]; $Script:ErrorCodeIndex++}
|
||||
$LoggingDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$LoggingDetails.Add('LogMessage', $Null)
|
||||
$LoggingDetails.Add('WarningMessage', $Null)
|
||||
$LoggingDetails.Add('ErrorMessage', $Null)
|
||||
$RegularExpressionTable = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$RegularExpressionTable.Base64 = '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$' -As [Regex]
|
||||
$CommonParameterList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::CommonParameters)
|
||||
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::OptionalCommonParameters)
|
||||
|
||||
#Define the error handling definition
|
||||
[ScriptBlock]$ErrorHandlingDefinition = {
|
||||
If (($Null -ieq $Script:LASTEXITCODE) -or ($Script:LASTEXITCODE -eq 0))
|
||||
{
|
||||
[Int]$Script:LASTEXITCODE = $GetAvailableErrorCode.InvokeReturnAsIs()
|
||||
}
|
||||
|
||||
$ErrorMessageList = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$ErrorMessageList.Add('Message', $_.Exception.Message)
|
||||
$ErrorMessageList.Add('Category', $_.Exception.ErrorRecord.FullyQualifiedErrorID)
|
||||
$ErrorMessageList.Add('ExitCode', $Script:LASTEXITCODE)
|
||||
$ErrorMessageList.Add('Script', $_.InvocationInfo.ScriptName)
|
||||
$ErrorMessageList.Add('LineNumber', $_.InvocationInfo.ScriptLineNumber)
|
||||
$ErrorMessageList.Add('LinePosition', $_.InvocationInfo.OffsetInLine)
|
||||
$ErrorMessageList.Add('Code', $_.InvocationInfo.Line.Trim())
|
||||
|
||||
ForEach ($ErrorMessage In $ErrorMessageList.GetEnumerator())
|
||||
{
|
||||
$LoggingDetails.ErrorMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - ERROR: $($ErrorMessage.Key): $($ErrorMessage.Value)"
|
||||
Write-Warning -Message ($LoggingDetails.ErrorMessage) -Verbose
|
||||
}
|
||||
|
||||
Switch (($ContinueOnError.IsPresent -eq $False) -or ($ContinueOnError -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Determine default parameter value(s)
|
||||
Switch ($True)
|
||||
{
|
||||
{([String]::IsNullOrEmpty($LogDirectory) -eq $True) -or ([String]::IsNullOrWhiteSpace($LogDirectory) -eq $True)}
|
||||
{
|
||||
[System.IO.DirectoryInfo]$LogDirectory = "$($Env:Windir)\Logs\Software\$($ScriptPath.BaseName)"
|
||||
}
|
||||
}
|
||||
|
||||
#Start transcripting (Logging)
|
||||
[System.IO.FileInfo]$ScriptLogPath = "$($LogDirectory.FullName)\$($ScriptPath.BaseName)_$($GetCurrentDateFileFormat.Invoke()).log"
|
||||
If ($ScriptLogPath.Directory.Exists -eq $False) {$Null = [System.IO.Directory]::CreateDirectory($ScriptLogPath.Directory.FullName)}
|
||||
Start-Transcript -Path "$($ScriptLogPath.FullName)" -Force -WhatIf:$False
|
||||
|
||||
#Log any useful information
|
||||
[String]$CmdletName = $MyInvocation.MyCommand.Name
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of script `"$($CmdletName)`" began on $($ScriptStartTime.ToString($DateTimeLogFormat))"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Script Path = $($ScriptPath.FullName)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
[String[]]$AvailableScriptParameters = (Get-Command -Name ($ScriptPath.FullName)).Parameters.GetEnumerator() | Where-Object {($_.Value.Name -inotin $CommonParameterList)} | ForEach-Object {"-$($_.Value.Name):$($_.Value.ParameterType.Name)"}
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Available Script Parameter(s) = $($AvailableScriptParameters -Join ', ')"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
[String[]]$SuppliedScriptParameters = $PSBoundParameters.GetEnumerator() | ForEach-Object {"-$($_.Key):$($_.Value.GetType().Name)"}
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Supplied Script Parameter(s) = $($SuppliedScriptParameters -Join ', ')"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Switch ($True)
|
||||
{
|
||||
{([String]::IsNullOrEmpty($ParameterSetName) -eq $False)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Parameter Set Name = $($ParameterSetName)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Command Line: $((Get-WMIObject -Namespace 'Root\CIMv2' -Class 'Win32_Process' -Filter "ProcessID = $($PID)").CommandLine)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($PSBoundParameters.Count) command line parameter(s) were specified."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$OperatingSystemDetailsTable = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
||||
$OperatingSystemDetailsTable.ProductName = $OperatingSystem.Caption -ireplace '(Microsoft\s+)', ''
|
||||
$OperatingSystemDetailsTable.Version = $OperatingSystem.Version
|
||||
$OperatingSystemDetailsTable.Architecture = $OperatingSystem.OSArchitecture
|
||||
|
||||
$OperatingSystemRegistryDetails = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
||||
$OperatingSystemRegistryDetails.Add((New-Object -TypeName 'PSObject' -Property @{Alias = ''; Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'; ValueName = 'UBR'; Value = $Null}))
|
||||
$OperatingSystemRegistryDetails.Add((New-Object -TypeName 'PSObject' -Property @{Alias = 'ReleaseVersion'; Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'; ValueName = 'ReleaseID'; Value = $Null}))
|
||||
$OperatingSystemRegistryDetails.Add((New-Object -TypeName 'PSObject' -Property @{Alias = 'ReleaseID'; Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'; ValueName = 'DisplayVersion'; Value = $Null}))
|
||||
|
||||
ForEach ($OperatingSystemRegistryDetail In $OperatingSystemRegistryDetails)
|
||||
{
|
||||
$OperatingSystemRegistryDetail.Value = Try {(Get-Item -Path $OperatingSystemRegistryDetail.Path).GetValue($OperatingSystemRegistryDetail.ValueName)} Catch {}
|
||||
|
||||
:NextOSDetail Switch (([String]::IsNullOrEmpty($OperatingSystemRegistryDetail.Value) -eq $False) -and ([String]::IsNullOrWhiteSpace($OperatingSystemRegistryDetail.Value) -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
Switch ($OperatingSystemRegistryDetail.ValueName)
|
||||
{
|
||||
{($_ -ieq 'UBR')}
|
||||
{
|
||||
$OperatingSystemDetailsTable.Version = $OperatingSystemDetailsTable.Version + '.' + $OperatingSystemRegistryDetail.Value
|
||||
|
||||
Break NextOSDetail
|
||||
}
|
||||
}
|
||||
|
||||
Switch (([String]::IsNullOrEmpty($OperatingSystemRegistryDetail.Alias) -eq $False) -and ([String]::IsNullOrWhiteSpace($OperatingSystemRegistryDetail.Alias) -eq $False))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$OperatingSystemDetailsTable.$($OperatingSystemRegistryDetail.Alias) = $OperatingSystemRegistryDetail.Value
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$OperatingSystemDetailsTable.$($OperatingSystemRegistryDetail.ValueName) = $OperatingSystemRegistryDetail.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$OperatingSystemDetailsTable.$($OperatingSystemRegistryDetail.ValueName) = $OperatingSystemRegistryDetail.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ForEach ($OperatingSystemDetail In $OperatingSystemDetailsTable.GetEnumerator())
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($OperatingSystemDetail.Key): $($OperatingSystemDetail.Value)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Powershell Version: $($PSVersionTable.PSVersion.ToString())"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$ExecutionPolicyList = Get-ExecutionPolicy -List
|
||||
|
||||
For ($ExecutionPolicyListIndex = 0; $ExecutionPolicyListIndex -lt $ExecutionPolicyList.Count; $ExecutionPolicyListIndex++)
|
||||
{
|
||||
$ExecutionPolicy = $ExecutionPolicyList[$ExecutionPolicyListIndex]
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The powershell execution policy is currently set to `"$($ExecutionPolicy.ExecutionPolicy.ToString())`" for the `"$($ExecutionPolicy.Scope.ToString())`" scope."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
|
||||
#Log hardware information
|
||||
$MSSystemInformationMembers = $MSSystemInformation.PSObject.Properties | Where-Object {($_.MemberType -imatch '^NoteProperty$|^Property$') -and ($_.Name -imatch '^Base.*|Bios.*|System.*$') -and ($_.Name -inotmatch '^.*Major.*|.*Minor.*|.*Properties.*$')} | Sort-Object -Property @('Name')
|
||||
|
||||
Switch ($MSSystemInformationMembers.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to display device information properties from the `"$($MSSystemInformation.__CLASS)`" WMI class located within the `"$($MSSystemInformation.__NAMESPACE)`" WMI namespace. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
ForEach ($MSSystemInformationMember In $MSSystemInformationMembers)
|
||||
{
|
||||
[String]$MSSystemInformationMemberName = ($MSSystemInformationMember.Name)
|
||||
[String]$MSSystemInformationMemberValue = $MSSystemInformation.$($MSSystemInformationMemberName)
|
||||
|
||||
Switch ([String]::IsNullOrEmpty($MSSystemInformationMemberValue))
|
||||
{
|
||||
{($_ -eq $False)}
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - $($MSSystemInformationMemberName) = $($MSSystemInformationMemberValue)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - The `"MSSystemInformation`" WMI class could not be found."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
}
|
||||
}
|
||||
|
||||
#region Log Cleanup
|
||||
[Int]$MaximumLogHistory = 3
|
||||
|
||||
$LogList = Get-ChildItem -Path ($LogDirectory.FullName) -Filter "$($ScriptPath.BaseName)_*" -Recurse -Force | Where-Object {($_ -is [System.IO.FileInfo])}
|
||||
|
||||
$SortedLogList = $LogList | Sort-Object -Property @('LastWriteTime') -Descending | Select-Object -Skip ($MaximumLogHistory)
|
||||
|
||||
Switch ($SortedLogList.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - There are $($SortedLogList.Count) log file(s) requiring cleanup."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
|
||||
For ($SortedLogListIndex = 0; $SortedLogListIndex -lt $SortedLogList.Count; $SortedLogListIndex++)
|
||||
{
|
||||
Try
|
||||
{
|
||||
$Log = $SortedLogList[$SortedLogListIndex]
|
||||
|
||||
$LogAge = New-TimeSpan -Start ($Log.LastWriteTime) -End (Get-Date)
|
||||
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to cleanup log file `"$($Log.FullName)`". Please Wait... [Last Modified: $($Log.LastWriteTime.ToString($DateTimeMessageFormat))] [Age: $($LogAge.Days.ToString()) day(s); $($LogAge.Hours.ToString()) hours(s); $($LogAge.Minutes.ToString()) minute(s); $($LogAge.Seconds.ToString()) second(s)]."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
|
||||
$Null = [System.IO.File]::Delete($Log.FullName)
|
||||
}
|
||||
Catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - There are $($SortedLogList.Count) log file(s) requiring cleanup."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Import Dependency Modules
|
||||
If (($ModulesDirectory.Exists -eq $True) -and ($ModulesDirectory.GetDirectories().Count -gt 0))
|
||||
{
|
||||
$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 ($Null -ine $LatestModuleVersion)
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to import dependency powershell module `"$($LatestModuleVersion.Name)`" [Version: $($LatestModuleVersion.Version.ToString())]. Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.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)
|
||||
{
|
||||
$AdditionalFunctionsFilter = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
$AdditionalFunctionsFilter.Add('*.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
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to dot source the functions contained within the dependency script `"$($AdditionalFunctionToImport.Name)`". Please Wait... [Script Path: `"$($AdditionalFunctionToImport.FullName)`"]"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
. "$($AdditionalFunctionToImport.FullName)"
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Load any required libraries
|
||||
[System.IO.DirectoryInfo]$LibariesDirectory = "$($FunctionsDirectory.FullName)\Libraries"
|
||||
|
||||
Switch ([System.IO.Directory]::Exists($LibariesDirectory.FullName))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LibraryPatternList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
||||
#$LibraryPatternList.Add('')
|
||||
|
||||
Switch ($LibraryPatternList.Count -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$LibraryList = Get-ChildItem -Path ($LibariesDirectory.FullName) -Include ($LibraryPatternList.ToArray()) -Recurse -Force | Where-Object {($_ -is [System.IO.FileInfo])}
|
||||
|
||||
$LibraryListCount = ($LibraryList | Measure-Object).Count
|
||||
|
||||
Switch ($LibraryListCount -gt 0)
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
For ($LibraryListIndex = 0; $LibraryListIndex -lt $LibraryListCount; $LibraryListIndex++)
|
||||
{
|
||||
$Library = $LibraryList[$LibraryListIndex]
|
||||
|
||||
[Byte[]]$LibraryBytes = [System.IO.File]::ReadAllBytes($Library.FullName)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to load assembly `"$($Library.FullName)`". Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$Null = [System.Reflection.Assembly]::Load($LibraryBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#Perform script action(s)
|
||||
Try
|
||||
{
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application Definition Path: $($ApplicationDefinitionPath.FullName)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Switch ([System.IO.File]::Exists($ApplicationDefinitionPath.FullName))
|
||||
{
|
||||
{($_ -eq $True)}
|
||||
{
|
||||
$ApplicationDefinitionContents = [System.IO.File]::ReadAllText($ApplicationDefinitionPath.FullName)
|
||||
|
||||
$ApplicationDefinition = New-Object -TypeName 'System.Xml.XmlDocument'
|
||||
$ApplicationDefinition.LoadXml($ApplicationDefinitionContents)
|
||||
|
||||
$AvailableApplicationList = $ApplicationDefinition.applications.application | Sort-Object -Property @{Expression = {Try {(Get-Date -Date ($AvailableApplication.CreatedTime))} Catch {}}}
|
||||
|
||||
#Starting at 100 provides space to set higher priority application(s) to the lower numbers to ensure they get installed first.
|
||||
$StartingApplicationOrder = 100
|
||||
|
||||
For ($AvailableApplicationListIndex = 0; $AvailableApplicationListIndex -lt $AvailableApplicationList.Count; $AvailableApplicationListIndex++)
|
||||
{
|
||||
$AvailableApplication = $AvailableApplicationList[$AvailableApplicationListIndex]
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to make configuration adjustment(s) to application `"$($AvailableApplication.Name)`". Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$AvailableApplication.Version = $StartingApplicationOrder.ToString()
|
||||
$AvailableApplication.Language = '($OperatingSystem.ProductType -in @(1))'
|
||||
|
||||
$StartingApplicationOrder++
|
||||
}
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to save application configuration changes to `"$($ApplicationDefinitionPath.FullName)`". Please Wait..."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$Null = $ApplicationDefinition.Save($ApplicationDefinitionPath.FullName)
|
||||
|
||||
$Null = Start-Sleep -Seconds 3
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
$LoggingDetails.WarningMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Application definition file `"$($ApplicationDefinitionPath.FullName)`" does not exist."
|
||||
Write-Warning -Message ($LoggingDetails.WarningMessage) -Verbose
|
||||
}
|
||||
}
|
||||
|
||||
$Script:LASTEXITCODE = $TerminationCodes.Success[0]
|
||||
}
|
||||
Catch
|
||||
{
|
||||
$ErrorHandlingDefinition.Invoke()
|
||||
}
|
||||
Finally
|
||||
{
|
||||
Try
|
||||
{
|
||||
#Determine the date and time the function completed execution
|
||||
$ScriptEndTime = (Get-Date)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Script execution of `"$($CmdletName)`" ended on $($ScriptEndTime.ToString($DateTimeLogFormat))"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
#Log the total script execution time
|
||||
$ScriptExecutionTimespan = New-TimeSpan -Start ($ScriptStartTime) -End ($ScriptEndTime)
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Script execution took $($ScriptExecutionTimespan.Hours.ToString()) hour(s), $($ScriptExecutionTimespan.Minutes.ToString()) minute(s), $($ScriptExecutionTimespan.Seconds.ToString()) second(s), and $($ScriptExecutionTimespan.Milliseconds.ToString()) millisecond(s)"
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Exiting script `"$($ScriptPath.FullName)`" with exit code $($Script:LASTEXITCODE)."
|
||||
Write-Verbose -Message ($LoggingDetails.LogMessage) -Verbose
|
||||
|
||||
Stop-Transcript
|
||||
}
|
||||
Catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
'Set object values
|
||||
Set oArguments = WScript.Arguments.Named
|
||||
Set oFSO = CreateObject("Scripting.FileSystemObject")
|
||||
Set oShell = CreateObject("WScript.Shell")
|
||||
Set oCMD = oFSO.GetFile(oShell.ExpandEnvironmentStrings("%COMSPEC%"))
|
||||
Set oPowershell = oFSO.GetFile(oShell.ExpandEnvironmentStrings("%WINDIR%") & "\System32\WindowsPowershell\v1.0\powershell.exe")
|
||||
|
||||
'Define ASCII Characters
|
||||
chrSpace = Chr(32)
|
||||
chrSingleQuote = Chr(39)
|
||||
chrDoubleQuote = Chr(34)
|
||||
|
||||
'Define Variable(s)
|
||||
ScriptInterpreter = CreateObject("Scripting.FileSystemObject").GetFileName(WScript.FullName)
|
||||
If (oArguments.Exists("Debug") = True) Then DebugMode = True End If
|
||||
|
||||
'Dynamically convert named VBScript arguments to their eqivalent powershell format
|
||||
oArgumentCount = oArguments.Count
|
||||
|
||||
If (oArgumentCount > 0) Then
|
||||
StringBuilder = ""
|
||||
|
||||
oArgumentCounter = 1
|
||||
|
||||
Set ArgumentNameExpression = New RegExp
|
||||
|
||||
With ArgumentNameExpression
|
||||
.Pattern = "^Debug$"
|
||||
.IgnoreCase = True
|
||||
.Global = False
|
||||
.Multiline = False
|
||||
End With
|
||||
|
||||
Set ArgumentValueExpression = New RegExp
|
||||
|
||||
With ArgumentValueExpression
|
||||
.Pattern = "^.*True|.*False$"
|
||||
.IgnoreCase = True
|
||||
.Global = False
|
||||
.Multiline = False
|
||||
End With
|
||||
|
||||
For Each oArgument In oArguments
|
||||
ArgumentName = Trim(oArgument)
|
||||
ArgumentValue = oArguments.Item(oArgument)
|
||||
|
||||
If (Not(ArgumentNameExpression.Test(ArgumentName))) Then
|
||||
Select Case ((Len(ArgumentValue) > 0) And (Not(ArgumentValueExpression.Test(ArgumentValue))))
|
||||
Case True
|
||||
If (InStr(ArgumentValue, ",") > 0) Then
|
||||
ArgumentValueParts = Split(ArgumentValue, ",")
|
||||
|
||||
ArgumentValuePartsCount = UBound(ArgumentValueParts)
|
||||
|
||||
ArgumentValuePartStringBuilder = ""
|
||||
|
||||
ArgumentValuePartCounter = 0
|
||||
|
||||
For Each ArgumentValuePart In ArgumentValueParts
|
||||
ArgumentValuePartFormat = chrDoubleQuote & ArgumentValuePart & chrDoubleQuote
|
||||
|
||||
ArgumentValuePartStringBuilder = ArgumentValuePartStringBuilder & ArgumentValuePartFormat
|
||||
|
||||
If ((ArgumentValuePartsCount > 0) And (ArgumentValuePartCounter < ArgumentValuePartsCount)) Then
|
||||
ArgumentValuePartStringBuilder = ArgumentValuePartStringBuilder & ","
|
||||
ArgumentValuePartCounter = ArgumentValuePartCounter + 1
|
||||
End If
|
||||
Next
|
||||
|
||||
ParameterFormat = "-" & ArgumentName & chrSpace & ArgumentValuePartStringBuilder
|
||||
ElseIf (IsNumeric(ArgumentValue) = True) Then
|
||||
ParameterFormat = "-" & ArgumentName & chrSpace & ArgumentValue
|
||||
Else
|
||||
ParameterFormat = "-" & ArgumentName & chrSpace & chrDoubleQuote & ArgumentValue & chrDoubleQuote
|
||||
End If
|
||||
Case False
|
||||
ParameterFormat = "-" & ArgumentName
|
||||
End Select
|
||||
|
||||
If (Len(ParameterFormat) > 0) Then
|
||||
|
||||
If ((oArgumentCount > 1) And (oArgumentCounter < oArgumentCount)) Then
|
||||
StringBuilder = StringBuilder & chrSpace
|
||||
End If
|
||||
|
||||
StringBuilder = StringBuilder & ParameterFormat
|
||||
|
||||
ArgumentCounter = oArgumentCounter + 1
|
||||
|
||||
ParameterFormat = Null
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
|
||||
StringBuilderResult = Trim(StringBuilder)
|
||||
|
||||
If (Len(StringBuilderResult) > 0) Then
|
||||
PowershellScriptParameters = StringBuilderResult & ";" & chrSpace & "[System.Environment]::Exit(($LASTEXITCODE -Bor [Int](-Not $? -And -Not $LASTEXITCODE)))"
|
||||
Else
|
||||
If (DebugMode = True) Then
|
||||
WScript.Echo("Debug mode is enabled. The specified command will NOT be executed.")
|
||||
End If
|
||||
|
||||
PowershellScriptParameters = ";" & chrSpace & "[System.Environment]::Exit(($LASTEXITCODE -Bor [Int](-Not $? -And -Not $LASTEXITCODE)))"
|
||||
End If
|
||||
|
||||
Set ArgumentNameExpression = Nothing
|
||||
|
||||
Set ArgumentValueExpression = Nothing
|
||||
Else
|
||||
If (DebugMode = True) Then
|
||||
WScript.Echo(oArgumentCount & chrSpace & "arguments were specified.")
|
||||
End If
|
||||
End If
|
||||
|
||||
'Define Additional Variable(s)
|
||||
Set ScriptPath = oFSO.GetFile(WScript.ScriptFullName)
|
||||
ScriptDirectory = ScriptPath.ParentFolder
|
||||
System32Directory = oShell.ExpandEnvironmentStrings("%WINDIR%") & "\System32"
|
||||
CommandPromptExecutionParameters = oCMD.Name & chrSpace & "/c"
|
||||
PowershellExecutionParameters = chrDoubleQuote & oPowershell.Path & chrDoubleQuote & chrSpace & "-ExecutionPolicy Bypass -NonInteractive -NoProfile -NoLogo -WindowStyle Hidden -Command"
|
||||
PowershellScriptPath = ScriptDirectory & "\" & oFSO.GetBaseName(ScriptPath) & ".ps1"
|
||||
|
||||
'Execute Powershell Script
|
||||
If (Len(PowershellScriptParameters) > 0) Then
|
||||
Command = PowershellExecutionParameters & chrSpace & chrDoubleQuote & "&" & chrSpace & chrSingleQuote & PowershellScriptPath & chrSingleQuote & chrSpace & PowershellScriptParameters & chrDoubleQuote
|
||||
Else
|
||||
Command = PowershellExecutionParameters & chrSpace & chrDoubleQuote & "&" & chrSpace & chrSingleQuote & PowershellScriptPath & chrSingleQuote & chrDoubleQuote
|
||||
End If
|
||||
|
||||
If ((ScriptInterpreter = "cscript.exe") Or (DebugMode = True)) Then
|
||||
WScript.Echo("Command:" & chrSpace & Command)
|
||||
End If
|
||||
|
||||
If (DebugMode = False) Then
|
||||
RunCommand = oShell.Run(Command, 0, True)
|
||||
End If
|
||||
|
||||
If ((ScriptInterpreter = "cscript.exe") Or (DebugMode = True)) And (IsEmpty(RunCommand) = False) Then
|
||||
WScript.Echo("Exit Code:" & chrSpace & RunCommand)
|
||||
End If
|
||||
|
||||
If (DebugMode = False) Then
|
||||
WScript.Quit(RunCommand)
|
||||
End If
|
||||
Reference in New Issue
Block a user