Throw message not being shown - powershell

I'm trying to print my own error messages using throw. Consider this example:
$computerName = $env:COMPUTERNAME
$adsi = [adsi]("WinNT://$computerName")
if (!($adsi.Children.Find($userGroup, 'group')))
{
throw "User group not found."
}
If the user group is incorrect, this error message is shown:
Exception calling "Find" with "2" argument(s): The group name could not be found.
Is there a way to show my throw message, rather than the generic exception?

try this:
$computerName = $env:COMPUTERNAME
$adsi = [adsi]("WinNT://$computerName")
try {
$adsi.Children.Find($userGroup, 'group')
}
catch{
throw "User group not found."
}

[adsi] has a habit of throwing terminating errors. This happens with Get-ADUser as well. This is why capturing the error in a try/catch (like in whatever's answer) is necessary.
As an alternative you can check if the group exists by querying all local groups first and see if yours exists.
$computerName = $env:COMPUTERNAME
$adsi = [adsi]("WinNT://$computerName")
$localGroups = $adsi.children | Where-Object{$_.SchemaClassName -eq "Group"}
If($userGroup -notin $localGroups.Name){
throw "Your group is in another castle."
}
or a variant
if(-not ($adsi.children | Where-Object{$_.SchemaClassName -eq "Group" -and $_.Name -eq $userGroup})){
throw "Your group is in another castle."
}
Depending on where you are continuing with this code it might be advantageous to store this information once.

Related

Unable to catch the error using try..catch in powershell

I am trying to catch the error if DL is not found. I have written the below code
try
{
Get-DistributionGroup -Identity "#AB-TestDL"|select ManagedBy -ErrorAction Stop
}
catch
{
if($Error[0] -match "couldn't be found on")
{
Write-Host "DL not found"
}
}
But when i run the code, it throws an error as "#AB-TestDL" couldn't be found on ...
Please help me capture this error. Thanks..
Try using the -ErrorAction Stop parameter on the Get-DistributionGroup -Identity "#AB-TestDL" CmdLet instead of Select-Object.
Select-Object can be used to create a new object but it isn't a error for the CmdLet when a property does not exist.
C:\> [PSCustomObject]#{ Test = 123 } | Select Test2 -ErrorAction Stop
Test2
-----
You can however make it work different (while i still suggest moving -ErrorAction Stop to the first CmdLet):
Set-StrictMode -Version 3
$Object = [PSCustomObject] #{
Test = 123
}
try {
$null = $Object.Test2
} catch {
throw "I don't extist and catch because of strictmode version 3"
}
Just an idea which came into my head. I actually never used strictmode this way.

Powershell try/catch/finally isn't executing right (or I've completely hosed it)

I have a script that checks for cyclic groups.
The script takes all groups in a domain (parent groups), checks the membership of those groups and adds any member with an objectClass of 'group' to an array (child groups).
The script then checks the child groups to see if the parent is a member of the child (yeah, it's allowed but still not a good idea).
I added a try/catch/finally block so I could get the actual group names instead of the truncated error message that PowerShell returns.
The problem is, the script stops at the first error it encounters instead of continuing on.
This is the first try/catch I've done, so please bear with me.
Here's the script:
$original_ErrorActionPreference = 'Continue'
$ErrorActionPreference = 'Stop'
Import-Module -Name ActiveDirectory
$domains = #('corp.com', 'dom1.corp.com', 'dom2.corp.com')
foreach($domain in $domains){
Write-Host $domain -ForegroundColor Yellow
$parents = Get-ADGroup -server $domain -Properties name,objectclass -Filter * #get all domain groups
write-host $parents.count
$table = #()
$pGroupCount = #($parents).Count
$record = #{
'Parent' = ''
'Child' = ''
'Nester' = ''
}
foreach($parent in $parents){
Write-Host $parent.name -ForegroundColor Green
The script works up to this point.
This is the part that fails-
try { #get members in the parent that are groups
$children = Get-ADGroupMember -Identity $parent | Where-Object{$_.ObjectClass -eq 'group'} | Select-Object name,distinguishedName,objectClass
} catch [Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember]{
Write-Host $parent.name ' must be checked manually' -ForegroundColor blue -BackgroundColor Yellow
$parent.distinguishedName | Out-String -Width 4096 | Out-File -FilePath "$env:USERPROFILE\desktop\$domain-manualCheck.txt" -Width 5120 -Append
} finally {
$pGroupCount = $pGroupCount - 1
write-host $children.count ' - ' $children.name -ForegroundColor Gray
Write-Host $pGroupCount ' groups to go' -foregroundColor yellow
foreach($child in $children){ #get members in the children that are groups AND that have the same name as the parent
$nested = Get-ADGroupMember $child.name | Where-Object {$_.objectClass -eq 'group' -and $_.name -eq $parent.name}
$nestedCount = #($nested).count
if ($nestedCount -gt 0){
foreach($nester in $nested){
Write-Host $parent.name -ForegroundColor White
Write-Host $nestedCount -ForegroundColor Magenta
Write-Host $nester.name -ForegroundColor Cyan
$record.'Parent' = $parent.name
$record.'Child' = $child.name
$record.'Nester' = $nester.name
$objRecord = New-Object psobject -Property $record
$table += $objRecord
}
}
}
$table | Export-Csv -Path "$env:USERPROFILE\desktop\$domain-Group-Report.csv" -NoTypeInformation
$error | out-string -width 4096 | Out-File -FilePath "$env:USERPROFILE\desktop\$domain-Errors.txt" -Width 5120 -Append
}
}
}
$ErrorActionPreference = $original_ErrorActionPreference
As soon as the script hits the first group that has an issue, this is the error that's returned (#comments are added):
PS C:\Users\admin_j\Desktop> .\gtest.ps1
corp.com #current domain
283 #total group count
Exchange Servers #current group
6 - Exchange Install Domain Servers Exchange Install Domain Servers Exchange Install Domain Servers Exchange Install Domain Servers Exchange Install Domain Servers #6 groups within the parent, groups are from sub-domains
Exchange Install Domain Servers
282 groups to go
Get-ADGroupMember : Cannot find an object with identity: 'Exchange Install Domain Servers' under: 'DC=corp,DC=com'.
At C:\Users\admin_j\Desktop\gtest.ps1:46 char:15
+ $nested = Get-ADGroupMember $child.name | Where-Object $_.objectClass -eq ' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Exchange Install Domain Servers:ADGroup) [Get-ADGroupMember], ADIdentityNotFoundException
+ FullyQualifiedErrorId : Cannot find an object with identity: 'Exchange Install Domain Servers' under: 'DC=corp,DC=com'.,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
Why, instead of writing the bad group (in this case 'Exchange Install Domain Servers' under: 'DC=corp,DC=com'.) to a file, did the script stop? The group does indeed exist.
Should I add another block to catch any 'object not found' errors and send those to a file?
Thank you!
As Will's comment implies, you have indeed hosed your catch clause by specifying a type literal not matching an exception you'd ever expect thrown.
The general syntax for a catch clause is as follows
catch [catch-type-list] <statement block>
Where [catch-type-list] is an optional list of exception types that the associated statement block will act as an exception handler for.
That means, that this catch clause:
catch [Microsoft.ActiveDirectory.Management.Commands.GetADGroupMem‌​ber] {
# ...
}
Will only ever handle errors caused by an exception of the type [Microsoft.ActiveDirectory.Management.Commands.GetADGroupMem‌​ber] - this is of course not an exception type, and so the associated statement block will never execute.
In order for your catch clause to make sense in this context, specify a relevant exception type:
try{
Get-ADGroupMember -Identity $parent
}
catch [Microsoft.ActiveDirectory.Management.ADServerDownException]{
# DC is unreachable, abort
}
catch [Microsoft.ActiveDirectory.Management.ADIdentityResolutionException]{
# Group identity not resolved, add to list and continue
}
catch {
# Something else, completely unforeseen, happened, you might want to re-throw and return from your function
}
The last catch clause, in which the type list has been omitted is known as a general catch clause, and will handle any exception that didn't match any of the preceding catch clauses.

Powershell Remove members from DLs says not there, but they are

I have a powershell script that is supposed to empty a distribution list. It gets the member list into an array. It then pipes the array into Remove-DistributionGroupMember. Each run will have some members throw 'X isn't a member of the group Y' errors. At the end of the loop, I re-enumerate the users and for everyone that 'isn't a member of the group' error got thrown, is still a member of the group. This is not consistent. Sometimes everything works, but usually there are different members of the group that fail.
$grp = (Get-DistributionGroup -Identity:$DLIST -ErrorAction:Stop)
$members = (Get-DistributionGroupMember -Identity:$grp -ErrorAction:Stop)
$members | % {
$member = $_
try {
Remove-DistributionGroupMember -Identity:$grp -Member:$_ -Confirm:$false -WarningAction:Stop -ErrorAction:Stop
}
catch {
$LogStream.WriteLine((Get-Date).toString() + " Error removing ${member}:`n" + $_.toString())
}
}
$members = (Get-DistributionGroupMember -Identity:$grp -ErrorAction:Stop)
write-host "Users in List:"
$members | % { $LogStream.WriteLine(" " + $_.ToString())}
3/20/2015 5:06:55 AM Error removing xxxxx.xxxx.com/North America/Spokane/Users/XXXXXX:
The recipient "xxxx.xxxx.com/North America/Spokane/Users/XXXXX" isn't a member of the group "CN=*YYYYY,OU=IT,DC=xxxxxxx,DC=xxxx,DC=com".
Users in List:
xxxxx.xxxx.com/North America/Spokane/Users/XXXXXX
Try adding this to the beginning of your script:
Set-ADServerSettings -ViewEntireForest $true
And I would also add the -ResultSize "Unlimited" to your Get- commands.

Suppress Exception in Office365 powershell

I have a script which adds members of an Active Directory group to an Office 365 distribution group. Many members of the AD group will also be members of the distribution group already, which causes the script to display the error:
Adding user#domain.com to distribution group GROUP
The recipient "user#domain.com" is already a member of the group "GROUP".
+ CategoryInfo : NotSpecified: (user#domain.com:RecipientWithAdUserGroupIdParameter`1)
[Add-DistributionGroupMember], MemberAlreadyExistsException
+ FullyQualifiedErrorId : [Server=HKNPR04MB0531,RequestId=84dc77fb-8cf4-4e2f-882e-0ce66b735d08,TimeStamp=9/02/2015 6:55:13 AM] [FailureCategory=Cmdlet-MemberAlreadyExistsException] 7CEFF683,Microsoft.Exchange.Management.RecipientTasks.AddDistributionGroupMember
+ PSComputerName : pod51055psh.outlook.com
I would like to suppress these errors, as I don't care if the members already exist.
I have tried catching the MemberAlreadyExistsException, setting -ErrorAction SilentlyContinue and catching all errors and writing "Error!" instead of the actual exception, however this does not seem to have taken effect.
Currently, my Try-Catch block looks like this:
try
{
Add-DistributionGroupMember -Identity $DistributionGroupName -Member $MemberEmail
}
Catch [System.Management.Automation.RemoteException]
{
if($_.FullyQualifiedErrorId -match 'AlreadyExists')
{
Write-Output "`t $emailaddress is already a member of $DistributionGroupName."
}
else
{
Write-Output "`t $_.Exception"
}
}
I believe that this should alert me when a user already exists, however I still receive an exception message.
Thanks to #mjolinor, I was able to catch the exception and provide a more user-friendly message. My corrected code is below:
try
{
Add-DistributionGroupMember -Identity $DistributionGroupName -Member $EmailAddress -ErrorAction Stop
}
Catch [System.Exception]
{
if($_.FullyQualifiedErrorId -match 'AlreadyExists')
{
Write-Output "`t $emailaddress is already a member of $DistributionGroupName."
}
else
{
Write-Output "`t $_.Exception"
}
}
I added the -ErrorAction Stop as suggested, which allowed me to Catch the exception. I also modified the exception type to catch all exceptions. Interestingly (in my opinion), the Catch block failed if I did not put an exception type in there.
Program output is now:
Adding user#domain.com to distribution group GROUP
user#domain.com is already a member of GROUP.

Checking if Distribution Group Exists in Powershell

I am writing a script to quickly create a new distribution group and populate it with a CSV. I am having trouble testing to see if the group name already exists.
If I do a get-distributiongroup -id $NewGroupName and it does not exist I get an exception, which is what I expect to happen. If the group does exist then it lists the group, which is also what I expect. However, I can not find a good way to test if the group exists before I try to create it. I have tried using a try/catch, and also doing this:
Get-DistributionGroup -id $NewGroupName -ErrorAction "Stop"
which makes the try/catch work better (as I understand non-terminating errors).
Basically, I need to have the user enter a new group name to check if it is viable. If so, then the group gets created, if not it should prompt the user to enter another name.
You can use SilentlyContinue erroraction so that no exception/error shows:
$done = $false
while(-not $done)
{
$newGroupName = Read-Host "Enter group name"
$existingGroup = Get-DistributionGroup -Id $newGroupName -ErrorAction 'SilentlyContinue'
if(-not $existingGroup)
{
# create distribution group here
$done = $true
}
else
{
Write-Host "Group already exists"
}
}
This should do the trick:
((Get-DistributionGroup $NewGroupName -ErrorAction 'SilentlyContinue').IsValid) -eq $true