System.Security.Principal.IdentityNotMappedException Catching all errors - powershell

I am having issues with a try/catch block where the catch block for System.Security.Principal.IdentityNotMappedException is catching all errors regardless if they're of type System.Security.Principal.IdentityNotMappedException or not. The problem is when I move the try/catch block outside of the script into it's own for testing, the try/catch works as intended.
The try/catch is inside a for/each so they only thing I can think of is that the loop is somehow tripping up the try/catch block? The one error it loves catching is System.Management.Automation.RuntimeException.
Below is the test script I made that works as intended, but placed within the foreach doesn't:
I actually got the error to manifest with this:
foreach($x in Get-ChildItem){
Get-Acl "C:\fake"
try {
$Acl = Get-Acl
Set-Acl LiteralPath "C:\temp" $Acl -ErrorAction Stop
Write-Host "Access Rule Added" -ForegroundColor Cyan
}
catch [System.UnauthorizedAccessException] {
Write-Host "Insufficient Priviliege. Owner: $($Acl.Owner) ($_)" -ForegroundColor Red
}
catch [System.Security.Principal.IdentityNotMappedException] {
Write-Host "Invalid Prinicpal! ($_)" -ForegroundColor Red
$abort = Read-Host -Prompt "Abort? (Y)"
if($abort -ieq "Y"){ Exit }
}
catch {
Write-Host "ALL: $_" -ForegroundColor Red
}
}

This isn't exactly an answer to my question (as I don't fully understand why it was happening and as such it might snag on something else) but adding -ErrorAction SilentlyContinue to the Get-Acl command that was throwing the first error helps prevent the errant catching:
foreach($x in Get-ChildItem){
Get-Acl "C:\fake" -ErrorAction SilentlyContinue
try {
$Acl = Get-Acl
Set-Acl LiteralPath "C:\temp" $Acl -ErrorAction Stop
Write-Host "Access Rule Added" -ForegroundColor Cyan
}
catch [System.UnauthorizedAccessException] {
Write-Host "Insufficient Priviliege. Owner: $($Acl.Owner) ($_)" -ForegroundColor Red
}
catch [System.Security.Principal.IdentityNotMappedException] {
Write-Host "Invalid Prinicpal! ($_)" -ForegroundColor Red
$abort = Read-Host -Prompt "Abort? (Y)"
if($abort -ieq "Y"){ Exit }
}
catch {
Write-Host "ALL: $_" -ForegroundColor Red
}
}
Though it's strange how $_ doesn't display the actual error but just AclObject in this instance.

Related

Powershell not reading .txt lines

I cannot get PowerShell to run this .txt file, what am I doing wrong? I tried changing the name of the .txt and checked passed scripts and everything seems to be the same but I keep getting an error saying that the ".txt in invalid"
$POSName = "$PSScriptRoot\Bex.txt"
foreach ($POS in (Get-Content $POSName)) {
$Bex = Get-Service -ComputerName $POSName | Where-Object { $_.name -eq "BexServ" }
}
If ($Bex -eq $null) {
# Service does not exist
Write-Host " doesn't exist." -ForegroundColor Red
}
Else {
# Service does exist
Write-Host "The $($Bex.Name) service found." -ForegroundColor Green
If ($Bex.Status -eq "Running") {
# Stop Service
Set-Service -status stopped -ComputerName $POSName -name $Box.Name -ErrorAction Stop
Write-Host "The $($Bex.Name) successfully stopped." -ForegroundColor Green
}
else {
#service already stopped
If ($Bex.Status -eq "Stopped") {
Write-Host "The $($Bex.Name) service already Stopped." -ForegroundColor Green
}
}
}
As commented, you are using the wrong variable in the loop. The code is reading the text file just fine, it is Get-Service that cannot deal with a path to a file in the -ComputerName parameter.
Also, the placing of the if..else should be inside the loop, not after.
Try
$POSName = "$PSScriptRoot\Bex.txt"
foreach ($POS in (Get-Content $POSName)) {
$Bex = Get-Service -ComputerName $POS | Where-Object { $_.name -eq "BexServ" }
If (!$Bex) {
# Service does not exist
Write-Host " doesn't exist." -ForegroundColor Red
}
Else {
# Service does exist
Write-Host "The $($Bex.Name) service found." -ForegroundColor Green
If ($Bex.Status -eq "Running") {
# Stop Service
Set-Service -status stopped -ComputerName $POSName -name $Box.Name -ErrorAction Stop
Write-Host "The $($Bex.Name) successfully stopped." -ForegroundColor Green
}
else {
#service already stopped
If ($Bex.Status -eq "Stopped") {
Write-Host "The $($Bex.Name) service already Stopped." -ForegroundColor Green
}
}
}
}
It might also be a good idea to output the computername ($POS) in the Write-Host lines too

Suppress Powershell Errors while adding to $Error Variable

I have a block of code executing that has been set up with a simple If/Else block to catch errors. I would normally use Try/Catch but the Exchange 2010 PS environment I'm working in doesn't allow me to use most of the Try/Catch features (and I can't update it or change it in any way because it's the customer's system and they're unwilling).
The issue is that while the code will function as expected when the Add-DistributionGroupMember cmdlet is set with -ErrorAction "Stop", it will output the error to the host each time, which annoys the customer (and me) because it's effectively just red noise since all the possible errors are being handled via a detailed output file.
If I set the cmdlet to -ErrorAction "SilentlyContinue" the error text is suppressed, but the Error is not added to the $Error[0] spot as I expected. The same is true of -ErrorAction "Ignore". The code requires that the Error be added to the $Error variable each time there is an error.
Here is the code:
$ListMembershipsIn | % {
$Alias = $_.Alias
$Member = $_.Member
Add-DistributionGroupMember -Identity $Alias -Member $Member -Confirm:$false -ErrorAction Stop
if($Error[0] -match "The recipient"){
Write-Host -ForegroundColor Yellow "Already a member"
Add-Content -Path $OutputPath -Value "$($Alias),$($Member),Group already contains Member"
}
elseif($Error[0] -match "couldn't be found"){
Write-Host -ForegroundColor Yellow "not found"
Add-Content -Path $OutputPath -Value "Group does not exist or cannot be found,$($Alias),N/A"
}
elseif($Error[0] -match "couldn't find"){
Write-Host -ForegroundColor Yellow "not found"
Add-Content -Path $OutputPath -Value "Member does not exist or cannot be found,$($Alias),$($Member)"
}
elseif($Error[0] -match "There are Multiple"){
Add-Content -Path $OuputPath -Value "Member name matches too many recipient - Add Member Manually,$($Alias),$($Member)"
}
else{
Add-Content -Path $OutputPath -Value "Member Successfully Added to Group,$($Alias),$($Member)"
Write-Host -ForegroundColor Green "Throw Flag here"
}
}
You have two options for recourse, you can utilize the -ErrorVariable common parameter, or a Try/Catch block to interact with the specific error.
ErrorVariable
When interacting with ErrorVariable, you can prepend the name with a + to append additional errors to it just like the $Error automatic variable, e.g.: -ErrorVariable '+MyError'
$ListMembershipsIn | ForEach-Object {
$Alias = $_.Alias
$Member = $_.Member
Add-DistributionGroupMember -Identity $Alias -Member $Member -ErrorVariable 'MyError'
## No error = good, continue the next iteration of the loop
If (-not $MyError)
{
Add-Content -Path $OutputPath -Value "Member Successfully Added to Group,$Alias,$Member"
Write-Host -ForegroundColor Green "Throw Flag here"
Continue
}
Switch -Regex ($MyError.Exception.Message)
{
'The recipient'
{
Write-Host -ForegroundColor Yellow "Already a member"
Add-Content -Path $OutputPath -Value "$Alias,$Member,Group already contains Member"
}
"couldn't be found"
{
Write-Host -ForegroundColor Yellow "not found"
Add-Content -Path $OutputPath -Value "Group does not exist or cannot be found,$Alias,N/A"
}
"couldn't find"
{
Write-Host -ForegroundColor Yellow "not found"
Add-Content -Path $OutputPath -Value "Member does not exist or cannot be found,$Alias,$Member"
}
'There are Multiple'
{
Add-Content -Path $OuputPath -Value "Member name matches too many recipient - Add Member Manually,$Alias,$Member"
}
}
}
Try/Catch
$ListMembershipsIn | ForEach-Object {
$Alias = $_.Alias
$Member = $_.Member
Try
{
Add-DistributionGroupMember -Identity $Alias -Member $Member -ErrorAction 'Stop'
## No error thrown = successful processing
Add-Content -Path $OutputPath -Value "Member Successfully Added to Group,$Alias,$Member"
Write-Host -ForegroundColor Green "Throw Flag here"
}
Catch
{
Switch -Regex ($_.Exception.Message)
{
'The recipient'
{
Write-Host -ForegroundColor Yellow "Already a member"
Add-Content -Path $OutputPath -Value "$Alias,$Member,Group already contains Member"
}
"couldn't be found"
{
Write-Host -ForegroundColor Yellow "not found"
Add-Content -Path $OutputPath -Value "Group does not exist or cannot be found,$Alias,N/A"
}
"couldn't find"
{
Write-Host -ForegroundColor Yellow "not found"
Add-Content -Path $OutputPath -Value "Member does not exist or cannot be found,$Alias,$Member"
}
'There are Multiple'
{
Add-Content -Path $OuputPath -Value "Member name matches too many recipient - Add Member Manually,$Alias,$Member"
}
}
}
}
It appears that Add-DistributionGroupMember command doesn't fill ErrorVariable when specified.
I found no way to avoid the unwanted output, so I handled the error with Tristan's trick rather than by exception handling (which is absolutely fine, but not fitting my own dev):
$Error.clear()
Add-DistributionGroupMember -Identity $mySite.MailingList -Member $emailAddress
if ($Error.count -eq 0) {
$script:logger["ldissue"] += "<li>Liste de diffusion $($mySite.MailingList) : La ressource <b>$($ADRecord.Name)</b> ($($ADRecord.SamAccountName) - $($BoondRecord.flags)) a été ajoutée à la liste</li>"
} else {
$script:logger["ldissue"] += "<li>Liste de diffusion $($mySite.MailingList) : La ressource <b>$($ADRecord.Name)</b> ($($ADRecord.SamAccountName) - $($BoondRecord.flags)) n'a pas pu être ajoutée à la liste (<i>$($Error[0])</i>)</li>"
}
Use the "-ErrorAction Continue" this won't suppress the error but it will ensure the script continues and it places the error in the $Error variable.
You can also use the $Error.clear() command to remove any stored errors in the session.

Powershell: Fix My Loop Logic

I am trying to get the logic straightened out for a loop that I need to continue to prompt a user to enter a valid UNC path. I have it set to test the path and output to the console that the path is invalid. But, after that, it moves back to my prompt for choice. I want it to instead, ask the user to enter another valid path before moving on to the next step. Here is my loop:
do{
Write-Host ""
$pathPrompt = Write-Host "Please enter path to file/folder:" -ForegroundColor Cyan;
$path = Read-Host;
$test = Test-Path $path
if($test -eq $false){
Write-Host "ERROR! Invalid Path!" -ForegroundColor Red
}
}until($test -eq $true){
Write-Host ""
Write-Host "Getting ACL on"$path -ForegroundColor Green
Get-NTFSAccess -Path $path
}
What am I missing or not doing right here?
Sounds like you want to reuse your validation test. You could put it in a function for reuse:
Function Get-ValidPath {
do {
Write-Host "`r`nPlease enter path to file/folder:" -ForegroundColor Cyan
$path = Read-Host
$test = Test-Path $path
if ($test -eq $false) {
Write-Host "ERROR! Invalid Path!" -ForegroundColor Red
}
} until ($test -eq $true)
$path
}
$validatedpath1 = Get-ValidPath
Write-Host "`r`nGetting ACL on $validatedpath1" -ForegroundColor Green
Get-NTFSAccess -Path $validatedpath1
$validatedpath2 = Get-ValidPath

IF/ELSE Get-SPWeb

I am trying to quickly check whether a web site exists. I seem to have an error in my IF statement, but I'm not sure of the correct syntax. Here's my code:
$URLis = "https://ourdevsite.dev.com/sites/flibidyboots"
add-pssnapin microsoft.sharepoint.powershell -ea 0
IF ((Get-SPWeb $URLis) -ne 0){
Write-Host "Site does not exist, so we can proceed with building it" -foregroundcolor green
}
Else {
Write-Host "Site does exist, so we need to pick another URL" -foregroundcolor red
}
What did I get wrong?
Ok, first of all its $null, not 0. And second, if it is not $null it exists, so your cases are mixed up.
Here is some code that will work.
Add-PSSnapin "Microsoft.SharePoint.Powershell" -ErrorAction SilentlyContinue
$url = "http://teams"
$w = Get-SPWeb -Identity $url -ErrorAction SilentlyContinue
if ($w) {
Write-Host "Site Exists" -ForegroundColor Green
} else {
Write-Host "No Site" -ForegroundColor Red
}

Powershell - verify object exists in AD

i have a text file containing arround 100 servers, how can i push these into a script and test if they exist within AD? I have a simple script below:
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
if (Get-ADComputer $serverlist ) {
Write-Host "#########################"
Write-Host "Computer object exists"
Write-Host "#########################"
}
else {
Write-Host "#########################"
Write-Host "Computer object NOT FOUND"
Write-Host "#########################"
}
}
the above does not work returning a error:
Get-ADComputer : Cannot convert 'System.Object[]' to the type 'Microsoft.ActiveDirectory.Management.ADComputer' required by parameter 'Identity'. Specified method is not supported.
Can someone please explain does the get-adcomputer only allow a single object? Also if i remove the txt file and add a server shown below:
if (Get-ADComputer "server name" )
The above provides only results if the server exists within AD, if the server does not the error is shown below:
Get-ADComputer : Cannot find an object with identity: 'iuiub' under: 'DC=####,DC=#####,DC=#####'
Thank you for any insight / help!
Phil
Create an array - #(). If the array has 1 or more objects in it - which is $true - then you know the computer exists. If the array has 0 objects in it - which is $false- then you know the computer doesn't exist. I know some people don't like the ErrorAction to be set to SilentlyContinue but you're "Outputting an Error" if an error does occur.
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
if (#(Get-ADComputer $server -ErrorAction SilentlyContinue).Count) {
Write-Host "#########################"
Write-Host "Computer object exists"
Write-Host "#########################"
}
else {
Write-Host "#########################"
Write-Host "Computer object NOT FOUND"
Write-Host "#########################"
}
}
Another thing you could try are try catch blocks. Sorta like this:
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
try{
Get-ADComputer $server -ErrorAction Stop
Write-Host "#########################"
Write-Host "Computer object exists"
Write-Host "#########################"
}
catch{
Write-Host "#########################"
Write-Host "Computer object NOT FOUND"
Write-Host "#########################"
}
}
Line 3, change $serverlist to $server
With regards to handling a not found result. I'd try flipping the logic :
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
$tempVar = Get-ADComputer $server
if ($tempVar -like "Get-ADComputer : Cannot find an object with identity" ) {
Write-Host "#########################"
Write-Host "Computer object NOT FOUND"
Write-Host "#########################"
}
else{
Write-Host "#########################"
Write-Host "Computer object exists"
Write-Host "#########################"
}
}
In order to get a more helpful output, I'd go with the following... You'll just have a list of green and red lines indicating which server was found and which one wasn't.
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
try {
Get-ADComputer $server -ErrorAction Stop | Out-Null
Write-Host "$($server) exists" -ForegroundColor DarkGreen
}
catch {
Write-Host "$($server) NOT FOUND" -ForegroundColor DarkRed
}
}