-
-
Save AlexAsplund/c98bd06484d87a6e67a4250a182f1f49 to your computer and use it in GitHub Desktop.
Class AdhcResult { | |
[string]$Source | |
[string]$TestName | |
[bool]$Pass | |
$Was | |
$ShouldBe | |
[string]$Category | |
[string]$Message | |
$Data | |
[string[]]$Tags | |
} | |
Function New-AdhcResult { | |
[cmdletbinding()] | |
param( | |
# Source of the result. The computer that was tested | |
[parameter(ValueFromPipelineByPropertyName)] | |
[string]$Source = $env:COMPUTERNAME, | |
# Name of the test | |
[parameter(Mandatory,ValueFromPipelineByPropertyName)] | |
[string]$TestName, | |
# True = Test pass | |
[parameter(Mandatory,ValueFromPipelineByPropertyName)] | |
[bool]$Pass, | |
[parameter(ValueFromPipelineByPropertyName)] | |
$Was, | |
[parameter(ValueFromPipelineByPropertyName)] | |
$ShouldBe, | |
# General category of the test. Like "Directory Services" or "DNS" | |
[parameter(Mandatory,ValueFromPipelineByPropertyName)] | |
[string]$Category, | |
# A more specific subcategory like "FSMO" or "DNS Forwarding" | |
[parameter(ValueFromPipelineByPropertyName)] | |
[string]$SubCategory, | |
# Tags for this test like "Security", "Updates", "Logon" | |
[parameter(Mandatory,ValueFromPipelineByPropertyName)] | |
[string[]]$Tags, | |
# General message | |
[parameter(ValueFromPipelineByPropertyName)] | |
[string]$Message, | |
# Extra data to the test result. Like accountnames or SPN's etc. | |
[parameter(ValueFromPipelineByPropertyName)] | |
$Data | |
) | |
Begin { | |
} | |
Process { | |
[AdhcResult]@{ | |
Source = $Source | |
TestName = $TestName | |
Pass = $Pass | |
Was = $Was | |
ShouldBe = $ShouldBe | |
Category = $Category | |
SubCategory = $SubCategory | |
Message = $Message | |
Data = $Data | |
Tags = $Tags | |
} | |
} | |
End { | |
} | |
} | |
Function Test-AdhcDCDiag { | |
[cmdletbinding()] | |
param( | |
# Name of the DC | |
[parameter(ValueFromPipeline)] | |
[string]$ComputerName, | |
# What DCDiag tests would you like to run? | |
[ValidateSet( | |
"All", | |
"Advertising", | |
"DNS", | |
"NCSecDesc", | |
"KccEvent", | |
"Services", | |
"NetLogons", | |
"CrossRefValidation", | |
"CutoffServers", | |
"CheckSecurityError", | |
"Intersite", | |
"CheckSDRefDom", | |
"Connectivity", | |
"SysVolCheck", | |
"Replications", | |
"ObjectsReplicated", | |
"DcPromo", | |
"RidManager", | |
"Topology", | |
"MachineAccount", | |
"LocatorCheck", | |
"OutboundSecureChannels", | |
"RegisterInDNS", | |
"VerifyEnterpriseReferences", | |
"KnowsOfRoleHolders", | |
"VerifyReplicas", | |
"VerifyReferences" | |
)] | |
[string[]]$Tests = "All", | |
# Excluded tests | |
[ValidateSet( | |
"Advertising", | |
"DNS", | |
"NCSecDesc", | |
"KccEvent", | |
"Services", | |
"NetLogons", | |
"CrossRefValidation", | |
"CutoffServers", | |
"CheckSecurityError", | |
"Intersite", | |
"CheckSDRefDom", | |
"Connectivity", | |
"SysVolCheck", | |
"Replications", | |
"ObjectsReplicated", | |
"DcPromo", | |
"RidManager", | |
"Topology", | |
"MachineAccount", | |
"LocatorCheck", | |
"OutboundSecureChannels", | |
"RegisterInDNS", | |
"VerifyEnterpriseReferences", | |
"KnowsOfRoleHolders", | |
"VerifyReplicas", | |
"VerifyReferences" | |
)] | |
[string[]]$ExcludedTests | |
) | |
Begin { | |
$DCDiagTests = @{ | |
Advertising = @{} | |
CheckSDRefDom = @{} | |
CheckSecurityError = @{ | |
ExtraArgs = @( | |
"/replsource:$((Get-ADDomainController -Filter *).HostName | ? {$_ -notmatch $env:computername} | Get-Random)" | |
) | |
} | |
Connectivity = @{} | |
CrossRefValidation = @{} | |
CutoffServers = @{} | |
DcPromo = @{ | |
ExtraArgs = @( | |
"/ReplicaDC", | |
"/DnsDomain:$((Get-ADDomain).DNSRoot)", | |
"/ForestRoot:$((Get-ADDomain).Forest)" | |
) | |
} | |
DNS = @{} | |
SysVolCheck = @{} | |
LocatorCheck = @{} | |
Intersite = @{} | |
KccEvent = @{} | |
KnowsOfRoleHolders = @{} | |
MachineAccount = @{} | |
NCSecDesc = @{} | |
NetLogons = @{} | |
ObjectsReplicated = @{} | |
OutboundSecureChannels = @{} | |
RegisterInDNS = @{ | |
ExtraArgs = "/DnsDomain:$((Get-ADDomain).DNSRoot)" | |
} | |
Replications = @{} | |
RidManager = @{} | |
Services = @{} | |
Topology = @{} | |
VerifyEnterpriseReferences = @{} | |
VerifyReferences = @{} | |
VerifyReplicas = @{} | |
} | |
$TestsToRun = $DCDiagTests.Keys | Where-Object {$_ -notin $ExcludedTests} | |
If($Tests -ne 'All'){ | |
$TestsToRun = $Tests | |
} | |
if(($Tests | Measure-Object).Count -gt 1 -and $Tests -contains "All"){ | |
Write-Error "Invalid Tests parameter value: You can't use 'All' with other tests." -ErrorAction Stop | |
} | |
Write-Verbose "Executing tests: $($DCDiagTests.Keys -join ", ")" | |
} | |
Process { | |
if(![string]::IsNullOrEmpty($ComputerName)) { | |
$ServerArg = "/s:$ComputerName" | |
} | |
else { | |
$ComputerName = $env:COMPUTERNAME | |
$ServerArg = "/s:$env:COMPUTERNAME" | |
} | |
Write-Verbose "Starting DCDIAG on $ComputerName" | |
$TestResults = @() | |
$TestsToRun | Foreach { | |
Write-Verbose "Starting test $_ on $ComputerName" | |
$TestName = $_ | |
$ExtraArgs = $DCDiagTests[$_].ExtraArgs | |
if($_ -in @("DcPromo", "RegisterInDNS")){ | |
if($env:COMPUTERNAME -ne $ComputerName){ | |
Write-Verbose "Test cannot be performed remote, invoking dcdiag" | |
$Output = Invoke-Command -ComputerName $ComputerName -ArgumentList @($TestName,$ExtraArgs) -ScriptBlock { | |
$TestName = $args[0] | |
$ExtraArgs = $args[1] | |
dcdiag /test:$TestName $ExtraArgs | |
} | |
} | |
else { | |
$Output = dcdiag /test:$TestName $ExtraArgs | |
} | |
} | |
else { | |
$Output = dcdiag /test:$TestName $ExtraArgs $ServerArg | |
} | |
$Fails = ($Output | Select-String -AllMatches -Pattern "fail" | Measure-Object).Count | |
$Passes = ($Output | Select-String -AllMatches -Pattern "passed" | Measure-Object).Count | |
$Pass = ($Fails -eq 0 -and $Passes -gt 0) | |
$ResultSplat = @{ | |
Source = $ComputerName | |
TestName = "$_" | |
Pass = ($Fails -eq 0 -and $Passes -gt 0) | |
Was = $Fails,$Passes | |
ShouldBe = 0,0 | |
Category = "DCDIAG" | |
Message = "$Output[-1]" | |
Data = $Output | |
Tags = @('DCDIAG',$_) | |
} | |
New-AdhcResult @ResultSplat | |
} | |
$TestResults | |
} | |
End { | |
} | |
} |
Hi Alex,
I am running this in a test environment on a Windows Server 2016 Std,
here is the error I am getting:
Cannot create object of type "AdhcResult". The SubCategory property was not found for the AdhcResult object. The available property is: [Source <System.String>] , [TestName <System.String>] , [Pass <System.Boolean>] , [Was <System.Object>] , [ShouldBe <System.Object>] , [Category <System.String>] , [Message <System.String>] , [Data <System.Object>] , [Tags <System.String[]>] At E:\Powershell\AD HealthCheck\Test-AdhcDcDiag.ps1:62 char:9
[AdhcResult]@{
~~~~~~~~~~~~~~
- CategoryInfo : InvalidArgument: (:) [], RuntimeException
- FullyQualifiedErrorId : ObjectCreationError
This is solved when you use this Class in the beginning of the script:
Class AdhcResult { [string]$Source [string]$TestName [bool]$Pass $Was $ShouldBe [string]$Category [string]$SubCategory [string]$Message $Data [string[]]$Tags }
Following on from what @Raffytje found, it was still generating the same error for me, until I saw the SubCategory property was missing.
Fixed class is below.
Class AdhcResult {
[string]$Source
[string]$TestName
[bool]$Pass
$Was
$ShouldBe
[string]$Category
[string]$SubCategory
[string]$Message
$Data
[string[]]$Tags
}
Hi Alex,
I am running this in a test environment on a Windows Server 2016 Std,
here is the error I am getting:
Cannot create object of type "AdhcResult". The SubCategory property was not found for the AdhcResult object. The available property is: [Source <System.String>] ,
[TestName <System.String>] , [Pass <System.Boolean>] , [Was <System.Object>] , [ShouldBe <System.Object>] , [Category <System.String>] , [Message <System.String>] , [Data
<System.Object>] , [Tags <System.String[]>]
At E:\Powershell\AD HealthCheck\Test-AdhcDcDiag.ps1:62 char:9