Project “Lift and Shift”–Phase 1: Triage

This is the first blog post in what is going to be a series that I am tagging “Lift and Shift”.

Recently, I had an experience that I know many people have had.  I discovered that my parents were approaching the age where it is no longer possible for them to safely live in their own house, without close support.  As my siblings and I started working through the process of figuring out how to ensure they were well looked after – I came across a somewhat unique problem.

Namely, my father has a substantial server infrastructure running in his house.  Specifically – he has three Hyper-V servers with dozens of virtual machines that operate the business infrastructure for a number of local businesses and family friends.  And it fell to me to figure out how we could safely, quickly shutdown this infrastructure without leaving anyone in the lurch.

This blog series is documenting the process that I am following to get this up and running.

So – where do we start?  Well, the first place to start is in understanding what we have to move.  The problem that I encountered here is that my fathers infrastructure had grown organically over the last couple of years, and no one was really sure about what was running where, and what was needed.

The approach I took here was to get on the phone with my father, connect to his systems with PowerShell, and start triaging.

The first thing I wanted to do was to identify any virtual machines that could just be deleted immediately.  To do this I ran the following chunk of code:

Remove-Module Hyper-V
Import-Module Hyper-V -RequiredVersion 1.1
$servers = @("WS08Core", "whvs12r21", "whvs12r23")
get-vm -ComputerName $servers | ? state -eq off | ? ReplicationMode -ne Replica

What this block of code does is:

  • Load the Hyper-V module for managing Windows Server 2012 R2
  • Create an array of all the Hyper-V Servers in my fathers environment
  • List all virtual machines that are off, but are not replicated virtual machines

We were able to delete most of the virtual machines that turned up in this list.

The second task was to go through each running virtual machine, and discuss what it did.  As we talked – I put notes in the virtual machine notes.  In this process we identified a number of virtual machines that we wanted to keep – but should be kept local as they were personal development virtual machines.

Finally, I needed to understand how much resource was needed for the running virtual machines that needed to be moved off-premises.  For this I ran this code:

$exclude = @("funnelweb", "cobol", "rubytest", "timstest", "centos6core")
get-vm -ComputerName $servers | ? ReplicationMode -ne Replica | ?{!$exclude.Contains($_.Name)} | select MemoryAssigned | Measure-Object -sum MemoryAssigned | %{$_.sum / 1GB}
get-vm -ComputerName $servers | ? ReplicationMode -ne Replica | ?{!$exclude.Contains($_.Name)} | Get-VMHardDiskDrive | %{get-vhd -Path $_.Path -ComputerName $_.ComputerName} | select FileSize | %{[long]$_.FileSize} | measure-object -sum | %{$_.sum / 1GB}

What this code does is:

  • Create an array of virtual machines that I do not want to look at
  • Get all virtual machines that are not replicas and are not in the excluded virtual machine set – and return the total Memory and Disk used by the virtual machines

When this was done I knew that we had a set of virtual machines that used about 58GB of RAM and 2.1 TB of disk.

The next challenge was to figure out where to move this to.


Cross-device experiences with Project Rome


Today we live in a multi-device world, and the way we use them spans different platforms and form factors: We read the morning news on our tablets, check email during the morning commute on our phones and use our desktop PCs when at work. At night, we watch movies on our home media consoles.

The Windows platform targets devices ranging from desktop PCs, laptops and smartphones, to large-screen hubs, HoloLens, wearable devices, IoT and Xbox. The device landscape is further diversified with Android and iOS devices, emerging VR/AR solutions, and new IoT products. This heterogeneous environment provides the average user with many choices and device options.

However, the tasks we perform on a daily basis (whether at home with family, or at work with colleagues) are not inherently device-centric, but rather human-centric. As we increase our device count and rely more on apps to run our lives, it is becoming more complicated to get things done.


Project Rome is a platform for creating experiences that transcend a single device so they can harmonize across devices – empowering a developer to create human-centric scenarios that move with the user and blur the lines between their devices regardless of form factor or platform. This vision is beginning to take shape in the Windows 10 Anniversary Update (Windows 10, Version 1607) with the Remote Systems API, enabling developers to extend their app experiences across Windows devices connected proximally or through the cloud.

This blog post covers the functionality of the Remote Systems API by walking through an example app experience built on Project Rome, and encourages developers to break down the barriers between devices to reduce friction and better serve your users’ needs.

Contoso Music App

Paul is a developer who has built a UWP app for streaming music. He has a growing user base and observes usage across a variety of Windows 10 devices. His telemetry shows installs occurring on phones, PCs and even Xbox. Identifying an opportunity, Paul sets out to a) reduce the friction of listening to music across these different devices and b) make it easier to get his app on other devices. Overall, he wants to ensure that his users can enjoy their great tunes all day, no matter where they are.

Paul decides to create a scenario where users can transfer the current song they are streaming over to a new device. Sample scenarios include listening to music on your phone then after arriving home, transferring to your Xbox; listening on your work PC then transferring to your phone to go for a walk, etc. All the tools he needs are available from Project Rome, namely, the Remote Systems API.


Discovering Devices

The first step for Paul to introduce an effective cross-device experience is the discovery of other devices from the host device, and subsequent connection to the target device.

Paul can implement device discovery over Wi-Fi and Bluetooth Low Energy (BLE) when the target device is in proximity, or via the Cloud. This discovery is provided by the RemoteSystemWatcher class, which selects the optimal transport given the scenario; the target devices do not require any special code implemented in order to be discoverable. Should he desire some advanced features for more targeted discovery, Paul can implement filters on RemoteSystemWatcher for discovery type, device type and availability status of the discovered devices. He can also connect to a device directly by IP address.

Wrapping this functionality in a simple control within his app, the watcher is started when a user opens the control. RemoteSystemAdded events are fired when new devices are discovered (given they meet the filter conditions) and Paul can build a device list to populate the control with friendly device names for the user to select.


Before connecting to a device, Paul must call the RequestAccessAsync() method to ensure his app is allowed to access remote devices (this is satisfied by declaring the “remoteSystem” capability in the application manifest). Once all conditions are met, connection is one click away and the doors are open for Paul to take his music experience across device barriers.


Connecting and Launching an Experience

Launching an app experience to a remote device is done using the RemoteLauncher.LaunchUriAsync API (an existing API that has been extended to work across devices). Prior to launching, a connection is established by passing a RemoteSystem object into RemoteSystemConnectionRequest(). Paul leverages these APIs to specify the device the user has selected for connection, as well as to provide the payload required to launch the current song that was playing (using his “contosoapp:” protocol activation, also defined in the app’s manifest).


He also provides a URI of his website, promoting the installation of his app to use as a fallback should the target device not have his app installed. Less than an hour after getting started, Paul wraps up his coding and starts preparing the update for shipping to his users.

Messaging Between Connected Devices

Several months later and pleased with both the user feedback on his app as well as the growing engagement and installs, Paul decides to further augment the user experience by implementing the ability to message between connected devices, enabling remote control experience for his music app. With Remote Systems already enabled, he can do this easily by leveraging app services on remote devices. Remote app services enable a foreground app on a host device to invoke application functionality on the target device (given the app is installed on the target).

Paul already has a local app service in his app that allows other applications to control music playback; to enable remote functionality for his service, he simply adds <SupportsRemoteSystems=”true”> to his AppService element in the appx manifest. Next, in his app code that connects and launches to remote devices, he instantiates an AppServiceConnection object and creates a RemoteSystemConnectionRequest object for the target device, thereby opening a connection to an app service on the remote target device.

After that, Paul is done with the heavy lifting and he now has a channel for sending and receiving messages to and from the app service – enabling him to create a companion experience for controlling music playback on the host device.



Wrapping Up

Project Rome breaks down barriers across all Windows devices and creates experiences that are no longer constrained to a single device. The Remote Systems API available in Windows 10 is a key piece of Project Rome that provides exposure of the device graph and the ability to connect and command – this is fundamental for driving user engagement and productivity for applications across all devices.

Going forward, we are excited to continue building on our vision and collaborating with the developer community – our aim is to empower developers to enable compelling and productive experiences for users — no matter what device they are using.

To learn more and browse sample code, including the snippets shown above, please check out the following articles and blog posts:

Download Visual Studio to get started.

The Windows team would love to hear your feedback.  Please keep the feedback coming using our Windows Developer UserVoice site. If you have a direct bug, please use the Windows Feedback tool built directly into Windows 10.


Waiting for VMs to restart in a complex configuration script with PowerShell Direct

Have you ever tried to automate the setup of a complex environment including the base OS, AD, SQL, Hyper-V and other components?

For my demo at Ignite 2016 I did just that.  I would like to share a few things I learned while writing a single PowerShell script that builds the demo environment from scratch. The script heavily uses PowerShell Direct and just requires the installation sources put into specific folders.

In this blog post I’d like to provide solutions for two challenges that I came across:

  • Determining when a virtual machine is ready for customization using PowerShell Direct, and – as a variation of that theme –
  • Determining when Active Directory is fully up and running in a fully virtualized PoC/demo environment.

Solution #1 Determining when a virtual machine is ready for customization using PowerShell Direct

Some guest OS operations require multiple restarts. If you’re using a simple approach to automate everything from a single script and check for the guest OS to be ready, things might go wrong. For example, with a naïve PowerShell Direct call using Invoke-Command, the script might resume while the virtual machine is restarting multiple times to finish up role installation. This can lead to unpredictable behavior and break scripts.

One solution is using a wrapper function like this:

This wrapper function first makes sure that the virtual machine is running, if not, the VM is started. If the heartbeat integration component is enabled for the VM, it will also wait for a proper heartbeat status – this resolves the multiple-reboot issue mentioned above. Afterwards, it waits for a proper PowerShell Direct connection. Both wait operations have time-outs to make sure script execution is not blocked perpetually. Finally, the provided script block is run passing through arguments.

Solution #2 Determining when Active Directory is fully up and running

Whenever a Domain Controller is restarted, it takes some time until the full AD functionality is available.  If you use a VMConnect session to look at the machine during this time, you will see the status message “Applying Computer Settings”.  Even with the Invoke-CommandWithPSDirect wrapper function above, I noticed some calls, like creating a new user or group, will fail during this time.

In my script, I am therefore waiting for AD to be ready before continuing:

This function leverages the Invoke-CommandWithPSDirect function to ensure the VM is up and running. To make sure that Active Directory works properly, it then requests the local computer’s AD object until this call succeeds.

Using these two functions has saved me quite some headache. For additional tips, you can also take a look at Ben’s tips around variables and functions.



PS: The full script for building the guarded fabric demo environment for Ignite 2016’s session BRK3124: Dive into Shielded VMs with Windows Server 2016 Hyper-V will be shared through our Virtualization Documentation GitHub.