Home > database >  PowerShell: Inventory Report Shows Blank Data for Installation Date of Every AD Domain Controller
PowerShell: Inventory Report Shows Blank Data for Installation Date of Every AD Domain Controller

Time:11-25

I'm trying to get the operating system installation date of every Active Directory (AD) Domain Controller of a single AD domain as part of an inventory report. Thanks to this article, everything shown in the code block below will work in any AD environment. The "Install Date" column though, shows blank data in the grid view. To get the installation date it requires a PS-remoting session into each target Domain Controller. Not sure what I'm doing wrong with this after quite a bit of research, so posting here.

# Import AD module
Import-Module ActiveDirectory
 
# Get your ad domain
$DomainName = (Get-ADDomain).DNSRoot
 
$AllDCs = Get-ADDomainController -Filter * -Server $DomainName | Select-Object Hostname,Ipv4address,isGlobalCatalog,Site,Forest,OperatingSystem
  
# Create empty DataTable object
$DCTable = New-Object System.Data.DataTable
      
# Add columns
$DCTable.Columns.Add() | Out-Null
$DCTable.Columns[0].Caption = "Hostname"
$DCTable.Columns[0].ColumnName = "Hostname"
  
$DCTable.Columns.Add() | Out-Null
$DCTable.Columns[1].Caption = "IPv4Address"
$DCTable.Columns[1].ColumnName = "IPv4Address"
                      
$DCTable.Columns.Add() | Out-Null
$DCTable.Columns[2].Caption = "isGlobalCatalog"
$DCTable.Columns[2].ColumnName = "isGlobalCatalog"
$DCTable.Columns[2].DataType = "Boolean"
  
$DCTable.Columns.Add() | Out-Null
$DCTable.Columns[3].Caption = "Site"
$DCTable.Columns[3].ColumnName = "Site"
  
$DCTable.Columns.Add() | Out-Null
$DCTable.Columns[4].Caption = "Forest"
$DCTable.Columns[4].ColumnName = "Forest"
  
$DCTable.Columns.Add() | Out-Null
$DCTable.Columns[5].Caption = "OperatingSystem"
$DCTable.Columns[5].ColumnName = "OperatingSystem"
 
$DCTable.Columns.Add() | Out-Null
$DCTable.Columns[6].Caption = "PingStatus"
$DCTable.Columns[6].ColumnName = "PingStatus"

$DCTable.Columns.Add() | Out-Null
$DCTable.Columns[7].Caption = "InstallDate"
$DCTable.Columns[7].ColumnName = "InstallDate"
 
# Loop each DC                        
ForEach($DC in $AllDCs)
{  
{
(invoke-command (Get-WmiObject Win32_OperatingSystem).ConvertToDateTime( (Get-WmiObject Win32_OperatingSystem).InstallDate )) 
}
    $ping = ping $DC.Hostname -n 1 | Where-Object {$_ -match "Reply" -or $_ -match "Request timed out" -or $_ -match "Destination host unreachable"
    }
        switch ($ping)
    {
        {$_ -like "Reply*" }                          { $PingStatus = "Success" }
        {$_ -like "Request timed out*"}               { $PingStatus = "Timeout" }
        {$_ -like "Destination host unreachable*"}    { $PingStatus = "Unreachable" }
        default                                       { $PingStatus = "Unknown" }
    }  
    
         
    $DCTable.Rows.Add(  $DC.Hostname,
                        $DC.Ipv4address,
                        $DC.isGlobalCatalog,
                        $DC.Site,
                        $DC.Forest,
                        $DC.OperatingSystem,
                        $PingStatus,
                        $InstallDate
                              
                        )| Out-Null                          
}
 
# Display results in console 
$DCTable | Sort-Object Site | Out-GridView
 
#Creating head style
$Head = @"
<style>
  body {
    font-family: "Arial";
    font-size: 8pt;
    }
  th, td, tr { 
    border: 1px solid #e57300;
    border-collapse: collapse;
    padding: 5px;
    text-align: center;
    }
  th {
    font-size: 1.2em;
    text-align: left;
    background-color: #003366;
    color: #ffffff;
    }
  td {
    color: #000000;
     
    }
  .even { background-color: #ffffff; }
  .odd { background-color: #bfbfbf; }
  h6 { font-size: 12pt; 
       font-color: black;
       font-weight: bold;
       }
 
 text { font-size: 10pt;
        font-color: black;
        }
 }
</style>
"@

CodePudding user response:

As mentioned in the comments, you need to:

  • Make sure you actually execute the Invoke-Command statement on the target DC, by:
    • Surrounding the statement in {...} (to create a scriptblock, rather than execute locally)
    • Passing -ComputerName $DC.Hostname to Invoke-Command
  • Assign the output from that call to $InstallDate

ForEach($DC in $AllDCs)
{
    $ping = ping $DC.Hostname -n 1 | Where-Object {$_ -match "Reply" -or $_ -match "Request timed out" -or $_ -match "Destination host unreachable"}
    switch ($ping)
    {
        {$_ -like "Reply*" }                          { $PingStatus = "Success" }
        {$_ -like "Request timed out*"}               { $PingStatus = "Timeout" }
        {$_ -like "Destination host unreachable*"}    { $PingStatus = "Unreachable" }
        default                                       { $PingStatus = "Unknown" }
    }  

    $InstallDate = if($PingStatus -eq 'Success'){
        Invoke-Command { (Get-WmiObject Win32_OperatingSystem).ConvertToDateTime( (Get-WmiObject Win32_OperatingSystem).InstallDate )) } -ComputerName $DC.Hostname
    }
         
    $DCTable.Rows.Add(  $DC.Hostname,
                        $DC.Ipv4address,
                        $DC.isGlobalCatalog,
                        $DC.Site,
                        $DC.Forest,
                        $DC.OperatingSystem,
                        $PingStatus,
                        $InstallDate
                              
                        )| Out-Null
    # ...

}

  • Related