powershellgpo

PowerShell return a custom error message on non-terminating error based on the error type


I have a PowerShell script that I am working on and I am trying to figure out how to have it catch the non-terminating error and return a custom error message instead of the standard error message text. I am specifically concerned with 2 different errors that I expect to see based on parameters and how I can have the script return a custom error text depending on which error it is instead of returning the long system error.

Code is below

 $SG = Read-Host -Prompt 'Enter the name of the Security Group you want to get the members for'
 $GPOType = Read-Host -Prompt 'Are you Linking a User or Computer GPO - Type either User or Computer'
 $gpoName = Read-Host -Prompt 'Enter the Group Policy Name you want to Link'
 $targetGpoName = Read-Host -Prompt 'Enter the Group Policy name of the policy that you want to link new one above - For example if the Target policy link order is 10 this will put the new Policy in Link Order 10 moving the target Polciy to Link Order 11'
 $EnableLink = Read-Host -Prompt 'Enter Yes or No to enable link or not'
 $GPO = get-gpo -Name $targetGpoName


 $OUlists = get-adgroupmember -identity $SG | where-object {$_.samaccountname -notlike '*svc*' -and $_.objectclass -like $GPOType} | ForEach-Object -process {
 $DN = $_.distinguishedname; 
 $null,$trailingRDNs = $DN -split '(?<!\\),'
 $parentDNs = $trailingRDNs -join ','

 foreach ($parentDN in $parentDNs)
 {

 Write-Host "Working on ($parentDN )"
 New-GPLink -Name $gpoName -order ((Get-GPInheritance -Target $parentDN).GpoLinks | Where-Object DisplayName -eq $targetGpoName | select -expandproperty order) -Target $parentDN -LinkEnabled $EnableLink 
 }
 }

the errors I am getting as expected are as follows:

first expected error: when the target GPO isnt linked to the OU so the script cant determine the order since the target GPO isnt linked thus returning an error saying ...Cannot bind parameter 'Order' to the target. Exception setting "Order": "Cannot convert null... this is expected and is the behavior i want for this but instead of returning the full error (as seen below) i want it to just return a custom message. some thing like "GPO used for Order targeting is not linked to this OU. New GPO will Not be linked to this OU" full error:

New-GPLink : Cannot bind parameter 'Order' to the target. Exception setting "Order": "Cannot convert null to type "System.Int32"." At line:23 char:36 Name -order ((Get-GPInheritance -Target $parentDN).GpoLinks | Where-O ... CategoryInfo : WriteError: (:) [New-GPLink], ParameterBindingException FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.GroupPolicy.Commands.NewGPLinkCommand

Second Error I am getting as expected is the error when the GPO is already linked to the desired OU. again, this is an error I expect to get but also want a custom message to display something like this: "GPO is already linked to this OU"

the full error is below: New-GPLink : The GPO named 'Test-Do-Not-Use' is already linked to a Scope of Management with Path 'OU=Blah,OU=Blah,DC=Something,DC=Somewhere,DC=Sometime,DC=Here,DC=There'. At line:23 char:3 New-GPLink -Name $gpoName -order ((Get-GPInheritance -Target $paren ... CategoryInfo : InvalidArgument: (Microsoft.Group...ewGPLinkCommand:NewGPLinkCommand) [New-GPLink], ArgumentException FullyQualifiedErrorId : UnableToCreateNewLink,Microsoft.GroupPolicy.Commands.NewGPLinkCommand

I have tried incorporating the write-error "custom statement" -category InvalidArgument or Write error depending on which error i am targeting and placed it inside the foreach loop under the New-Gplink section but that didnt get me anything.

since its a non-terminating error, i dont think i can use catch.

any suggestions and help would be greatly appreciated. Thank you in advance

thanks to all for the help here is the working script

 $SG = Read-Host -Prompt 'Enter the name of the Security Group you want to get the members for'
 $GPOType = Read-Host -Prompt 'Are you Linking a User or Computer GPO - Type either User or Computer'
 $gpoName = Read-Host -Prompt 'Enter the Group Policy Name you want to Link'
 $targetGpoName = Read-Host -Prompt 'Enter the Group Policy name of the policy that you want to link new one above - For example if the Target policy link order is 10 this will put the new Policy in Link Order 10 moving the target Polciy to Link Order 11'
 $EnableLink = Read-Host -Prompt 'Enter Yes or No to enable link or not'
 $GPO = get-gpo -Name $targetGpoName

 $OUlists = get-adgroupmember -identity $SG | where-object {$_.samaccountname -notlike '*svc*' -and $_.objectclass -like $GPOType} | ForEach-Object -process {
 $DN = $_.distinguishedname; 
 $null,$trailingRDNs = $DN -split '(?<!\\),'
 $parentDNs = $trailingRDNs -join ','

 foreach ($parentDN in $parentDNs){


 Write-Host "Working on ($parentDN )"
 try {
 New-GPLink -Name $gpoName -order ((Get-GPInheritance -Target $parentDN).GpoLinks | Where-Object DisplayName -eq $targetGpoName | select -expandproperty order) -Target $parentDN -LinkEnabled $EnableLink -ErrorAction Stop 
 }catch [System.ArgumentException]{
 write-warning "GPO is already linked to this OU"
 }
 catch [System.Management.Automation.ParameterBindingException]{
 write-warning "Target GPO used for Order does not exist thus the GPO will not be linked"
 }
 }
 }

Solution

  • You can run 'New-GPLink' with '-ErrorAction SilentlyContinue -ErrorVariable err' and then see if there is an error to handle.

    Here is an example code:

    New-GPLink -Name $gpoName -order ((Get-GPInheritance -Target $parentDN).GpoLinks | Where-Object DisplayName -eq $targetGpoName | select -expandproperty order) -Target $parentDN -LinkEnabled $EnableLink -ErrorAction SilentlyContinue -ErrorVariable err
    
    if ($err.ToString() -like "*Cannot bind parameter 'Order' to the target*") {
        Write-Error -Message 'GPO used for Order targeting is not linked to this OU. New GPO will not be linked to this OU'
    } elseif ($err.ToString() -like "*The GPO named 'Test-Do-Not-Use' is already linked to a Scope of Management with Path*") {
        Write-Error -Message 'GPO is already linked to this OU'
    } else {
        Write-Error $err
    }
    

    By the way, something is confusing in your script. You are converting '$trailingRDNs' to a single string by running '$parentDNs = $trailingRDNs -join ','' and then you are running a foreach loop 'foreach ($parentDN in $parentDNs)' in '$parentDNs' which is a single string. Am I missing something?