Search code examples
powershellcopy-item

Does Copy-Item Change the type of Destination Parameter in PowerShell


I hope that this is a silly mistake and I am overlooking something really simple. I have a function to map a network drive and copy the contents of network drive to a destination. In the end, I return the destination path for re-use later. However, it seems to be returning different type of object for destination path. Following is the code snippet:

  function CopyDropFolder {
 param(
    [string] $dropFolder,
    [string] $releaseName,
    [string] $mapDrive
 )

 $stageDirectory= $('c:\temp\' + $releaseName + '-' + (Get-Date -Uformat %Y%m%d-%H%M).ToString() + '\')
 [string]$destinationDirectory = $stageDirectory
 Write-Host 'Mapping Folder ' $dropFolder ' as '  $mapDrive 
 MountDropFolder -mapfolder $dropFolder -mapDrive $mapDrive

 $sourceDir = $mapDrive + ':' + '\'  
 Write-Host 'Copying from mapped drive (' $sourceDir ') to ' $stageDirectory
 Copy-Item  $sourceDir -Destination $stageDirectory -Recurse
 Write-Host $destinationDirectory
 return $destinationDirectory  
 }

I call the function as follows:

$stageDirectory = CopyDropFolder -dropFolder $mapFolder -releaseName $releaseName -mapDrive $newDrive
Write-Host 'Staged to ' $stageDirectory 

The output from with the function (Write-Host $destinationDirectory) is:

c:\temp\mycopieddirectory-20161228-1422\

However from the main script where the call is made, output is:

Staged to  Z c:\temp\mycopieddirectory-20161228-1422\

It seems like the stageDirectory variable that is returned is somehow mapped with Z: which is the new drive that is mapped within the function.

Any ideas on how to actually return only the path that is printed above within the function?


Solution

  • PowerShell has the concept of pipelines. Everything you call that return a value which you don't assign to a variable or pipe e. g. to the Out-Null cmdlet will get returned from the function (even you don't explicitly use the return keyword). So you should pipe the output within your functions to Out-Null:

     function CopyDropFolder {
     param(
        [string] $dropFolder,
        [string] $releaseName,
        [string] $mapDrive
     )
    
     $stageDirectory= $('c:\temp\' + $releaseName + '-' + (Get-Date -Uformat %Y%m%d-%H%M).ToString() + '\')
     [string]$destinationDirectory = $stageDirectory
     Write-Host 'Mapping Folder ' $dropFolder ' as '  $mapDrive 
     MountDropFolder -mapfolder $dropFolder -mapDrive $mapDrive | Out-Null
    
     $sourceDir = $mapDrive + ':' + '\'  
     Write-Host 'Copying from mapped drive (' $sourceDir ') to ' $stageDirectory
     Copy-Item  $sourceDir -Destination $stageDirectory -Recurse | Out-Null
     Write-Host $destinationDirectory
     return $destinationDirectory  
     }
    

    Also, you could refactor your method like this:

    function Copy-DropFolder 
     {
         [CmdletBinding()]
         param
         (
            [string] $dropFolder,
            [string] $releaseName,
            [string] $mapDrive
         )
    
         $stageDirectory = Join-Path 'c:\temp\' ('{0}-{1}' -f $releaseName, (Get-Date -Uformat %Y%m%d-%H%M).ToString())
    
         MountDropFolder -mapfolder $dropFolder -mapDrive $mapDrive | Out-Null
         Copy-Item "$($mapDrive):\"  -Destination $stageDirectory -Recurse | Out-Null
    
         $stageDirectory
     }
    

    Three main improvements:

    1. Using approved verb (Copy-DropyFolder)
    2. Using the Join-Path cmdlet
    3. Removed Write-Host outputs (you will find plenty of articles why you shouldn't use Write-Host).