以前 Hyper-V の管理とか操作を調べていて管理ツール上の動作イメージサムネイルをどうやって取得しているのかな、と思ったら WMI を利用して取得していることを教えてもらったので、ついでにアクティビティにしてみました。
PowerShell での方法はこちらの MSDN Blog に書いてありますが、これの WF アクティビティ化したものになります。やっている事としては、Msvm_ComputerSystem に対して該当するゲスト OS の情報を取得しにいき、結果から Msvm_VirtualSystemsettingData の情報を取得。その値を元に、再度 Msvm_ComputerSystem を取得、GetVirtualSystemThumbnailImage メソッドの情報を取得した上でメソッドを呼び出す。言葉で書くと非常にわかりずらいですが、大体このような感じで実行すれば、ゲスト OS のサムネイルが取得できます。
1: Imports System.Activities
2: Imports System.Management
3:
4: Public MustInherit Class WMIExecuteActivityBase
5: Inherits AsyncCodeActivity
6:
7: Protected _target As String = ""
8: Protected _where As String = ""
9: Protected _service As String = ""
10:
11: Public Property Scope As InArgument(Of ManagementScope)
12: Public Property Results As OutArgument(Of List(Of Hashtable))
13:
14: Protected Delegate Function asyncExecuteWMIDelegate(ByVal target As String, ByVal whereCondition As String, ByVal wmScope As ManagementScope) As List(Of Hashtable)
15:
16: Protected Overrides Function BeginExecute(context As System.Activities.AsyncCodeActivityContext, callback As System.AsyncCallback, state As Object) As System.IAsyncResult
17: Dim currentScope = context.GetValue(Me.Scope)
18:
19: Dim asyncExecute = New asyncExecuteWMIDelegate(AddressOf ExecuteWMI)
20: context.UserState = asyncExecute
21:
22: Return asyncExecute.BeginInvoke(_target, _where, currentScope, callback, state)
23: End Function
24:
25: Protected Overrides Sub EndExecute(context As System.Activities.AsyncCodeActivityContext, result As System.IAsyncResult)
26: Dim asyncExecute = TryCast(context.UserState, asyncExecuteWMIDelegate)
27: Dim wmiResult = asyncExecute.EndInvoke(result)
28:
29: context.SetValue(Me.Results, wmiResult)
30: End Sub
31:
32: Protected Overridable Function ExecuteWMI(ByVal target As String, ByVal whereCondition As String, ByVal wmScope As ManagementScope) As List(Of Hashtable)
33:
34: End Function
35:
36: Protected Function CreateScope(ByVal wmScope As ManagementScope) As ManagementScope
37: If wmScope Is Nothing Then
38: wmScope = New ManagementScope("\\" + My.Computer.Name + "\root\" + _service)
39: End If
40: If Not wmScope.IsConnected Then wmScope.Connect()
41: Return wmScope
42: End Function
43:
44: End Class
これがベースとなるアクティビティで、実際にはこれを継承した形で作成しました。
1: Imports System.Activities
2: Imports System.Management
3: Imports System.Drawing
4: Imports System.IO
5:
6: Public Class WMIGetVMThumbnailActivity
7: Inherits WMIExecuteActivityBase
8:
9: Private _imageX As Integer = 320
10: Private _imageY As Integer = 240
11: Private _imageFile As String = ""
12:
13: Public Property VMName As InArgument(Of String)
14: Public Property ImageFileName As InArgument(Of String)
15: Public Property ImageSizeX As InArgument(Of Integer)
16: Public Property ImageSizeY As InArgument(Of Integer)
17:
18: Protected Overrides Function BeginExecute(ByVal context As System.Activities.AsyncCodeActivityContext, ByVal callback As System.AsyncCallback, ByVal state As Object) As System.IAsyncResult
19: MyBase._target = "Msvm_ComputerSystem "
20: MyBase._where = "Caption = '仮想マシン' and ElementName = '" + context.GetValue(Me.VMName) + "'"
21: MyBase._service = "virtualization"
22:
23: _imageX = context.GetValue(Me.ImageSizeX)
24: _imageY = context.GetValue(Me.ImageSizeY)
25: _imageFile = context.GetValue(Me.ImageFileName)
26:
27: Return MyBase.BeginExecute(context, callback, state)
28: End Function
29:
30: Protected Overrides Function ExecuteWMI(ByVal target As String, ByVal whereCondition As String, ByVal wmScope As System.Management.ManagementScope) As System.Collections.Generic.List(Of System.Collections.Hashtable)
31: Dim result As New List(Of Hashtable)
32: Try
33: wmScope = CreateScope(wmScope)
34:
35: Dim wmQuery As New ObjectQuery("SELECT * FROM " + target + " WHERE " + whereCondition)
36: Dim wmSearcher As New ManagementObjectSearcher(wmScope, wmQuery)
37: Dim wmVirtualSystem As ManagementObject = Nothing
38: For Each wmRes As ManagementObject In wmSearcher.Get
39: For Each wmVir As ManagementObject In wmRes.GetRelated("Msvm_VirtualSystemsettingData")
40: wmVirtualSystem = wmVir
41: Exit For
42: Next
43: Exit For
44: Next
45: If wmVirtualSystem Is Nothing Then Return result
46:
47: Dim wmVsmsQuery As New ObjectQuery("SELECT * FROM " + target + " WHERE " + whereCondition)
48: Dim wmVsmsSearcher As New ManagementObjectSearcher(wmScope, wmVsmsQuery)
49: For Each wmVsms As ManagementObject In wmVsmsSearcher.Get
50: Dim inParam = wmVsms.GetMethodParameters("GetVirtualSystemThumbnailImage")
51: inParam("WidthPixels") = _imageX
52: inParam("HeightPixels") = _imageY
53: inParam("TargetSystem") = wmVirtualSystem.Path.Path
54:
55: Dim wmMethodResult = wmVsms.InvokeMethod("GetVirtualSystemThumbnailImage", inParam, Nothing)
56: Dim wmImage() = CType(wmMethodResult("ImageData"), Byte())
57: My.Computer.FileSystem.WriteAllBytes(_imageFile, wmImage, False)
58: Exit For
59: Next
60:
61: Catch ex As Exception
62: result.Clear()
63: End Try
64: Return result
65: End Function
66:
67: End Class
このようなロジックになります。ただし、注意することが 1 点だけありまして、この方法で取得したイメージ(WriteAllBytes で保存している内容)は、画像の形式で言うと RAW となりますので、一般的な画像形式に変換してあげる必要があります。
0 件のコメント:
コメントを投稿