These functions will allow you to easily save a set of credentials to disk so that they can be reused during an unattended session later. There are a few blog entries and newsgroup posts about this topic elsewhere, and Lee Holmes covers it in his “PowerShell Cookbook”, but nothing that I have seen actually helps you do the end-to-end of credential –> disk –> credential process. Hope you find it useful! I wrote this for my book, but as it’s of general use I thought I would share.
Update: 7/21/08 @ 11:16a
I’m changing the import conditions to work better on v1 of PowerShell. Download link has updated code.
Update: 7/21/08 @ 7:10p
Reader Steve S. pointed out to me that if you give Export-PSCredential a username, it does not work, but he expected it to. I agreed, so changed the logic a bit. I like it this way, now it works just like Get-Credential does (try get-credential “username” to see what I mean).
One last thing—big props to Brandon Shell who has written on this topic as well. In fact, I umm, er, was troubleshooting that script with him when he wrote it so I should know better. To be fair, I—ok I have no excuse. But I didn’t mean to steal any well-deserved thunder. ;) My script does store the username where his does not, although he says he’s got an updated one which does. Even so—the more the merrier so that you can see multiple ways to solve a problem.
1: # Author: Hal Rottenberg <hal@halr9000.com>
2: # Url: http://halr9000.com/article/tag/lib-authentication.ps1
3: # Purpose: These functions allow one to easily save network credentials to disk in a relatively
4: # secure manner. The resulting on-disk credential file can only [1] be decrypted
5: # by the same user account which performed the encryption. For more details, see
6: # the help files for ConvertFrom-SecureString and ConvertTo-SecureString as well as
7: # MSDN pages about Windows Data Protection API.
8: # [1]: So far as I know today. Next week I'm sure a script kiddie will break it.
9: #
10: # Usage: Export-PSCredential [-Credential <PSCredential object>] [-Path <file to export>]
11: # Export-PSCredential [-Credential <username>] [-Path <file to export>]
12: # If Credential is not specififed, user is prompted by Get-Credential cmdlet.
13: # If a username is specified, then Get-Credential will prompt for password.
14: # If the Path is not specififed, it will default to "./credentials.enc.xml".
15: # Output: FileInfo object referring to saved credentials
16: #
17: # Import-PSCredential [-Path <file to import>]
18: #
19: # If not specififed, Path is "./credentials.enc.xml".
20: # Output: PSCredential object
21:
22: function Export-PSCredential {
23: param ( $Credential = (Get-Credential), $Path = "credentials.enc.xml" )
24:
25: # Look at the object type of the $Credential parameter to determine how to handle it
26: switch ( $Credential.GetType().Name ) {
27: # It is a credential, so continue
28: PSCredential { continue }
29: # It is a string, so use that as the username and prompt for the password
30: String { $Credential = Get-Credential -credential $Credential }
31: # In all other caess, throw an error and exit
32: default { Throw "You must specify a credential object to export to disk." }
33: }
34:
35: # Create temporary object to be serialized to disk
36: $export = "" | Select-Object Username, EncryptedPassword
37:
38: # Give object a type name which can be identified later
39: $export.PSObject.TypeNames.Insert(0,’ExportedPSCredential’)
40:
41: $export.Username = $Credential.Username
42:
43: # Encrypt SecureString password using Data Protection API
44: # Only the current user account can decrypt this cipher
45: $export.EncryptedPassword = $Credential.Password | ConvertFrom-SecureString
46:
47: # Export using the Export-Clixml cmdlet
48: $export | Export-Clixml $Path
49: Write-Host -foregroundcolor Green "Credentials saved to: " -noNewLine
50:
51: # Return FileInfo object referring to saved credentials
52: Get-Item $Path
53: }
54:
55: function Import-PSCredential {
56: param ( $Path = "credentials.enc.xml" )
57:
58: # Import credential file
59: $import = Import-Clixml $Path
60:
61: # Test for valid import
62: if ( !$import.UserName -or !$import.EncryptedPassword ) {
63: Throw "Input is not a valid ExportedPSCredential object, exiting."
64: }
65: $Username = $import.Username
66:
67: # Decrypt the password and store as a SecureString object for safekeeping
68: $SecurePass = $import.EncryptedPassword | ConvertTo-SecureString
69:
70: # Build the new credential object
71: $Credential = New-Object System.Management.Automation.PSCredential $Username, $SecurePass
72: Write-Output $Credential
73: }

These versions work for you? The export is fine but the import doesn’t recognize the type. I don’t think the import function can validate the custom type you created.
PS C:\Scripts\PoSH> (import-clixml credentials.enc.xml).psobject.typenames
System.Management.Automation.PSCustomObject
System.Object
Or am I doing something wrong?
You know, it works great for me in v2, but I get the same error in v1. If you look at the .xml file, does it have the typename? “ExportedPSCredential “. I bet it doesn’t.
Darn, that was pretty elegant. I guess I’ll take it out for now. Try this one: http://poshcode.org/472
(I’ll update the links above.)
Thanks for the update. I suspected a version issue.
[...] Rottenberg has put together a very nice set of functions for exporting and importing PSCredential to a file. The export function takes a PSCredential and serializes it to an XML file. The [...]
[...] Hal brings us a couple of scripts for saving credentials [...]