Hyper-V On-The-Go – Sending Files to Your VMs (Part 1)

I was playing around with learning Microsoft Identity Manager (MIM) recently, trying to get it up and running in one of my labs. During the initial installation, it turned out there were several files and patches I needed to install as prerequisites.

I have a pretty firm rule about not allowing my lab VMs/VNets direct or indirect access to the internet, with just a few exceptions. This is to ensure no nasties get downloaded into my VMs and also for my own piece of mind.
In the interest of full disclosure, when running labs in a portable environment, especially without the benefit of running a Hyper-V host, routing is a bit more daunting to confgure and requires a manual method for recalling/documenting your configurations.

This made downloading these files directly from the VM problematic and I did NOT want to add an external NIC to each VM and configure it evey time I needed a file from the internet.

Whatever is a grumpy old admin to do?!?

My solution drew out of method I employed using ISOs with VM’s in the production lab at one of my previous employers. My job at the time was managing the Group Policies for both our Lab and Production environments. This meant I was constantly transporting updated GPO’s back and forth between the Lab and Production. I needed to create a lot of ISO images and decided that PowerShell would be the easiest method to get this done.

As I was setting the file transfers up it occurred to me that this would make a great addition to the “Boldly Going” series (especially handy since I was at a loss for a topic this month). So let’s jump into it and move some files!

There’s always more than one way to skin a Warp Core!

There are a few ways to get files from your host system into a VM. These include (but are not necessarily limited to):

  1. ISO transfer
  2. PowerShell Cmdlet transfer
  3. Direct VHD Transfer
  4. Network Transfer

The fourth option (Network Transfer) is problematic as explained earlier and so I will not be covering that option in this series. The other three options each merit their own blog entry so I will break those down individually. I will cover option One in this blog and cover options two and three in later blogs.

Creating ISO’s to insert into a VM

The method I’m about to demonstrate is part of my concept of what I call Semi-Automatic Administration. This is using pieces of code to manually run an automated process or to automate part of a process (ie when automating the whole process is not feasible or the ROI is not worth the effort).
This process uses a script file (Drag2ISO.ps1), and batch file (2Burn.cmd) and a link placed on your desktop.

The PowerShell Engine

My script is based off of Chris Wu’s New-IsoFile function located in the PS Gallery Here.

Drag2ISO.ps1

Param ($srcDir)
Function New-IsoFile
{
     
    Param
    ( 
        [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]$Source,
        [parameter(Position=1,Mandatory=$false,ValueFromPipeline=$true)][Alias('Path')]
        [String] $trgPath = "$($env:userprofile)\Desktop\$((Get-Date).ToString("yyyyMMdd-HHmmss.ffff")).iso", 
        [string] $BootFile = $null, 
        [string] $Media = "Disk", 
        [string] $Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"), 
        [switch] $Force 
    )
    Begin
    {
        # Decode here string for ISO public class definition
        Function Dec64($a){$b = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($a));Return $b} #
        ($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = "/unsafe" 
        If (!("ISOFile" -as [type]))
        { 
            $Type = (Dec64 "cHVibGljIGNsYXNzIElTT0ZpbGUNCnsNCiAgICBwdWJsaWMg
                dW5zYWZlIHN0YXRpYyB2b2lkIENyZWF0ZShzdHJpbmcgUGF0aCwgb2JqZWN
                0IFN0cmVhbSwgaW50IEJsb2NrU2l6ZSwgaW50IFRvdGFsQmxvY2tzKQ0KIC
                AgIHsNCiAgICAgICAgaW50IGJ5dGVzID0gMDsNCiAgICAgICAgYnl0ZVtdI
                GJ1ZiA9IG5ldyBieXRlW0Jsb2NrU2l6ZV07DQogICAgICAgIFN5c3RlbS5J
                bnRQdHIgcHRyID0gKFN5c3RlbS5JbnRQdHIpKCZieXRlcyk7DQogICAgICA
                gIFN5c3RlbS5JTy5GaWxlU3RyZWFtIG8gPSBTeXN0ZW0uSU8uRmlsZS5PcG
                VuV3JpdGUoUGF0aCk7DQogICAgICAgIFN5c3RlbS5SdW50aW1lLkludGVyb
                3BTZXJ2aWNlcy5Db21UeXBlcy5JU3RyZWFtIGkgPSBTdHJlYW0gYXMgU3lz
                dGVtLlJ1bnRpbWUuSW50ZXJvcFNlcnZpY2VzLkNvbVR5cGVzLklTdHJlYW0
                7DQoNCiAgICAgICAgaWYgKG8gPT0gbnVsbCkgeyByZXR1cm47IH0NCiAgIC
                AgICAgd2hpbGUgKFRvdGFsQmxvY2tzLS0gPiAwKSB7DQogICAgICAgICAgI
                CBpLlJlYWQoYnVmLCBCbG9ja1NpemUsIHB0cik7IG8uV3JpdGUoYnVmLCAw
                LCBieXRlcyk7DQogICAgICAgIH0NCiAgICAgICAgby5GbHVzaCgpOyBvLkN
                sb3NlKCk7DQogICAgfQ0KfQ==")
            Add-Type -CompilerParameters $cp -TypeDefinition $Type #-IgnoreWarnings
        } #If
        If ($BootFile -and (Test-Path $BootFile))
        { 
            ($Stream = New-Object -ComObject ADODB.Stream).Open() 
            $Stream.Type = 1  # adFileTypeBinary 
            $Stream.LoadFromFile((Get-Item $BootFile).Fullname) 
            ($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream) 
        } #If 
        $MediaType = [Ordered]@{BDR=18; BDRE=19;CDR=2; CDRW=3;DISK=12;
                        DVDDASHR=9;DVDDASHRW=10;DVDDASHR_DUALLAYER=11;
                        DVDPLUSR=6; DVDPLUSRW=7;DVDPLUSR_DUALLAYER=8;
                        DVDPLUSRW_DUALLAYER=13;DVDRAM=5;} #MediaType
        If ($MediaType[$Media] -eq $null)
        {
            write-debug "Unsupported Media Type: $Media";
            write-debug ("Choose one from: " + $MediaType.Keys);
            Break
        } #If
        ($Image = new-object -com IMAPI2FS.MsftFileSystemImage `
            -Property @{VolumeName=$Title}).ChooseImageDefaultsForMediaType($MediaType[$Media]) 
        If ((Test-Path $trgPath) -and (!$Force))
        {
            "File Exists $trgPath"
            Break
        } 
        If (!($Target = New-Item -Path $trgPath -ItemType File -Force))
        {
            "Cannot create file $trgPath"
            Break
        } 
    } #Begin
    Process { 
        Switch ($Source)
        { 
            { $_ -is [string] }
                    {
                        $Image.Root.AddTree((Get-Item $_).FullName, $true)
                        continue
                    } 
            { $_ -is [IO.FileInfo] }
                    {
                        $Image.Root.AddTree($_.FullName, $true)
                        continue
                    } 
            { $_ -is [IO.DirectoryInfo] }
                    {
                        $Image.Root.AddTree($_.FullName, $true)
                        continue
                    } 
        }#Switch 
    } #Process 
    End
    { 
        If ($Boot)
        {
            $Image.BootImageOptions=$Boot
        } 
        $Result = $Image.CreateResultImage() 
        [ISOFile]::Create($Target.FullName,$Result.ImageStream,$Result.BlockSize,$Result.TotalBlocks) 
        $Target 
    } #End 

}
If ((Test-Path $srcDir) -eq $False){}
# IyBJRVggIkZ1bmN0aW9uIE5ldy1Jc29GaWxlIHtgbiROZXdJU09gbmB0fSAjTmV3LUlzb0ZpbGUi
$writeDate = Get-Date -f yyyyMMdd
GCI $srcDir |
    New-ISOFile -Path "$srcDir.iso" `
                -Title "$($srcDir.Replace(' ','_').Split('\')[-1])-$writeDate)" `
                -Force

The Command line Engine

The batch file portion passes the dragged folder info to the Powershell script which then copies to files into an ISO file.

2Burn.cmd

@Title=Creating ISO Image from [%1]
@If []==[%1] Exit
@Set pthPS=%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
@Set pthScript=%OneDriveConsumer%\Drag2ISO.ps1
@"%pthPS%" -NoProfile -ExecutionPolicy Bypass -File "%pthScript%" -srcDir %1
@Timeout /T 10

The Override Button on your Desktop

Place both files in a directory of your choice but be sure the batch file points to the correct folder for the PS1 file (4th line). I settled on the root folder of my personal OneDrive so that it would be available across most of my machines.

Because we are trying to create a Drag-&-Drop process we need to add a link to the batch file onto our desktop. Create the shortcut, rename it to your pleasure and, if you want, give it a new icon. I do this to make it easier to find it on my desktop when I need it. I have included screen-shots fo r changing the icons below:

Right-Click on the link you created and open the properties. Change
the icon and select OK to open the default icon file.
Choose the Icon you want to use and click OK to apply it
Note the Icon has changed
Click OK to save your changes  
Now we’re ready to collect the files!

Building the image to fix the ship

This process will ISO-wrap either a single file OR multiple files in a single folder (and any sub-folders). In either case, the ISO file will be created in the same folder as the original.

Now we’re ready to create the ISO. In Windows Explorer, navigate to the folder where you downloaded/copied the file needed on the VM and select it (if you’re copying multiple files, move up one folder level and select the folder containing the files).

Now drag the file/folder to the link on your desktop and drop it. The ISO should be created immediately or after several seconds (depending on the size of your file(s)). The command window will indicate when the file has been created and will close automatically after 10 seconds.

The ISO has been created.

Now all that’s left is to connect the ISO to your VM and copy the files to its HDD (or run them from the ISO).

Warping along on a wing and a prayer

Once the scripts and links are in place, I have found this to be the quickest method for getting files onto your VMs. But different situations demand different solutions to a problem and I will be covering the other two solutions in other blogs. Until then “Lab long and prosper!“.

More Blogs in the ‘Boldly Going” Series

  1. Hardware Considerations for Portable Labs
  2. Enabling the Hyper-V Engine
  3. Reclaiming Drivespace
  4. Sending Files to Your VMs (Part 1)
  5. Sending Files to Your VMs (Part 2)
  6. Sending Files to Your VMs (Part 3)
  7. Changing the Lab VM State

Authors