Issue in AD Diagnosis Report

This topic contains 8 replies, has 3 voices, and was last updated by  Sethuraman 1 day, 21 hours ago.

  • Author
    Posts
  • #87806

    Sethuraman
    Participant

    Hi i am trying to generate AD Diagnosis using dcdiag and exporting to xml. but while taking the data from xml is where the problem lies. I am following don jones method of "create html reports in powershell book". Please check the code below and help, in my script i cant get any output for Diagnosis Module. its blank while i can get out put services. Please help me.

    Import-Module ActiveDirectory
    ############# Fucntion for creating log file if not exist ##############

    $global:logPath = $null

    $ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path

    function New-Log($dir,$file)
    {
    $logDirectory = $dir
    $logFolder = Get-Date -Format dd_MMM_yyyy
    $logFileDate = Get-Date -uFormat "%d%m%Y_%S"
    $logFileName = "$file" + "_" + "$logFileDate" + ".log"
    $logFolderPath = "$logDirectory" + "\" + "LOG" + "\" + "$logFolder"
    $logFilePath = $logFolderPath + "\" +$logFileName
    $logPathExistence1 = Test-Path -Path $logFolderPath
    $logPathExistence2 = Test-Path -Path $logFilePath
    if (!$logPathExistence1)
    {
    $folderCreation = New-Item $logFolderPath -Type directory
    }

    if (!$logPathExistence2)
    {
    $fileCreation = New-Item $logFilePath -Type file
    }

    $global:logPath = $logFilePath
    }

    ###################### Function for writing logs ############################
    # #
    # There are 3 types of logs(0-Info, 1-Warning, 2-Error). #
    # Based on the log type It will appaned Date, Type and Message to log. #
    # #
    #############################################################################

    function Write-Log($message, $type)
    {
    if($Type -eq 0)
    {
    $Date = Get-Date
    $Log = "[" + $Date + "]" + "[Info] " + $Message
    $Log >> $global:logPath
    }
    elseif($Type -eq 1)
    {
    $Date = Get-Date
    $Log = "[" + $Date + "]" + "[Warning] " + $Message
    $Log >> $global:logPath
    }
    elseif($Type -eq 2)
    {
    $Date = Get-Date
    $Log = "[" + $Date + "]" + "[Error] " + $Message
    $Log >> $global:logPath
    }
    else
    {
    $Date = Get-Date
    $Log = "[" + $Date + "]" + "[Others] " + $Message
    $Log >> $global:logPath
    }
    }
    Import-Module $ScriptDir\EnhancedHTML2.ps1
    ###################### Function for Creating ServiceCheck Output Folder ############################

    function Create-Output($dir)
    {
    $directory = $dir
    $folder = Get-Date -Format dd_MMM_yyyy
    $outFolderPath = "$directory" + "\" + "OUTPUT" + "\" + "$folder"
    $pathExistence = Test-Path -Path $outFolderPath
    if (!$pathExistence)
    {
    $folderCreation = New-Item $outFolderPath -Type directory
    }
    $global:outFolderPath = $outFolderPath
    }

    New-Log "$ScriptDir" "AD_Health_Check"

    Create-Output "$ScriptDir"

    ###################### Function for Reading the inputs from input.conf file ############################

    if (Test-Path -Path "$ScriptDir\input.conf"){
    Get-Content "$ScriptDir\input.conf" | foreach-object -begin {
    $h=@{}
    } -process {
    $k = [regex]::split($_,'=');
    if(($k[0].CompareTo("") -ne 0) -and ($k[0].StartsWith("[") -ne $True))
    {
    $h.Add($k[0], $k[1])
    }
    }

    $ComputerList=$h.Servers.Split(",")
    $ADService=$h.ServiceNames.Split(",")
    $To=$h.To
    $From=$h.From
    $Subject=$h.Subject
    $Signature=$h.Signature
    $SMTPMail=$h.SMTPMailServer

    }else{
    Write-Log "Input.conf file not exits"
    Exit
    }

    #CSS format for the report
    $Style =@"

    body{
    color:#333333;
    font-family:calibri,Tahoma;
    font-size : 10pt;
    }

    h1{
    text-align:center;
    color:#1B4F72;
    }

    h2{
    border-top:1px solid #666666;
    color:#1B4F72;
    }

    th{
    font-weight:bold;
    color:#eeeeee;
    background-color:#1B4F72;
    cursor:pointer;
    }

    .odd {background-color:#ffffff;}

    .even {background-color:#dddddd;}

    .paginate_enabled_next, .paginate_enabled_previous
    {
    cursor:pointer;
    border:1px solid #222222;
    background-color:#dddddd;
    padding:2px;
    margin:4px;
    border-radius:2px
    }

    .paginate_disabled_previous, .paginate_disabled_previous
    {
    color:#666666;
    cursor:pointer;
    background-color:#dddddd;
    padding:2px;
    margin:4px;
    border-radius:2px
    }

    .dataTables_info {margin-bottom:4px;}

    .sectionheader {cursor:pointer;}

    .secrtionheader:hover {color:red;}

    .grid {width:80%}

    .red{
    color:red;
    font-weight:bold;
    }

    .green{
    color:green;
    font-weight:bold;
    }

    "@

    #Fucntion to get AD Services
    Function Get-checkservice{
    [cmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][String]$ComputerName
    )
    foreach($DCservice in $ComputerList){
    foreach($include in $ADService){
    $SV=Get-WmiObject -Class win32_service -ComputerName $DCservice -Filter "Name='$include'"
    $props = @{'ServiceName'=$sv.name;
    'DisplayName'=$sv.displayname;
    'Status'=$sv.status;
    'ServerName' =$sv.PSComputerName;}
    New-Object -TypeName PSObject $props}}
    }

    Function Get-ADreplication{
    [cmdletBinding()]
    param(
    [Parameter(Mandatory=$True)][String]$ComputerName
    )
    foreach($replication in $ComputerList){
    $repinfo= repadmin /replsum * /bysrc /bydest /sort:delta
    $props= @{'DSAType'=$repinfo.DSAType;
    'HOSTNAME'=$repinfo.hostname;
    'Delta'=$repinfo.Delta;
    'Fails'=$repinfo.Fails;
    'Slash'=$repinfo.slash;
    'Total'=$repinfo.Total;
    'PctError'=$repinfo.PcTError;
    'ErrorMessage'=$repinfo.ErrorMsg;}
    New-Object -TypeName PSObject $props}

    }

    Function Get-ADDiagnosis{

    dcdiag.exe /test:dns /v /e /x:$ScriptDir\dcdiag.xml /e

    [System.Xml.XmlDocument]$XD = new-object System.Xml.XmlDocument
    $XD.Load("$ScriptDir\dcdiag.xml") | gm
    ForEach ($Element in $XD.DCDIAGTestResults.DNSEnterpriseTestResults.Summary.Domain.DC)
    {
    ForEach ($Test in $Element){
    $props= @{
    'DC'= $Element.Name
    'Authentication'=$Test.status;
    'Basic'=$Test.status;
    'Forwarders'=$Test.status;;
    'Delegation'=$Test.status;
    'DynamicUpdate'=$Test.status;
    'RecordRegistration'=$Teststatus;
    'ExternalNameResolution'=$Test.status;}}
    New-Object -TypeName PSObject $props}
    }

    foreach($computer in $ComputerList){
    try{
    $reachable = $true
    Write-output "Checking Connectivity to $computer"
    Get-WmiObject -Class win32_bios -ComputerName $computer | Out-Null
    }catch{
    Write-Warning "$computer connectivity failed"
    $reachable = $false
    }
    if($reachable){

    $params = @{'As'='Table';
    'Precontent'='♦ AD Service Check';
    'EvenRowCssClass'='even';
    'OddRowCssClass'='odd';
    'MakeTableDynamic'=$True;
    'TableCssClass'='grid';
    'Properties'='ServiceName','DisplayName','Status',@{n='ServerName';e={$_.Servername}}}
    $html_Service = Get-checkservice -ComputerName $computer | ConvertTo-EnhancedHTMLFragment @params

    $params = @{'As'='Table';
    'Precontent'='♦ AD Replication Report';
    'EvenRowCssClass'='even';
    'OddRowCssClass'='odd';
    'MakeTableDynamic'=$True;
    'TableCssClass'='grid';
    'Properties'='DSAType','HOSTNAME','Delta','Fails','Slash','Total','PCTError','ErrorMessage'}
    $html_replication = Get-ADreplication -ComputerName $computer | ConvertTo-EnhancedHTMLFragment @params

    $params = @{'As'='Table';
    'Precontent'='♦ AD Diagnosis Report';
    'EvenRowCssClass'='even';
    'OddRowCssClass'='odd';
    'MakeTableDynamic'=$True;
    'TableCssClass'='grid';
    'Properties'='DC','Authentication','Basic','Forwarders','Delegation','DynamicUpdate','RecordRegistration','ExternalNameResolution'}
    $html_diagnosis = Get-ADDiagnosis | ConvertTo-EnhancedHTMLFragment @params

    #Assembling the final html report
    $params = @{'CssStyleSheet'=$Style;
    'Title'="Server Health check";
    'PreContent'="Active Directory Health Check"
    'HTMLFragments'=@($html_Service,$html_replication,$html_diagnosis)
    'jQueryDataTableUri'='C:\html\jquerydatatable.js';
    'jQueryUri'='C:\html\jQuery.js'}
    $windowsHealth=ConvertTo-EnhancedHTML @params | Out-File -FilePath "$outFolderPath\AD_Health_Check.html"
    }}

  • #87968

    Des Davies
    Participant

    I found a few errors in your Get-ADDiagnostics function. The most obvious is the missing or extra ; within the hashtable. However, the bigger issue was with how you were accessing the elements in the XML. The status for each test was in an element under the "Test" property. Also, each test type needed to be accessed via an array index.

    Final note, I added a test to see if the xml file existed, and deleted it, if it did. (If it exists the output from dcdiag fails. I finally added the "/S:DCNAME" parameter to dcdiag so you can run this from something other than a DC. (You could use "Get-ADDomainController" to get this programatically rather than manually code it).

    Here is what I came up with. Let me know if anything needs clarification.

    Function Get-ADDiagnosis{
        $ScriptDir = "C:\Scripts"
        
        If (Test-Path $ScriptDir\dcdiag.xml) {
            Remote-Item $ScriptDir\dcdiag.xml
        }
    
        dcdiag.exe /test:dns /v /e /x:$ScriptDir\dcdiag.xml /S:DCSERVER /e
        
        [System.Xml.XmlDocument]$XD = new-object System.Xml.XmlDocument
        $XD.Load("$ScriptDir\dcdiag.xml")
    
        ForEach ($Element in $XD.DCDIAGTestResults.DNSEnterpriseTestResults.Summary.Domain.DC)
        {
            $props= @{
                'DC'= $Element.Name
                'Authentication'=$Element.Test.Status[0];
                'Basic'=$Element.Test.Status[1];
                'Forwarders'=$Element.Test.Status[2];
                'Delegation'=$Element.Test.Status[3];
                'DynamicUpdate'=$Element.Test.Status[4];
                'RecordRegistration'=$Element.Test.Status[5];
                'ExternalNameResolution'=$Element.Test.Status[6]
            }
            New-Object -TypeName PSObject $props
        }
    }
    
    • #88838

      Sethuraman
      Participant

      Thank you des davis, your answer helped me, now its working.

  • #87986

    postanote
    Participant

    Also, what are these all about???
    'Precontent'='♦
    Remove the 'diamond symbol' to make sure that is not causing issues.
    Yet. it just may be a issue when you copied and pasted here, but just to be sure.

    • #88816

      Sethuraman
      Participant

      Those diamonds are html code with i have used in the code, it will come as diamond symbol before the heading like bullet points.when i paste here and post the reply those html codes are compiled

  • #88813

    Sethuraman
    Participant

    Hi Des Davis,

    I tried that, i am still getting empty output, am i missing something?

  • #88817

    Sethuraman
    Participant

    This is the xml i am trying to get the data from, when i give $Element.DC i get its value as 'ACTIVEDIRECTORY', but when i try your code $Element.Test.state[x] i dont get any value in my html report





    • #88820

      Sethuraman
      Participant


      #-
      #-
      #-
      #-
      #
      #
      #
      #
      #
      #
      #
      #
      #
      #

    • #88822

      Sethuraman
      Participant

      DCDIAGTestResults
      DNSEnterpriseTestResults
      Summary
      Domain Name="simlab"
      DC Name="ACTIVEDIRECTORY"
      Test Name="Authentication" Status="PASS"
      Test Name="Basic" Status="PASS"
      Test Name="Forwarders" Status="FAIL"
      Test Name="Delegation" Status="PASS"
      Test Name="DynamicUpdate" Status="PASS"
      Test Name="RecordRegistration" Status="PASS"
      Test Name="ExternalNameResolution" Status="N-A"
      /DC
      /Domain
      /Summary

You must be logged in to reply to this topic.