In MDT-integrated Configuration Manager, a UDI task sequence contains a couple of steps called Branding to Reg that brands OSD variables to the registry. This can be useful for reporting, and they can be inventoried with Configuration Manager using the handy RegKeyToMOF utility.
These steps can also be added manually to a ZTI task sequence as Kenneth van Surksum describes in his blog series.
The steps run a script called “OSDBranding.vbs” which defines which variables will be stamped to the following registry location:
HKLM\Software\Microsoft\MPSD\OSD
You can edit this script to add / remove any variables you want to save in the registry. If you have custom variables that begin with “OSD” for example, these will be saved to the registry by default.
I wrote the following PowerShell script to retrieve these OSD registry values post-deployment from any remote computer. The script includes a calculation of the deployment duration if the OSDStartTime and OSDEndTime variables are populated and adds it as OSDDuration. It only returns properties that actually have populated values.
Example:
Get-OSDInfo -Computername PC001
Get-OSDInfo
function Get-OSDInfo { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 0)] [ValidateScript({ Test-Connection -ComputerName $_ -Count 2 -Quiet })] [string]$ComputerName ) # Define code to run $Code = { $results = @() # Check if the registry key exists, and get the property list if it does try { $Properties = Get-Item -Path 'HKLM:\SOFTWARE\Microsoft\MPSD\OSD' | Select-Object -ExpandProperty Property -ErrorAction Stop } catch { Write-Host -Object "$_" -ForegroundColor Red continue } # Get the property values for each key $Properties | ForEach-Object -Process { $value = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MPSD\OSD' -Name $_ | Select-Object -ExpandProperty $_ if ($value) { $obj = New-Object -TypeName psobject Add-Member -InputObject $obj -Name Property -Value $_ -MemberType NoteProperty Add-Member -InputObject $obj -Name Value -Value $value -MemberType NoteProperty $results += $obj } } # Calculate OSD duration if start time and end time exists $start = $results | Where-Object -FilterScript { $_.Property -eq 'OSDStartTime' } $end = $results | Where-Object -FilterScript { $_.Property -eq 'OSDEndTime' } if (($start.Value -ne $null) -and ($end.Value -ne $null)) { $Hours = (($end.Value | Get-Date) - ($start.Value | Get-Date)).Hours $Minutes = (($end.Value | Get-Date) - ($start.Value | Get-Date)).Minutes $Duration = "$Hours hours $Minutes minutes" $obj = New-Object -TypeName psobject Add-Member -InputObject $obj -Name Property -Value 'OSDDuration' -MemberType NoteProperty Add-Member -InputObject $obj -Name Value -Value $Duration -MemberType NoteProperty $results += $obj } # Sort and return results $results = $results | Sort-Object -Property Property if ($results) { return $results } } # Invoke the code remotely try { Invoke-Command -ComputerName $ComputerName -ScriptBlock $Code -ErrorAction Stop | Select-Object -Property Property, Value | Format-Table -AutoSize } catch { Write-Host -Object "$_" -ForegroundColor Red } }
Hey, if i want to use the “hostname” when im running the script, Tried to make $computer1=hostname
then Get-OSDInfo -Computername $computer1
But didnt get it to work, any tips? Thanks Pontus.
Hi, try this version of the code. Simply omit the “computername” parameter to run it against the local machine.
function Get-OSDInfo
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
ValueFromPipeline = $true,
Position = 0)]
[ValidateScript({
Test-Connection -ComputerName $_ -Count 2 -Quiet
})]
[string]$ComputerName
)
# Define code to run
$Code = {
$results = @()
# Check if the registry key exists, and get the property list if it does
try
{
$Properties = Get-Item -Path ‘HKLM:\SOFTWARE\Microsoft\MPSD\OSD’ | Select-Object -ExpandProperty Property -ErrorAction Stop
}
catch
{
Write-Host -Object “$_” -ForegroundColor Red
continue
}
# Get the property values for each key
$Properties | ForEach-Object -Process {
$value = Get-ItemProperty -Path ‘HKLM:\SOFTWARE\Microsoft\MPSD\OSD’ -Name $_ | Select-Object -ExpandProperty $_
if ($value)
{
$obj = New-Object -TypeName psobject
Add-Member -InputObject $obj -Name Property -Value $_ -MemberType NoteProperty
Add-Member -InputObject $obj -Name Value -Value $value -MemberType NoteProperty
$results += $obj
}
}
# Calculate OSD duration if start time and end time exists
$start = $results | Where-Object -FilterScript {
$_.Property -eq ‘OSDStartTime’
}
$end = $results | Where-Object -FilterScript {
$_.Property -eq ‘OSDEndTime’
}
if (($start.Value -ne $null) -and ($end.Value -ne $null))
{
$Hours = (($end.Value | Get-Date) – ($start.Value | Get-Date)).Hours
$Minutes = (($end.Value | Get-Date) – ($start.Value | Get-Date)).Minutes
$Duration = “$Hours hours $Minutes minutes”
$obj = New-Object -TypeName psobject
Add-Member -InputObject $obj -Name Property -Value ‘OSDDuration’ -MemberType NoteProperty
Add-Member -InputObject $obj -Name Value -Value $Duration -MemberType NoteProperty
$results += $obj
}
# Sort and return results
$results = $results | Sort-Object -Property Property
if ($results)
{
return $results
}
}
# Invoke the code remotely
try
{
If ($ComputerName)
{
Invoke-Command -ComputerName $ComputerName -ScriptBlock $Code -ErrorAction Stop |
Select-Object -Property Property, Value |
Format-Table -AutoSize
}
Else
{
Invoke-Command -ScriptBlock $Code -ErrorAction Stop |
Select-Object -Property Property, Value |
Format-Table -AutoSize
}
}
catch
{
Write-Host -Object “$_” -ForegroundColor Red
}
}