PowerShell Problem Solver: Copy Files with Credentials Revisited

In the last PowerShell Problem Solver, I shared a proxy function to copy files to a network share using alternate credentials. You might want to take a moment to look at that article before continuing. As I stated at the end of the article, most of the time using the temporary PSDrive works just fine.

Troubleshooting the use of PSDrive to copy files

In my testing, I eventually ran into an error “Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.” What makes this difficult to troubleshoot is that it isn’t always apparent where this connection is defined. I used WMI to query for network connections.

get-wmiobject win32_networkconnection

I even checked using the legacy NET USE command to see if there were any lingering connections. Sometimes you can be left with a mapped connection to the IPC$ share. If that happens, then you can easily delete it.
net use \chi-fp02ipc$ /delete

Rebooting didn’t always resolve this issue. So I decided to take a different approach in my Copy-Item proxy function. Sometimes the old school ways are the best ways. I still wanted a mapped drive using alternate credentials so why not use NET USE? The syntax for mapping a drive with credentials is:
NET USE <driveletter> <share UNC> /user:<username> <password>

To use this in PowerShell requires a little work. First, the NET USE command can only use a single letter for the drive mapping. Since I have no way of knowing what drive letters are in use, I’ll use PowerShell to programmatically figure it out.
$drv = dir function:[e-z]: -Name | Where { -Not (test-path $_ )} | select -first 1

When you start PowerShell, it automatically creates a function for every drive letter. That’s why when you type D: at a PowerShell prompt, you change location to the D: drive. In the one-liner above, I’m getting a directory listing of functions E: through Z:. The [e-z] is a regular expression pattern. The –Name parameter means the first part of the expression will only write something like D: to the pipeline, in other words a filesystem location. These locations are piped to Where-Object which tests if the drive exists or not. If it doesn’t exist, PowerShell writes the object to Select-Object where I am selecting only the first drive letter not in use.

Credentials, NET USE, and PSCredential

The credential part is a little trickier because the NET USE command has no concept of a PSCredential and I don’t want to have to include a Password parameter. So here’s how you can break apart a PSCredential object. The name part is stored in the Username parameter. However, the password is stored as a secure string, meaning it is encrypted in memory on your computer. The NET USE command is expecting plain text. The trick is to invoke the Get-NetworkCredential() method on the PSCredential object. This will break the PSCredential down, including a Password property with a clear next value! This is why it is important that you lock your desktop when stepping away if using PSCredentials in your PowerShell session. While the credential goes away when PowerShell ends, anyone with access to your computer and some PowerShell knowledge could quickly find and decipher credential password. The end result is that I can use the NET USE command to map a temporary drive using credentials, delivered from PowerShell.

net use $drv $destination /user:$($credential.username) $Credential.GetNetworkCredential().Password

As with the previous version of my script, I can change the destination parameter.
$PSBoundParameters.Destination = "$($drv)"

The wrapped Copy-Item cmdlet will use this destination. At the end, I’ll remove the NET USE mapping.
if (Test-Path -path $drv) {
  Write-Verbose "Removing temporary drive mapping"
  net use $drv /d | Out-Null

Here is another version of my Copy-Item2 function that uses the NET USE command.

#requires -version 2.0

#copy item with credential

Function Copy-Item2 {

A Copy-Item replacement that supports alternate credentials
This is a proxy version of Copy-Item that has been modified to support using alternate credentials when copying files to a UNC.
.Parameter Credential
Enter a saved PSCredential object or an account name in the format domainusername or computernameusername. You will be prompted for the password.
This parameter only works if the destination is a UNC.
Last Updated:	9/25/2014

PS C:> dir c:work*.xml | Copy-Item2 -destination \chi-fp02IT -credential globomanticsadministrator -passthru


[CmdletBinding(DefaultParameterSetName='Path', SupportsShouldProcess=$true, ConfirmImpact='Medium', SupportsTransactions=$true)]
     [Parameter(ParameterSetName='Path', Mandatory=$true, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='LiteralPath', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
     [Parameter(Position=1, Mandatory=$True,HelpMessage="Enter the destination path",
       if ($Destination -match "^\\S+\S+") {
       else {
        Throw "You can only use the credential parameter with a UNC destination."

 begin {
     Write-Verbose "Starting $($MyInvocation.Mycommand)"
     try {
         $outBuffer = $null
         if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
             $PSBoundParameters['OutBuffer'] = 1

         if ($Credential) {
             #create a temporary PSDrive with the credential
             Write-Verbose -Message "Creating temporary PSDrive to $Destination"
             Try {

                #get a free drive letter
                $drv = dir function:[e-z]: -Name | Where { -Not (test-path $_ )} | select -first 1

                Write-verbose "Using credential for $($credential.username)"
                net use $drv $destination /user:$($credential.username) $Credential.GetNetworkCredential().Password | out-null

                #verify command completed
                if (-not (Test-Path "$($drv)")) {
                    Throw "Net Use command failed: net use $drv $destination /user:$($credential.username) $($Credential.GetNetworkCredential().Password)"
             Catch {

             #Change PSBoundParameter to reflect new destination
             Write-Verbose "Setting destination parameter to $($drv):"
             $PSBoundParameters.Destination = "$($drv)"

             #remove the credential from PSBound parameters
             Write-Verbose "Removing original credential from PSBoundParameters"
             $PSBoundParameters.Remove("Credential") | Out-Null
         }#if Credential

         $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Copy-Item', [System.Management.Automation.CommandTypes]::Cmdlet)
         $scriptCmd = {& $wrappedCmd @PSBoundParameters }
         $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
     } catch {
 } #begin

 process {
     try {
     } catch {
 } #process

 end {
     try {
     } catch {
     #remove temporary drive mapping
     if (Test-Path  -path $drv) {
       Write-Verbose "Removing temporary drive mapping"
       net use $drv /d | Out-Null

     Write-Verbose "Ending $($MyInvocation.Mycommand)"

 } #end

} #end function Copy-Item2

Sponsored Content

Maximize Value from Microsoft Defender

In this ebook, you’ll learn why Red Canary’s platform and expertise bring you the highest possible value from your Microsoft Defender for Endpoint investment, deployment, or migration.

This command is essentially the same as the previous version. The only thing that differs is how the temporary drive is created. In my testing, the NET USE approach was much more resilient. Although if you have an existing drive mapping to the server you will still get the multiple connections not allowed error. But at least in my experience this has been easier to troubleshoot and resolve.

Proxy functions can be great problem solvers because you can take advantage of all the cmdlet’s features with the benefit of adding your own customizations. I expect will see proxy functions solving future PowerShell problems.

Related Topics:


Don't have a login but want to join the conversation? Sign up for a Petri Account

Comments (2)

2 responses to “PowerShell Problem Solver: Copy Files with Credentials Revisited”

  1. You need to add -Isvalid parameter to Test-Path or you get also drive letters assigned to non present DVD drives etc to be marked as available you can just use [char] enumeration for loop like below instead of function

    65..90 | %{test-path -path ($K = [char]$_+”:”) -IsValid} | %{Write-Output $K$_}

Leave a Reply

External Sharing and Guest User Access in Microsoft 365 and Teams

This eBook will dive into policy considerations you need to make when creating and managing guest user access to your Teams network, as well as the different layers of guest access and the common challenges that accompany a more complicated Microsoft 365 infrastructure.

You will learn:

  • Who should be allowed to be invited as a guest?
  • What type of guests should be able to access files in SharePoint and OneDrive?
  • How should guests be offboarded?
  • How should you determine who has access to sensitive information in your environment?

Sponsored by: