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 .PARAMETER VMName VMname passed to Copy-VMfile for VM deployment .PARAMETER Deployment Deployment passed to Copy-VMfile for VM deployment .PARAMETER Authentication Authentication passed to Invoke-Command for remote deployment #> [cmdletbinding(DefaultParameterSetName='LocalCopyVMFile')] param ( [string]$VMname, # Specify the Hyper-V host name where the VM resides. Default - Localhost. [Parameter()] [Alias("HyperVServerName")] [String]$ComputerName=$env:COMPUTERNAME, [pscredential]$Credential, [Parameter(ValueFromPipeLine=$True)] [ValidateScript({ $_.PSObject.TypeNames[0] -eq 'PSDeploy.Deployment' })] [psobject[]]$Deployment ) Write-Verbose "Starting CopyVM deployment on VMnamed $ComputerName with $($Deployment.count) sources" [void]$PSBoundParameters.Remove('Deployment') $LocalCopyVMFileHash = @{} Try { $SourceHyperVHost = [System.Net.Dns]::GetHostEntry([string]$computername).HostName $LocalCopyVMFileHash.Add('ComputerName',$SourceHyperVHost) } Catch { Write-Warning -Message "Could not resolve the $ComputerName. Skipping it." #Throw "Could not determine Hyper-V host for $($Map.Source), skipping" } # Fail safe if the CreateFullPath is not specified in the Options under YML file if($Deployment.DeploymentOptions.CreateFullPath) { $LocalCopyVMFileHash.Add('CreateFullPath',[System.Management.Automation.SwitchParameter]::Present) } # Add the Deployment Options to the PSBound Parameters $Deployment.DeploymentOptions | Get-Member -MemberType NoteProperty | Where -Property Name -ne 'CreateFullpath' | select -ExpandProperty Name | foreach {$null = $LocalCopyVMFileHash.add("$PSitem",$Deployment.DeploymentOptions.$PSitem)} # Runs the local Copy-VMFile cmdlet (comes with Hyper-V module on Server 2012R2 + ) foreach($deploy in $Deployment) { if($deploy.SourceExists) { $Targets = $deploy.Targets foreach($Target in $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")" 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")" 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)" } } |