How do I specify default PSCredential for my script?

This topic contains 6 replies, has 3 voices, and was last updated by Profile photo of Dave Wyatt Dave Wyatt 3 years, 3 months ago.

  • Author
    Posts
  • #13223
    Profile photo of GS
    GS
    Participant

    Hello,

    I want my script to access PSCredential type parameter which is optional. I want to use credentials of current user if it's not supplied but use $cred if it's supplied and I plan to use that parameter to use later say in Get-WMIObject calls.
    How do I properly initialize $cred parameter?

    [Parameter(Mandatory=$False)]
    [PSCredential]$cred;

  • #13252
    Profile photo of GS
    GS
    Participant

    You guys are awesome!

    What notations in '*:Credential' means in brackets? I assume brackets are used to specify which value you need to pull out of hashtable based on that key. But both "*" and ":" I assume signify something special

  • #13253
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    The complete details of that variable are in the about_Parameters_Default_Values help file. It's a hashtable / Dictionary with a special syntax enforced for keys. The keys must be ":"; the part can be *, in which case it applies to all commands with .

    You do need to be running at least PowerShell 3.0 to use $PSDefaultParameterValues, though; keep that in mind if you've still got older versions floating around.

  • #13299
    Profile photo of GS
    GS
    Participant

    Hello,

    Got following error when using substitution method on following command. How do I remove credentials when specifically using Add-Content? Issue is that credentials which I specify manually when I run cmdLet is network credentials to query AD in different domain but I have to write to local file system where that account do not have permissions. Is it still possible to use substituion method instead of creating HastTable?

    Add-Content -Path @"c:\out.txt" -Value ("Processing account")


    The FileSystem provider supports credentials only on the New-PSDrive cmdlet. Perform the operation again without specifying credentials.
    At C:\ExpirationMailer.ps1:78 char:1
    + Add-Content -Path $OutputFile -Value ("Processing account $_.givenName $_.Surnam ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotImplemented: (:) [], PSNotSupportedException
    + FullyQualifiedErrorId : NotSupported

  • #13300
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    You just have to be more selective in which cmdlets the substitution applies to. A key of '*:Credential' means your PSCredential gets applied to any cmdlet which has a "Credential" parameter. You could do something like this, instead:

    $PSDefaultParameterValues['*-AD*:Credential'] = $Credential
    

    That would only apply to cmdlets whose name contained "-AD". You can make multiple entries to the table, if you need to use some cmdlets and not others.

    Personally, I prefer the splatting / hashtable approach, for its PowerShell 2.0 compatibility and finer control in situations like this.

  • #13226
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Splatting can be helpful here:

    [CmdletBinding()]
    param (
        [pscredential]
        $Credential
    )
    
    # Setting up the hashtable which will either be empty, or contain your $Credential object
    
    $credHash = @{}
    if ($Credential)
    {
        $credHash['Credential'] = $Credential
    }
    
    # Splatting the hashtable to other commands.  If $credHash contains a credential object, it gets
    # passed to the cmdlet.  If it's empty, nothing is passed to the -Credential parameter, and Get-WmiObject
    # defaults to using the current user's credentials.
    
    Get-WmiObject -Class Win32_OperatingSystem @credHash
    

    I've read that you can also set your parameter's default value to [pscredential]::Empty , but that some cmdlets don't properly handle that value. It's more reliable to use the splatting approach.

  • #13233
    Profile photo of Rob Campbell
    Rob Campbell
    Participant

    Another option:

    [CmdletBinding()]
    param (
    [pscredential]
    $Credential
    )
    if ($Credential)
    {
    $PSDefaultParameterValues = $PSDefaultParameterValues.clone()
    $PSDefaultParameterValues['*:Credential'] = $Credential
    }

    Now any cmdlet that takes a -Credential parameter will automatically use that credential, and no other changes are required in the script.

    Cloning the $PSDefaultParameterValues is necessary to preserve whatever default parameters values are set in the session, while protecting the preference variable in the parent scope. Unlike the other preference variables, it's a hash table, which means just adding a new key would actually update the preference in the parent scope, and would still be in effect when the script exits.

You must be logged in to reply to this topic.