第 7 章 - WMI の操作Chapter 7 - Working with WMI

WMI と CIMWMI and CIM

PowerShell には、Windows Management Instrumentation (WMI) など、その他のテクノロジを操作するためのコマンドレットが既定で付属しています。PowerShell ships by default with cmdlets for working with other technologies such as Windows Management Instrumentation (WMI). PowerShell にはネイティブな WMI コマンドレットがいくつもあり、追加のソフトウェアやモジュールをインストールする必要がありません。There are several native WMI cmdlets that exist in PowerShell without having to install any additional software or modules.

PowerShell には、WMI を操作するためのコマンドレットが最初から備わっています。PowerShell has had cmdlets for working with WMI since the beginning. PowerShell にどのような WMI コマンドレットがあるのかを特定するには、Get-Command を使用できます。Get-Command can be used to determine what WMI cmdlets exist in PowerShell. 次の結果は、PowerShell バージョン 5.1 を実行している Windows 10 ラボ環境コンピューターからのものです。The following results are from my Windows 10 lab environment computer that is running PowerShell version 5.1. 実行している PowerShell バージョンによっては、結果が異なる場合があります。Your results may differ depending on what PowerShell version you're running.

Get-Command -Noun WMI*
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Cmdlet          Get-WmiObject                                      3.1.0.0    Microsof...
Cmdlet          Invoke-WmiMethod                                   3.1.0.0    Microsof...
Cmdlet          Register-WmiEvent                                  3.1.0.0    Microsof...
Cmdlet          Remove-WmiObject                                   3.1.0.0    Microsof...
Cmdlet          Set-WmiInstance                                    3.1.0.0    Microsof...

Common Information Model (CIM) コマンドレットは、PowerShell バージョン 3.0 で導入されました。Common Information Model (CIM) cmdlets were introduced in PowerShell version 3.0. CIM コマンドレットは、Windows マシンと Windows 以外のマシンの両方で使用できるように設計されています。The CIM cmdlets are designed so they can be used on both Windows and non-Windows machines. WMI コマンドレットは非推奨化されているため、古い WMI ではなく CIM コマンドレットを使用することをお勧めします。The WMI cmdlets are deprecated so my recommendation is to use the CIM cmdlets instead of the older WMI ones.

CIM コマンドレットはすべて、モジュール内に含まれています。The CIM cmdlets are all contained within a module. CIM コマンドレットの一覧を取得するには、次の例に示すように、Module パラメーターを指定して Get-Command を使用します。To obtain a list of the CIM cmdlets, use Get-Command with the Module parameter as shown in the following example.

Get-Command -Module CimCmdlets
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Cmdlet          Export-BinaryMiLog                                 1.0.0.0    CimCmdlets
Cmdlet          Get-CimAssociatedInstance                          1.0.0.0    CimCmdlets
Cmdlet          Get-CimClass                                       1.0.0.0    CimCmdlets
Cmdlet          Get-CimInstance                                    1.0.0.0    CimCmdlets
Cmdlet          Get-CimSession                                     1.0.0.0    CimCmdlets
Cmdlet          Import-BinaryMiLog                                 1.0.0.0    CimCmdlets
Cmdlet          Invoke-CimMethod                                   1.0.0.0    CimCmdlets
Cmdlet          New-CimInstance                                    1.0.0.0    CimCmdlets
Cmdlet          New-CimSession                                     1.0.0.0    CimCmdlets
Cmdlet          New-CimSessionOption                               1.0.0.0    CimCmdlets
Cmdlet          Register-CimIndicationEvent                        1.0.0.0    CimCmdlets
Cmdlet          Remove-CimInstance                                 1.0.0.0    CimCmdlets
Cmdlet          Remove-CimSession                                  1.0.0.0    CimCmdlets
Cmdlet          Set-CimInstance                                    1.0.0.0    CimCmdlets

CIM コマンドレットでは引き続き WMI を操作できます。そのため、他のユーザーが "PowerShell CIM コマンドレットを使用して WMI のクエリを実行するとき" と言っても、混乱しないようにしてください。The CIM cmdlets still allow you to work with WMI so don't be confused when someone makes the statement "When I query WMI with the PowerShell CIM cmdlets..."

前述したように、WMI は PowerShell とは別個のテクノロジであり、ユーザーは WMI にアクセスするために CIM コマンドレットを使用しているだけです。As I previously mentioned, WMI is a separate technology from PowerShell and you're just using the CIM cmdlets for accessing WMI. 次の例のように、WMI Query Language (WQL) を使用して WMI のクエリを実行する古い VB スクリプトが見つかる場合があります。You may find an old VBScript that uses WMI Query Language (WQL) to query WMI such as in the following example.

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colBIOS = objWMIService.ExecQuery _
    ("Select * from Win32_BIOS")

For each objBIOS in colBIOS
    Wscript.Echo "Manufacturer: " & objBIOS.Manufacturer
    Wscript.Echo "Name: " & objBIOS.Name
    Wscript.Echo "Serial Number: " & objBIOS.SerialNumber
    Wscript.Echo "SMBIOS Version: " & objBIOS.SMBIOSBIOSVersion
    Wscript.Echo "Version: " & objBIOS.Version
Next

その VB スクリプトから WQL クエリを取得して、変更することなく Get-CimInstance コマンドレットで使用できます。You can take the WQL query from that VBScript and use it with the Get-CimInstance cmdlet without any modifications.

Get-CimInstance -Query 'Select * from Win32_BIOS'
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 3810-1995-1654-4615-2295-2755-89
Version           : VRTUAL - 4001628

これは、PowerShell で WMI のクエリを実行する通常の方法ではありません。That's not how I typically query WMI with PowerShell. しかし、これは問題なく使えて、既存の VB スクリプトを PowerShell に簡単に移行できます。But it does work and allows you to easily migrate existing VBScripts to PowerShell. WMI のクエリを実行するワンライナーの記述に取り掛かる際には、次の構文を使用します。When I start out writing a one-liner to query WMI, I use the following syntax.

Get-CimInstance -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 3810-1995-1654-4615-2295-2755-89
Version           : VRTUAL - 4001628

シリアル番号だけが必要な場合は、出力を Select-Object にパイプ処理して、SerialNumber プロパティのみを指定できます。If I only want the serial number, I can pipe the output to Select-Object and specify only the SerialNumber property.

Get-CimInstance -ClassName Win32_BIOS | Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

既定では、使用されることがないのに背後で取得されるプロパティがいくつかあります。By default, there are several properties that are retrieved behind the scenes that are never used. これは、ローカル コンピューター上で WMI のクエリを実行するときにはそれほど問題にならないでしょう。It may not matter much when querying WMI on the local computer. しかし、リモート コンピュートに対するクエリを開始すると、その情報を返すのに追加の処理時間がかかるだけでなく、必要ない余計な情報をネットワーク経由でプルしなければならなくなります。But once you start querying remote computers, it's not only additional processing time to return that information, but also additional unnecessary information to have to pull across the network. Get-CimInstance には、取得される情報を制限する Property パラメーターがあります。Get-CimInstance has a Property parameter that limits the information that's retrieved. これにより、WMI へのクエリの効率が向上します。This makes the query to WMI more efficient.

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

前の結果ではオブジェクトが返されました。The previous results returned an object. 単純な文字列を返すには、ExpandProperty パラメーターを使用します。To return a simple string, use the ExpandProperty parameter.

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
Select-Object -ExpandProperty SerialNumber
3810-1995-1654-4615-2295-2755-89

単純な文字列を返すには、ピリオドを使うスタイルの構文を使用することもできます。You could also use the dotted style of syntax to return a simple string. そうすれば Select-Object にパイプ処理する必要がありません。This eliminates the need to pipe to Select-Object.

(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
3810-1995-1654-4615-2295-2755-89

CIM コマンドレットによるリモート コンピューターへのクエリ実行Query Remote Computers with the CIM cmdlets

引き続き、ドメイン ユーザーであるローカル管理者として PowerShell を実行しています。I'm still running PowerShell as a local admin who is a domain user. Get-CimInstance コマンドレットを使用してリモート コンピューターから情報のクエリを実行しようとすると、アクセス拒否のエラー メッセージが表示されます。When I try to query information from a remote computer using the Get-CimInstance cmdlet, I receive an access denied error message.

Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
Get-CimInstance : Access is denied.
At line:1 char:1
+ Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
+ ``````````````````````````````````````````````````````~~
    + CategoryInfo          : PermissionDenied: (root\cimv2:Win32_BIOS:String) [Get-CimI
   nstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80070005,Microsoft.Management.Infrastructure.Cim
   Cmdlets.GetCimInstanceCommand
    + PSComputerName        : dc01

多くのユーザーが PowerShell のセキュリティについて懸念を抱いていますが、実際のところ、PowerShell でユーザーが付与されるアクセス許可は GUI とまったく同じです。Many people have security concerns when it comes to PowerShell, but the truth is you have exactly the same permissions in PowerShell as you do in the GUI. それ以上でも以下でもありません。No more and no less. 前の例の問題は、PowerShell を実行しているユーザーに、DC01 サーバーから WMI 情報のクエリを実行する権限がないことです。The problem in the previous example is that the user running PowerShell doesn't have rights to query WMI information from the DC01 server. Get-CimInstance には Credential パラメーターがないため、ドメイン管理者として PowerShell を再起動することができます。I could relaunch PowerShell as a domain administrator since Get-CimInstance doesn't have a Credential parameter. ただし、PowerShell から実行する内容がすべてドメイン管理者として実行されるため、この方法はお勧めできません。セキュリティの観点からすると、これは状況によっては危険な場合があります。But, trust me, that isn't a good idea because then anything that I run from PowerShell would be running as a domain admin. That could be dangerous from a security standpoint depending on the situation.

最小限の特権の原則に従って、Credential パラメーター (コマンドにある場合) を使用し、コマンドごとにドメイン管理アカウントに昇格します。Using the principle of least privilege, I elevate to my domain admin account on a per command basis using the Credential parameter, if a command has one. Get-CimInstance には Credential パラメーターがないため、このシナリオの解決策は、CimSession を先に作成することです。Get-CimInstance doesn't have a Credential parameter so the solution in this scenario is to create a CimSession first. 次に、コンピューター名の代わりに CimSession を使用して、リモート コンピューター上の WMI のクエリを実行します。Then I use the CimSession instead of a computer name to query WMI on the remote computer.

$CimSession = New-CimSession -ComputerName dc01 -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

CIM セッションは、$CimSession という名前の変数に格納されました。The CIM session was stored in a variable named $CimSession. 先に実行されるようにかっこ内で Get-Credential コマンドレットを指定したことにも注目してください。これで、新しいセッションが作成される前に、代替の資格情報が要求されます。Notice that I also specified the Get-Credential cmdlet in parentheses so that it executes first, prompting me for alternate credentials, before creating the new session. この章の後半で、代替の資格情報を指定する、より効率的な別の方法を紹介しますが、複雑化する前にこの基本的な概念を理解しておくことが重要です。I'll show you another more efficient way to specify alternate credentials later in this chapter, but it's important to understand this basic concept before making it more complicated.

前の例で作成した CIM セッションを Get-CimInstance コマンドレットと共に使用して、リモート コンピューター上の WMI から BIOS 情報を照会できるようになりました。The CIM session created in the previous example can now be used with the Get-CimInstance cmdlet to query the BIOS information from WMI on the remote computer.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 0986-6980-3916-0512-6608-8243-13
Version           : VRTUAL - 4001628
PSComputerName    : dc01

単にコンピューター名を指定するのではなく、CIM セッションを使用することには、追加のメリットがいくつかあります。There are several additional benefits to using CIM sessions instead of just specifying a computer name. 同じコンピューターに対して複数のクエリを実行する場合、クエリごとにコンピューター名を使用するよりも、CIM セッションを使用する方が効率的です。When running multiple queries to the same computer, using a CIM session is more efficient than using the computer name for each query. CIM セッションを作成するだけで、接続が一度に設定されます。Creating a CIM session only sets up the connection once. 次に、その同じセッションが、複数のクエリで情報を取得するために使用されます。Then, multiple queries use that same session to retrieve information. コンピューター名を使用する場合、コマンドレットで個別のクエリごとに接続を設定して破棄しなければなりません。Using the computer name requires the cmdlets to set up and tear down the connection with each individual query.

Get-CimInstance コマンドレットでは既定で WSMan プロトコルを使用します。これは、リモート コンピューターが接続するために PowerShell バージョン 3.0 以上が必要であることを意味します。The Get-CimInstance cmdlet uses the WSMan protocol by default, which means the remote computer needs PowerShell version 3.0 or higher to connect. 実際に問題になるのは、PowerShell バージョンではなくスタック バージョンです。It's actually not the PowerShell version that matters, it's the stack version. スタック バージョンは、Test-WSMan コマンドレットを使用して特定できます。The stack version can be determined using the Test-WSMan cmdlet. バージョン 3.0 が必要です。It needs to be version 3.0. これは、PowerShell バージョン 3.0 以上で見つかるバージョンです。That's the version you'll find with PowerShell version 3.0 and higher.

Test-WSMan -ComputerName dc01
wsmid           : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor   : Microsoft Corporation
ProductVersion  : OS: 0.0.0 SP: 0.0 Stack: 3.0

古い WMI コマンドレットでは、以前のバージョンの Windows と互換性がある DCOM プロトコルを使用しています。The older WMI cmdlets use the DCOM protocol, which is compatible with older versions of Windows. しかし、DCOM は新しいバージョンの Windows でファイアウォールによってブロックされるのが普通です。But DCOM is typically blocked by the firewall on newer versions of Windows. New-CimSessionOption コマンドレットでは、New-CimSession で使用するための DCOM プロトコル接続を作成できます。The New-CimSessionOption cmdlet allows you to create a DCOM protocol connection for use with New-CimSession. これにより、Windows Server 2000 と同じくらい古いバージョンの Windows と通信するために Get-CimInstance コマンドレットを使用できます。This allows the Get-CimInstance cmdlet to be used to communicate with versions of Windows as old as Windows Server 2000. これはまた、DCOM プロトコルを使うように構成された CimSession と共に Get-CimInstance コマンドレットを使用する場合、リモート コンピューター上に PowerShell が必要ないことを意味します。This also means that PowerShell is not required on the remote computer when using the Get-CimInstance cmdlet with a CimSession that's configured to use the DCOM protocol.

New-CimSessionOption コマンドレットを使用して DCOM プロトコル オプションを作成し、それを変数に格納します。Create the DCOM protocol option using the New-CimSessionOption cmdlet and store it in a variable.

$DCOM = New-CimSessionOption -Protocol Dcom

効率を上げるために、ドメイン管理者または管理者特権の資格情報を変数に格納できます。そうすることで、それらをコマンドごとに何度も入力する必要がなくなります。For efficiency, you can store your domain administrator or elevated credentials in a variable so you don't have to constantly enter them for each command.

$Cred = Get-Credential
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

Windows Server 2008 (R2 以外) を実行する SQL03 という名前のサーバーがあります。I have a server named SQL03 that runs Windows Server 2008 (non-R2). これは、既定では PowerShell がインストールされていない最新の Windows Server オペレーティング システムです。It's the newest Windows Server operating system that doesn't have PowerShell installed by default.

DCOM プロトコルを使用して、SQL03 への CimSession を作成します。Create a CimSession to SQL03 using the DCOM protocol.

$CimSession = New-CimSession -ComputerName sql03 -SessionOption $DCOM -Credential $Cred

前のコマンドでは、今度は再び手動で入力するのではなく、Credential パラメーターの値として $Cred という名前の変数を指定したことに注目してください。Notice in the previous command, this time I specified the variable named $Cred as the value for the Credential parameter instead of having to enter them manually again.

クエリの出力は、基になるプロトコルとして何が使用されているかに関係なく同じです。The output of the query is the same regardless of the underlying protocol being used.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 7237-7483-8873-8926-7271-5004-86
Version           : VRTUAL - 4001628
PSComputerName    : sql03

Get-CimSession コマンドレットは、現在接続されている CimSession の内容と、それらで使用されているプロトコルを確認するために使用されます。The Get-CimSession cmdlet is used to see what CimSessions are currently connected and what protocols they're using.

Get-CimSession
Id           : 1
Name         : CimSession1
InstanceId   : 80742787-e38e-41b1-a7d7-fa1369cf1402
ComputerName : dc01
Protocol     : WSMAN

Id           : 2
Name         : CimSession2
InstanceId   : 8fcabd81-43cf-4682-bd53-ccce1e24aecb
ComputerName : sql03
Protocol     : DCOM

前に作成した CimSession を両方取得して、$CimSession という名前の変数に格納します。Retrieve and store both of the previously created CimSessions in a variable named $CimSession.

$CimSession = Get-CimSession

1 つのコマンドを使用して、両方のコンピューターに対してクエリを実行します。1 つには WSMan プロトコルを、もう 1 つには DCOM を使用します。Query both of the computers with one command, one using the WSMan protocol and the other one with DCOM.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 0986-6980-3916-0512-6608-8243-13
Version           : VRTUAL - 4001628
PSComputerName    : dc01

SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 7237-7483-8873-8926-7271-5004-86
Version           : VRTUAL - 4001628
PSComputerName    : sql03

私は WMI と CIM のコマンドレットについて多数のブログ記事を執筆しています。I've written numerous blog articles about the WMI and CIM cmdlets. 最も役に立つものの 1 つでは、WSMan と DCOM のどちらを使用すべきかを自動的に特定し、どれを手動で設定するかを把握する必要なしに CIM セッションを自動的に設定するために作成した関数について説明しています。One of the most useful ones is about a function that I created to automatically determine if WSMan or DCOM should be used and set up the CIM session automatically without having to figure out which one manually. そのブログ記事のタイトルは、「DCOM へのフォールバックを使用してリモート コンピューターへの CimSession を作成する PowerShell 関数」です。That blog article is titled PowerShell Function to Create CimSessions to Remote Computers with Fallback to Dcom.

CIM セッションが完了したら、Remove-CimSession コマンドレットを使用してそれらを削除する必要があります。When you're finished with the CIM sessions, you should remove them with the Remove-CimSession cmdlet. すべての CIM セッションを削除するには、Get-CimSessionRemove-CimSession にパイプ処理するだけでかまいません。To remove all CIM sessions, simply pipe Get-CimSession to Remove-CimSession.

Get-CimSession | Remove-CimSession

まとめSummary

この章では、PowerShell を使用してローカルとリモート両方のコンピューター上の WMI を操作する方法について学習しました。In this chapter, you've learned about using PowerShell to work with WMI on both local and remote computers. さらに、CIM コマンドレットを使用して、WSMan と DCOM の両方のプロトコルでリモート コンピューターを操作する方法を学習しました。You've also learned how to use the CIM cmdlets to work with remote computers with both the WSMan or DCOM protocol.

確認Review

  1. WMI コマンドレットと CIM コマンドレットの違いは何か。What is the difference in the WMI and CIM cmdlets?
  2. 既定では、Get-CimInstance コマンドレットで使用されるプロトコルは何か。By default, what protocol does the Get-CimInstance cmdlet use?
  3. Get-CimInstance を使用してコンピューター名を指定する代わりに、CIM セッションを使用するメリットは何か。What are some of the benefits of using a CIM session instead of specifying a computer name with Get-CimInstance?
  4. Get-CimInstance で使用する既定のプロトコルとは異なる、別のプロトコルを指定する方法は何か。How do you specify an alternate protocol other than the default one for use with Get-CimInstance?
  5. CIM セッションはどのように終了または削除するか。How do you close or remove CIM sessions?