简体   繁体   中英

PowerShell Error handling from a module

I'm having a weird issue with error handling from within a module. When I copy my advanced function in the ISE editor and run it from there I don't see any errors reported. As this is the desired behavior. However, when I paste that same function in a module file ( Toolbox.ActiveDirectory.psm1 ) and call it from there, it does fill up the variable $Error .

I don't really understand why it's reporting the errors from the function Get-ADTSProfileHC from within the module and not from within the script pane. As you can see I erase the last error in the Catch clause (thanks to the help of DanL in a previous question).

It seems like there's a difference between error handling from the console or from a module.

The function:

Function Get-ADusersHC {
[CmdletBinding(SupportsShouldProcess=$True)]
Param(
     [Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true,Position=0)]
     [String[]] $OU
)

Begin {
    Function Get-ADOUNameHC {
        $CanonicalName = $_.CanonicalName
        [System.Collections.ArrayList]$Pieces = $CanonicalName.split(“/”) 
        $Pieces.Remove($Pieces[-1])
        $OU = $Pieces -join '\'
        $OU -replace ($Pieces[0],$Pieces[0].ToUpper())
    }

    Function Get-ADManagerDisplayNameHC {
        $m = Get-ADObject -Identity $_.manager -Properties displayName,cn
        if($m.ObjectClass -eq "user") { $m.displayName } Else{ $m.cn }
    }

    Function Get-ADTSProfileHC {

        [CmdletBinding()]
        Param(
            [Parameter(Mandatory=$true,Position=0)]
            [String] $DistinguishedName,
            [parameter(Mandatory=$true,Position=1)]
            [ValidateNotNullOrEmpty()]
            [ValidateSet('UserProfile','AllowLogon','HomeDirectory','HomeDrive')]
            [String]$Property
        )

        Begin {
            $User = [ADSI]"LDAP://$DistinguishedName"
        }

        Process {
            Try {
                Switch ($Property) {
                    'AllowLogon'    {if ($($User.psbase.InvokeGet('allowLogon')) -eq '1'){$True}else{$False}}
                    'HomeDirectory' {$User.psbase.InvokeGet('TerminalServicesHomeDirectory')}
                    'HomeDrive'     {$User.psbase.InvokeGet('TerminalServicesHomeDrive')}
                    'UserProfile'   {$User.psbase.InvokeGet('TerminalServicesProfilePath')}
                }
            }
            Catch {
                # When we receive an error, it means the field has never been used before and is blank
                # this is due to an error in the AD (same problem with the Quest CmdLet), AllowLogon is 
                # always 'TRUE' but we don't set it because we can't read it sometimes so we write 'blanks'
                Write-Output $null
                $Error.Remove($Error[0])
            }
        }
    }
}

Process {    
    Foreach ($_ in $OU) {
        Write-Verbose "Function Get-HCADusersNoManager > OU: $_"
        Write-Verbose "Function Get-HCADusersNoManager > Manager field empty"
        Get-ADUser -SearchBase $_ -Filter 'SAMAccountName -eq "shenn"' -Properties * |
        #Get-ADUser -SearchBase $_ -Filter * -Properties * |
        Foreach {
            $Properties = ([Ordered] @{
                    "Creation date" = $_.whenCreated;
                    "Display name" = $_.displayName;
                    "CN name" = $_.name;
                    "Last name" = $_.sn;
                    "First name" = $_.givenName;
                    "Logon name" = $_.sAMAccountName;
                    "Manager" = if($_.manager){Get-ADManagerDisplayNameHC};
                    "Employee ID" = $_.EmployeeID;
                    "HeidelbergcCement Billing ID" = $_.extensionAttribute8
                    "Type of account" = $_.employeeType;
                    "OU" = Get-ADOUNameHC;
                    "Notes" = $_.info -replace "`n"," ";
                    "E-mail" = $_.EmailAddress;
                    "Logon script" = $_.scriptPath;
                    "TS User Profile" = Get-ADTSProfileHC $_.DistinguishedName 'UserProfile';
                    "TS Home directory" = Get-ADTSProfileHC $_.DistinguishedName 'HomeDirectory';
                    "TS Home drive" = Get-ADTSProfileHC $_.DistinguishedName 'HomeDrive';
                    "TS Allow logon" = Get-ADTSProfileHC $_.DistinguishedName 'AllowLogon'
                    })
            $Object = New-Object -TypeName PSObject -Property $Properties
            Write-Output $Object
        }
    }
} 

}

The error:

Exception calling "InvokeGet" with "1" argument(s): "The directory property cannot be foun
d in the cache.
"
At C:\Program Files\WindowsPowerShell\Modules\Toolbox.ActiveDirectory\Toolbox.ActiveDirect
ory.psm1:299 char:42
+                         'UserProfile'   {$User.psbase.InvokeGet('TerminalService ...
+                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodTargetInvocation

I found the answer thanks to another post on StackOverflow from a Microsoft engineer. It appears that the $Error variable for modules needs to be changed in the Global scope.

In short, I had to change $Error.Remove($Error[0]) to:

$Global:Error.Remove($Global:Error[0])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM