-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathRemoteHyperVModel.cs
152 lines (122 loc) · 4.69 KB
/
RemoteHyperVModel.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Security;
using static cmdwtf.Toolkit.IEnumerable;
namespace HyperVPeek
{
public class RemoteHyperVModel
{
// WIM Class Names
private const string MsvmVirtualSystemManagementService = "Msvm_VirtualSystemManagementService";
private const string MsvmComputerSystem = "Msvm_ComputerSystem";
// Property Names
private const string ElementName = "ElementName";
private const string Caption = "Caption";
// Method Names
private const string GetVirtualSystemThumbnailImage = "GetVirtualSystemThumbnailImage";
// Values
private const string VirtualMachineCaption = "Virtual Machine";
// Argument names
private const string TargetSystem = "TargetSystem";
private const string WidthPixels = "WidthPixels";
private const string HeightPixels = "HeightPixels";
private const string ImageData = "ImageData";
public ConnectionState ConnectionState
{
get
{
if (_session is not null && _virtualSystemManagementService is not null)
{
return ConnectionState.Connected;
}
else if (_session is not null)
{
return ConnectionState.Connecting;
}
return ConnectionState.Disconnected;
}
}
public bool IsLocal { get; private set; }
internal string LastVmTargeted { get; set; } = string.Empty;
private CimSession? _session;
private CimInstance? _virtualSystemManagementService;
public bool Connect(string domain, string hostname, string username, SecureString password)
{
if (ConnectionState == ConnectionState.Connected)
{
return false;
}
CimCredential creds = new(PasswordAuthenticationMechanism.Default, domain, username, password);
using WSManSessionOptions options = new()
{
Timeout = TimeSpan.FromSeconds(1.0),
MaxEnvelopeSize = (1024 * 1024), // 1MB envelope size.
};
// compare local domain / machine name to target
var ipgp = IPGlobalProperties.GetIPGlobalProperties();
bool noDomain = string.IsNullOrWhiteSpace(domain)
|| domain == "."
|| domain.Equals(ipgp.DomainName, StringComparison.OrdinalIgnoreCase);
bool noTargetMachine = string.IsNullOrWhiteSpace(hostname)
|| hostname == "."
|| hostname.Equals(Environment.MachineName, StringComparison.OrdinalIgnoreCase)
|| hostname.Equals(ipgp.HostName, StringComparison.OrdinalIgnoreCase);
IsLocal = noDomain && noTargetMachine;
// can't use creds on the local machine
if (!IsLocal)
{
options.AddDestinationCredentials(creds);
}
_session = IsLocal
? CimSession.Create(null, options)
: CimSession.Create(hostname, options);
_virtualSystemManagementService = _session.SelectAll(MsvmVirtualSystemManagementService).First();
return true;
}
public bool Disconnect()
{
if (ConnectionState == ConnectionState.Disconnected)
{
return false;
}
_session?.Dispose();
_session = null;
_virtualSystemManagementService?.Dispose();
_virtualSystemManagementService = null;
return true;
}
public IEnumerable<string> GetVirtualMachineList()
{
IEnumerable<CimInstance> systemsQuery = _session?.Select(ElementName, $"{MsvmComputerSystem} where {Caption} = '{VirtualMachineCaption}'")
?? Array.Empty<CimInstance>();
return systemsQuery.Select
(s => s.CimInstanceProperties[ElementName]?.Value?.ToString())
.NotNull();
}
public byte[] GetVirtualMachinePreview(string systemName, ushort imageWidth, ushort imageHeight)
{
using CimInstance? vm = _session?.SelectAll($"{MsvmComputerSystem} where {ElementName} = '{systemName}'").First();
if (vm == null)
{
throw new RemoteHyperVException($"Failed to find virtual machine named {systemName}");
}
CimMethodParametersCollection parameters = new()
{
CimMethodParameter.Create(TargetSystem, vm, CimType.Reference, CimFlags.In),
CimMethodParameter.Create(WidthPixels, imageWidth, CimFlags.In),
CimMethodParameter.Create(HeightPixels, imageHeight, CimFlags.In),
};
CimMethodResult? result = _session?.InvokeMethod(_virtualSystemManagementService, GetVirtualSystemThumbnailImage, parameters);
return result?.OutParameters[ImageData].Value is not byte[] imageData || imageData.Length == 0
? throw new RemoteHyperVException($"Failed to get image data for {systemName}")
: imageData;
}
public bool SetMaxEnvelopeSize(uint sizeKilobytes)
=> ConnectionState == ConnectionState.Connected
&& _session?.SetMaxEnvelopeSize(sizeKilobytes) == 0;
}
}