2

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?

Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
sohail
  • 589
  • 1
  • 11
  • 26

1 Answers1

2

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).
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • That is very interesting to know. I will try this and let you know the result. – sohail Dec 28 '16 at 20:46
  • Also, I am confused as to why would it effect the variable $destinationDirectory when I am using $stageDirectory as my destination variable – sohail Dec 28 '16 at 20:50
  • The Output might trick you, e. g. the `MoutDropFolder` may use Write-Host. can you try my refactored solution? – Martin Brandl Dec 28 '16 at 20:58
  • My apologies. Yes, I tried and forgot to add | output-null to the first statement. It works :) Thanks @Martin – sohail Dec 28 '16 at 21:00
  • 1
    Your refactored code works perfectly. So, what is the best practice to output to console as well as to the log file? I read in some post that Write-Host is not necessarily evil :) as we can redirect its output when executing. – sohail Dec 28 '16 at 21:30
  • I would try to avoid such logging at all. If I want to provide outputs I would use the Write-Verbose cmdlet so the caller can decide whether he wants to get output using `Copy-DropFolder -verbose`. – Martin Brandl Dec 28 '16 at 21:33