Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save cdhunt/5729126 to your computer and use it in GitHub Desktop.
Save cdhunt/5729126 to your computer and use it in GitHub Desktop.
Gets a PowerShell Credential [PSCredential] from the Windows Credential Manager. This only works for Generic Credentials.

I've updated the script to a Module and expanded the help.

To use as a module, save to a new folder in \Documents\WindowsPowerShell\Modules with a filename that matches the foldername and a psm1 extention.

ex C:\Users\you\Documents\WindowsPowerShell\Modules\StoredCredential\StoredCredential.psm1

The MIT License

Copyright (c) 2012 Tobias Burger

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

<#
.SYNOPSIS
Gets a PowerShell Credential (PSCredential) from the Windows Credential Manager
.DESCRIPTION
This module will return a [PSCredential] object from a credential stored in Windows Credential Manager. The
Get-StoredCredential function can only access Generic Credentials.
Alias: GSC
.PARAMETER Name
The name of the target login informations in the Windows Credential Manager
.EXAMPLE
PS C:\>Get-StoredCredential tfs.codeplex.com
UserName Password
-------- --------
codeplexuser System.Security.SecureString
.EXAMPLE
PS C:\>$cred = gsc production
PS C:\>$conn = Connect-WSMan -ComputerName ProdServer -Credential $cred
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.PSCredential
.NOTES
To add credentials open up Control Panel>User Accounts>Credential Manager and click "Add a gereric credential".
The "Internet or network address" field will be the Name required by the Get-StoredCredential function.
Forked from https://gist.github.com/toburger/2947424 which was adapted from
http://stackoverflow.com/questions/7162604/get-cached-credentials-in-powershell-from-windows-7-credential-manager
.LINK
Get-Credential
.ROLE
Operations
.FUNCTIONALITY
Security
#>
function Get-StoredCredential
{
[CmdletBinding()]
[OutputType([PSCredential])]
Param
(
[Parameter(Mandatory, Position=0)]
[ValidateNotNullOrEmpty()]
[Alias("Address", "Location", "TargetName")]
[string]$Name
)
End
{
$nCredPtr= New-Object IntPtr
$success = [ADVAPI32.Util]::CredRead($Name,1,0,[ref] $nCredPtr)
if ($success) {
$critCred = New-Object ADVAPI32.Util+CriticalCredentialHandle $nCredPtr
$cred = $critCred.GetCredential()
$username = $cred.UserName
$securePassword = $cred.CredentialBlob | ConvertTo-SecureString -AsPlainText -Force
$cred = $null
Write-Output (New-Object System.Management.Automation.PSCredential $username, $securePassword)
} else {
Write-Verbose "No credentials where found in Windows Credential Manager for TargetName: $Name"
}
}
Begin
{
$sig = @"
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct NativeCredential
{
public UInt32 Flags;
public CRED_TYPE Type;
public IntPtr TargetName;
public IntPtr Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public IntPtr CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public IntPtr TargetAlias;
public IntPtr UserName;
internal static NativeCredential GetNativeCredential(Credential cred)
{
NativeCredential ncred = new NativeCredential();
ncred.AttributeCount = 0;
ncred.Attributes = IntPtr.Zero;
ncred.Comment = IntPtr.Zero;
ncred.TargetAlias = IntPtr.Zero;
ncred.Type = CRED_TYPE.GENERIC;
ncred.Persist = (UInt32)1;
ncred.CredentialBlobSize = (UInt32)cred.CredentialBlobSize;
ncred.TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName);
ncred.CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob);
ncred.UserName = Marshal.StringToCoTaskMemUni(System.Environment.UserName);
return ncred;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Credential
{
public UInt32 Flags;
public CRED_TYPE Type;
public string TargetName;
public string Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public string CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public string TargetAlias;
public string UserName;
}
public enum CRED_TYPE : uint
{
GENERIC = 1,
DOMAIN_PASSWORD = 2,
DOMAIN_CERTIFICATE = 3,
DOMAIN_VISIBLE_PASSWORD = 4,
GENERIC_CERTIFICATE = 5,
DOMAIN_EXTENDED = 6,
MAXIMUM = 7, // Maximum supported cred type
MAXIMUM_EX = (MAXIMUM + 1000), // Allow new applications to run on old OSes
}
public class CriticalCredentialHandle : Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid
{
public CriticalCredentialHandle(IntPtr preexistingHandle)
{
SetHandle(preexistingHandle);
}
public Credential GetCredential()
{
if (!IsInvalid)
{
NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(handle,
typeof(NativeCredential));
Credential cred = new Credential();
cred.CredentialBlobSize = ncred.CredentialBlobSize;
cred.CredentialBlob = Marshal.PtrToStringUni(ncred.CredentialBlob,
(int)ncred.CredentialBlobSize / 2);
cred.UserName = Marshal.PtrToStringUni(ncred.UserName);
cred.TargetName = Marshal.PtrToStringUni(ncred.TargetName);
cred.TargetAlias = Marshal.PtrToStringUni(ncred.TargetAlias);
cred.Type = ncred.Type;
cred.Flags = ncred.Flags;
cred.Persist = ncred.Persist;
return cred;
}
else
{
throw new InvalidOperationException("Invalid CriticalHandle!");
}
}
override protected bool ReleaseHandle()
{
if (!IsInvalid)
{
CredFree(handle);
SetHandleAsInvalid();
return true;
}
return false;
}
}
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, out IntPtr CredentialPtr);
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
public static extern bool CredFree([In] IntPtr cred);
"@
try
{
Add-Type -MemberDefinition $sig -Namespace "ADVAPI32" -Name 'Util' -ErrorAction Stop
}
catch
{
Write-Error -Message "Could not load custom type. $($_.Exception.Message)"
}
}
}
Export-ModuleMember Get-StoredCredential
New-Alias -Name gsc -Value Get-StoredCredential -ErrorAction SilentlyContinue
if ($?) {
Export-ModuleMember -Alias gsc
}
@PackElend
Copy link

when I run it within PowerShell ISE I get this error:

Export-ModuleMember : The Export-ModuleMember cmdlet can only be called from inside a module.
At C:\Users\c563368\Documents\WindowsPowerShell\Moduls\StoredCredential\Get-CredentialFromWindowsCredentialManager.ps1:207 char:1
+ Export-ModuleMember Get-StoredCredential
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (:) [Export-ModuleMember], InvalidOperationException
    + FullyQualifiedErrorId : Modules_CanOnlyExecuteExportModuleMemberInsideAModule,Microsoft.PowerShell.Commands.ExportModuleMemberCommand

any idea what goes wrong?

@mblennegard
Copy link

@PackElend That error occurs because you are not using the code as a module. If you want to use the code directly in a script, simply just remove the last six (6) rows from the code, starting with "Export-ModuleMember..." That code creates the alias for the module, which you don't really "need" if you are running the code directly from within another script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment