PSDeployScripts/CopyVMFile.ps1

<#
    .SYNOPSIS
        Uses Copy-VMfile cmdlet which ships with Hyper-V on Sever 2012 R2
 
    .DESCRIPTION
        Uses Copy-VMfile cmdlet (introduced in Server 2012 R2 Hyper-V) to perform the deployment.
        The cmdlet has some issues while copying to C:\windows\System32 & 'C:\Program files' folder (issue with DSC resources),
        We workaround that by copying to a temp location and then moving the files and folders.
 
        Deployment Options:
            Exposed FileSource - this is equal to 'host' in the Server2012R2 Hyper-V (can change in future versions so exposed here).
            CreateFullPath - Set this to True/False if you want the destination path to be created.
    .PARAMETER Deployment
        Deployment to run
         
#>

[cmdletbinding()]
# Invoke-PSDeploy fails if there is a parameter set here
param (
    
    [Parameter(ValueFromPipeLine=$True)]
    [ValidateScript({ $_.PSObject.TypeNames[0] -eq 'PSDeploy.Deployment' })]
    [psobject[]]$Deployment,

    # Specify the name of the VM, this is where the artifcats will be deployed
    [string]$name,

    # Specify the Hyper-V host name where the VM resides. Default - Localhost.
    [String]$ComputerName=$env:COMPUTERNAME,

    #Specify the FileSource, at present only possible value is 'Host'
    [String]$FileSource,

    # Create full path if required on the VM.
    [Switch]$createFullPath
)
BEGIN {
    Write-Verbose "Starting CopyVM deployment on VMnamed $VMName running on Host $ComputerName with $($Deployment.count) sources"
    [void]$PSBoundParameters.Remove('Deployment')
}
PROCESS {
   # Runs the local Copy-VMFile cmdlet (comes with Hyper-V module on Server 2012R2 + )
    foreach($deploy in $Deployment){
        $LocalCopyVMFileHash = @{}
        # add fail safe for FileSource & CreateFullPath
        if (-not $deploy.DeploymentOptions.FileSource) {
            # At the moment the cmdlet only supports specifying host as the file source.
            # This will add this if the deployment options does not have it mentioned
            $LocalCopyVMFileHash.Add('FileSource','Host')
        }
        else {
            $LocalCopyVMFileHash.Add('FileSource',$deploy.DeploymentOptions.FileSource)
        }

        
        if(-not $deploy.DeploymentOptions.CreateFullPath) {
            $LocalCopyVMFileHash.Add('CreateFullPath',$true)
        }
        else {
            $LocalCopyVMFileHash.Add('CreateFullPath',$deploy.DeploymentOptions.CreateFullPath)
        }

        if (-not $deploy.DeploymentOptions.Name) {
            Write-Warning -Message "No Name (VMName) specified for the deployment. Skipping the deployment $($Deploy | Out-String)."
            return
        }
        else {
            $LocalCopyVMFileHash.Add('Name',$($deploy.DeploymentOptions.Name)) 
        }

        if ($deploy.DeploymentOptions.ComputerName) {
            # if the ComputerName specified, do a name resolution.
            Try {
                $SourceHyperVHost = [System.Net.Dns]::GetHostEntry($deploy.DeploymentOptions.ComputerName).HostName
                $LocalCopyVMFileHash.Add('ComputerName',$SourceHyperVHost)
            }
            Catch
            {
                Write-Warning -Message "Could not resolve the $ComputerName. Skipping the Deployment $($Deploy | Out-String)."
                return # return the control back, we are skipping the computer
                #Throw "Could not determine Hyper-V host for $($Map.Source), skipping"
            }
        }
        else {
            # use the local machine name as the Hyper-V host where the VM is running
            $LocalCopyVMFileHash.Add('ComputerName',$env:COMPUTERNAME)
        }

        if ($deploy.SourceExists) {
            foreach($target in ($deploy.Targets)) {
                if($Deploy.SourceType -eq 'Directory') {
                    # logic to copy the folder into the VM using Copy-VMFile cmdlet.
                    # Credits to Ravi's tip -> http://www.powershellmagazine.com/2013/12/17/pstip-copying-folders-using-copy-vmfile-cmdlet-in-windows-server-2012-r2-hyper-v/
                    Get-Childitem -Path $($deploy.Source) -Recurse -File |
                        Foreach-Object -Process { 
                            $FileName = Split-Path -Path $PSitem.FullName -Leaf
                            $Target = $Target.trimend('\')
                            Write-Verbose "Invoking Copy-VMFile. Source -> $($PSitem.Fullname) Destination -> $("$Target\$Filename")"
                            #Write-Host "$($LocalCopyVMFileHash | out-String)"
                            Copy-VMFile @LocalCopyVMFileHash -SourcePath $PSitem.FullName -DestinationPath "$Target\$Filename"
                        }

                }
                elseif ($Deploy.SourceType -eq 'File')
                {
                    # logic to copy file into the VM using Copy-VMfile cmdlet.
                    $FileName = Split-Path -Path $Deploy.Source -Leaf
                    $Target = $Target.trimend('\')
                    Write-Verbose "Invoking Copy-VMFile. Source -> $($Deploy.Source) Destination -> $("$Target\$Filename")"
                    #Write-Host "$($LocalCopyVMFileHash | out-String)"
                    Copy-VMFile @LocalCopyVMFileHash -SourcePath $Deploy.Source -DestinationPath "$Target\$Filename"
                }
                else {
                    Write-Warning -Message 'Only recognized SourceType are File/Directory'
                }
            }
        }
        else {
            Write-Warning -Message "Source does not exist -> $($deploy.Source)"
        }
    }
}
END {

}