-
-
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. In the New-AdhcResult you have a mandatory paramater of $SubCategory but in the main script you are not setting it to anything. so the script just stops asking for the Subcategory. Any chance you could update the main body to have this?
Hi Davey!
Removed the parameter flag so it should work as expected now.
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
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. In the New-AdhcResult you have a mandatory paramater of $SubCategory but in the main script you are not setting it to anything. so the script just stops asking for the Subcategory. Any chance you could update the main body to have this?