PowerShell try-catch exit loop before second try occurs - powershell

I'm trying to loop a list of users where it is unknown if it contains English or Swedish and in addition to this check I need to know if there is an account called "CMG*" before executing the main task.
The problem is that my first 'Try' runs the lines as expected but the second one is ignored, so it apparently exit the loop on 'continue' it seems.
Can you not have 2 sets of 'Try-Catch' inside an 'if' statement?
What I have tried is to flip the two sets of 'Try-Catch' and it results in whatever is first in the loop execute and the bottom one is ignored.
foreach($User in $Users){
if($User."ADattribute"){
try {
if(!(Get-MailboxFolderPermission -Identity "$($User.UserPrincipalName):\Calendar" | Where-Object User -like 'CMG*')){
Add-MailboxFolderPermission -Identity "$($User.UserPrincipalName):\Calendar" -User <SecretUser> -AccessRights Reviewer
}
continue
}
catch [System.Management.Automation.RemoteException] {
Write-Host ":\Calendar could not be found"
}
try {
if(!(Get-MailboxFolderPermission -Identity "$($User.UserPrincipalName):\Kalender" | Where-Object User -like 'CMG*')){
Add-MailboxFolderPermission -Identity "$($User.UserPrincipalName):\Kalender" -User <SecretUser> -AccessRights Reviewer
}
continue
}
catch [System.Management.Automation.RemoteException] {
Write-Host ":\Kalender could not be found."
}
}
}

I think you are missing the function of the keyword continue. When executing the continue keyword, the current iteration stops and it continues with the next iteration. So I think if you remove the continue keyword(s) that your script will work as excepted.
https://devblogs.microsoft.com/scripting/powershell-looping-the-continue-statement/

Related

handle ADIdentityNotFoundException without stopping the program

I have to loop for each object in an input file, doing a Get-ADUser on each object, and I want to handle the ADIdentityNotFoundException error without stopping the loop. Is there a better way I can accomplish this (simplified for example's sake):
Import-Csv $input | Foreach-Object {
$manager = "BLANK"
if ($user = Get-ADUser $_."samaccountname" -properties * ) {
# I don't think I need this in an IF{} since the line below won't work
# so $manager will be equal to the last value set, "BLANK", but
# this makes it easier to understand what I want to happen
$manager = $user."manager"
# I need more properties (thus -properties *) but again just an example
}
}
In essence, if the Get-ADUser lookup is successful, set $manager = $user."manager"
If it is not successful, do not stop the loop, do not copy the value of the previous user, have $manager = "BLANK"(or whatever). The issue I have with the try/catch solutions, is that ADIdentityNotFoundException doesn't trigger the catch unless I add -ErrorAction Stop, which will cause the undesired result of the program terminating.
I'm not sure why your program would be terminating. Using the below sample code loops through all the users in the array. I have purposely entered an incorrect username into the second value of the array (position [1]):
$users = "username1", "username2", "username3" #username2 is purposely incorrect
foreach ($i in $users){
try{
$user = Get-ADUser -Identity $i -Properties * -ErrorAction Stop
Write-Host "Found"
}catch{
Write-Host "Not found"
}
}
my output is
found
not found
found

Exception Handling with AD PowerShell

I am building a PowerShell script to create AD Groups (Global and DomainLocal) by Importing their names from a Csv file.
I am having a hard time handling exceptions that will be generated in case Groups already exist.
What I want to achieve is if the Groups do not exist by the name in Csv then PS should create them and show message "Groups have been created" and if they already exist then it should display "Groups already exist" line by line so that if one exists and the other one doesn't then it should display the corresponding message.
What is happening is that PS doesn't display a message when it has created groups and when exception does occur it displays message only for Global Group not Local.
Please advise
Here's the code -
Try {
New-ADGroup -Name TestGlobal -GroupCategory Security -GroupScope Global -ManagedBy TEMP01 -Description "Owner is TEMP01" -Path (Some OU)
} Catch [Microsoft.ActiveDirectory.Management.ADException] {
if ($_ -like "The specified group already exists") {
Write-Host “!!! GLOBAL GROUP ALREADY EXISTS !!!”
} elseif ($_ -eq $null) {
Write-Host " GLOBAL GROUP CREATED SUCCESSFULLY "
}
}
Try {
New-ADGroup -Name TestLocal -GroupCategory Security -GroupScope DomainLocal -ManagedBy TEMP02 -Description "Owner is TEMP02" -Path (Some OU)
} Catch [Microsoft.ActiveDirectory.Management.ADException] {
if ($_ -like "The specified group already exists") {
Write-Host “!!! LOCAL GROUP ALREADY EXISTS !!!”
} elseif ($_ -eq $null) {
Write-Host " LOCAL GROUP CREATED SUCCESSFULLY "
}
}
PowerShell is a bit strange in that, by default, errors are non-terminating. That means that errors will be output to the console, but it will just continue on to the next line of code as if nothing happened.
Unfortunately, Try blocks only respond to terminating errors.
You can change this behaviour. On both of your New-ADGroup lines, add this to the end:
-ErrorAction Stop
That will tell PowerShell that you want it to treat errors on that line as terminating.
If you want, you can do some more reading about it here:
https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/09/handling-errors-the-powershell-way/
https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/05/weekend-scripter-using-try-catch-finally-blocks-for-powershell-error-handling/

Powershell - Checking Security Group Members against another list

A bit of context, I am trying to get a list of users from a security group, then check if any of those users do not have an assigned XenDesktop.
Please forgive me, I only started using Powershell yesterday so my formatting is off. It first grabs the users from the AD group then checks if that user has an assigned desktop, which works but I what I can't seem to get working is that if the user is found in that list, I want it to move onto the next username, instead it continues to check against every machine and then onto the final bits of code.
$checkusernames = Get-ADGroupMember "***AD security Group***" | Select SamAccountName
$desktops = get-brokerdesktop -DesktopGroupName Personal_WIN8 | Select MachineName, #{Name='AssociatedUserNames';Expression={[string]::join(“;”, ($_.AssociatedUserNames))}}
foreach ($username in $checkusernames.SamAccountName) {
foreach ($desktop in $desktops) {
If ($desktop.AssociatedUserNames -like "*$username*") {
write-host $username "is assigned to" $desktop.machinename
}
write-host $username "is not assigned to a desktop"
}
Write-host $username "is not assigned to anything"
pause
}
If you want to exit from a ForEach loop early you can do so with the Break keyword. For example:
$checkusernames = Get-ADGroupMember "***AD security Group***" | Select SamAccountName
$desktops = get-brokerdesktop -DesktopGroupName Personal_WIN8 | Select MachineName, #{Name='AssociatedUserNames';Expression={[string]::join(“;”, ($_.AssociatedUserNames))}}
foreach ($username in $checkusernames.SamAccountName) {
$machine = ''
foreach ($desktop in $desktops) {
If ($desktop.AssociatedUserNames -like "*$username*") {
$machine = $desktop.machinename
break
}
}
If ($machine) {
write-host $username "is assigned to" $desktop.machinename
} Else {
write-host $username "is not assigned to a desktop"
pause
}
}
This will stop the current cycle of the inner ForEach loop (once it has completed in it's entirety) without interrupting the ongoing cycle of the outer one.
Per the dicussion in the comments, i've also reorganised the code so that you only get a single output dependent on whether a desktop is matched to a user or not and it only pauses if it does not find a match.

PowerShell - TRUE or FALSE returned If username exists in ActiveDirectory

I am wanting to check if an AD username exists, when I run the below condition I receive an error 'Get-ADUser : Cannot find and object with identity' This is obviously due to the specific username not existing, however if the condition is false then I want to echo a response to the user.
$username_value = "JSmith"
IF (Get-AdUser $username_value) {
Run script.....
}
ELSE {
Write-Host "The username does not exist."
}
EDIT: The answer below is correct for nearly every PowerShell cmdlet, but not Get-ADUser which somehow ignores -ErrorAction. I'll leave it here for future reference. In the meantime, you can use the following instead:
$user = Get-ADUser -filter {sAMAccountName -eq $username_value}
if (!$user) {
Write-Error "This username does not exist"
exit # or return, whatever is appropriate
}
You can just suppress the error using the -ErrorAction parameter. The return value from the cmdlet should be $null in that case and thus coerce nicely to $false.
$user = Get-ADUser -ErrorAction SilentlyContinue $username_value
if (!$user) {
Write-Error "This username does not exist"
exit # or return, whatever is appropriate
}
# run script ...

trying to catch error with Add-QADGroupMember

I'm writing a script to bulk add users from a CSV, then add groups from another user.
It's working fine, except that some groups i'm not able to add (I get access denied when using the AD MMC - we have to get a different group to add them for us). The problem is that Add-QADGroupMember silently fails. I would like to somehow catch the error and list the groups that I have to get added by the different group.
I've tried try/catch, but it doesn't work... i'm at a loss.
Here is the code at the moment:
$users = Import-Csv .\UserList.csv
foreach ($user in $users) {
$SameAs = $user.SameAs
$UserGroups = (Get-QADUser $SameAs).MemberOf
foreach ($group in $UserGroups) {
Add-QADGroupMember $group -Member $user.SamAccountName |Out-Null
}
}
I'm just not able to get it to throw an error or exception when it fails to add a group.
Thanks for any help.
You have to set the erroraction to "stop".
I had the same problem with PowerCLI and all commands from there.
Try it so:
Add-QADGroupMember $group -Member $user.SamAccountName -ErrorAction Stop |Out-Null
or you can set the ErrorActionPreference global with
$ErrorActionPreference = "Stop"