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

384 views Asked by At

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?

1

There are 1 answers

6
Martin Brandl On BEST ANSWER

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).