Created
November 27, 2019 06:54
-
-
Save benpye/4d011e65abc4d9c585b8a59f877a2d29 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Drawing; | |
using System.Linq; | |
using System.Windows.Forms; | |
using Microsoft.Management.Infrastructure; | |
using Microsoft.Management.Infrastructure.Options; | |
namespace VirtualMachineTray | |
{ | |
static class Program | |
{ | |
/// <summary> | |
/// The main entry point for the application. | |
/// </summary> | |
[STAThread] | |
static void Main() | |
{ | |
Application.SetHighDpiMode(HighDpiMode.SystemAware); | |
Application.EnableVisualStyles(); | |
Application.SetCompatibleTextRenderingDefault(false); | |
Application.Run(new VmTrayContext()); | |
} | |
} | |
internal struct VirtualMachine | |
{ | |
public string Name; | |
public string Guid; | |
public bool Running; | |
} | |
internal class VmTrayContext : ApplicationContext | |
{ | |
private NotifyIcon trayIcon; | |
private System.Threading.Timer timer; | |
private CimSession session; | |
internal VmTrayContext() | |
{ | |
var sessionOptions = new DComSessionOptions | |
{ | |
Timeout = TimeSpan.FromSeconds(30) | |
}; | |
session = CimSession.Create("localhost", sessionOptions); | |
trayIcon = new NotifyIcon() | |
{ | |
Visible = false, | |
}; | |
UpdateTrayIcon(); | |
trayIcon.Visible = true; | |
timer = new System.Threading.Timer((object state) => UpdateTrayIcon(), null, 1000, 1000); | |
} | |
private void UpdateTrayIcon() | |
{ | |
var vms = GetVirtualMachines(); | |
var vmCount = vms.Count(); | |
var runningCount = vms.Where(v => v.Running).Count(); | |
trayIcon.Text = RunningString(runningCount); | |
trayIcon.Icon = GetTrayIcon(runningCount > 0); | |
trayIcon.ContextMenu = new ContextMenu(); | |
if (vmCount > 0) | |
{ | |
foreach (var vm in vms) | |
{ | |
var state = vm.Running ? " [Running]" : ""; | |
trayIcon.ContextMenu.MenuItems.Add(new MenuItem( | |
$"{vm.Name}{state}", (object s, EventArgs a) => OpenVmConnect(vm.Name, vm.Guid) | |
)); | |
} | |
trayIcon.ContextMenu.MenuItems.Add(new MenuItem("-")); | |
} | |
trayIcon.ContextMenu.MenuItems.Add(new MenuItem("Open Hyper-V Manager", (object s, EventArgs a) => StartVmManager())); | |
} | |
private string RunningString(int count) | |
{ | |
if (count == 0) | |
{ | |
return "No virtual machines running"; | |
} | |
else if (count == 1) | |
{ | |
return "1 virtual machine running"; | |
} | |
else | |
{ | |
return $"{count} virtual machines running"; | |
} | |
} | |
private void OpenVmConnect(string vmName, string vmGuid) | |
{ | |
ProcessStartInfo psi = new ProcessStartInfo("vmconnect"); | |
psi.ArgumentList.Add("localhost"); | |
psi.ArgumentList.Add(vmName); | |
psi.UseShellExecute = true; | |
psi.Verb = "runas"; | |
Process.Start(psi); | |
} | |
private void StartVmManager() | |
{ | |
ProcessStartInfo psi = new ProcessStartInfo("mmc"); | |
psi.ArgumentList.Add("virtmgmt.msc"); | |
psi.UseShellExecute = true; | |
psi.Verb = "runas"; | |
Process.Start(psi); | |
} | |
private Icon GetTrayIcon(bool running) | |
{ | |
var font = new Font("Segoe MDL2 Assets", 12, FontStyle.Regular); | |
var iconBrush = new SolidBrush(Color.Black); | |
var indicatorBrush = new SolidBrush(running ? Color.Red : Color.Lime); | |
var bitmap = new Bitmap(16, 16); | |
var g = Graphics.FromImage(bitmap); | |
IntPtr icon; | |
g.Clear(Color.Transparent); | |
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel; | |
g.DrawString("\uE977", font, iconBrush, -3, 0); | |
g.FillEllipse(indicatorBrush, 8, 8, 8, 8); | |
icon = bitmap.GetHicon(); | |
return Icon.FromHandle(icon); | |
} | |
private IEnumerable<VirtualMachine> GetVirtualMachines() | |
{ | |
var instances = session.EnumerateInstances(@"root\virtualization\v2", "Msvm_ComputerSystem"); | |
return instances | |
.Where(i => (string)i.CimInstanceProperties["Caption"].Value != "Hosting Computer System") | |
.Select(i => new VirtualMachine() | |
{ | |
Name = (string)i.CimInstanceProperties["ElementName"].Value, | |
Guid = (string)i.CimInstanceProperties["Name"].Value, | |
Running = (UInt16)i.CimInstanceProperties["EnabledState"].Value == 2 | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment