# 画面設計書 283-CMオブジェクト取得

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおける`Get-DbaCmObject`コマンドの機能仕様を定義する設計書です。このコマンドは、SQL ServerホストマシンからWMI/CIMを使用してWindowsシステム情報を取得し、インテリジェントな接続フォールバック機能を提供します。

### 本画面の処理概要

**業務上の目的・背景**：SQL Server管理において、データベースエンジンだけでなく、ホストマシンのシステムレベル情報（ハードウェアスペック、OS詳細、サービス状態、パフォーマンスカウンターなど）の収集が必要となる場面は多くあります。`Get-DbaCmObject`は、複数の接続プロトコル（CIM over WinRM、CIM over DCOM、WMI、PowerShell Remoting）を自動的に試行し、最も効率的な方法で情報を取得します。また、接続結果をキャッシュすることで、同一サーバーへの再接続時のパフォーマンスを最適化します。

**画面へのアクセス方法**：PowerShellコンソールまたはスクリプトから`Get-DbaCmObject`コマンドを実行します。WMI/CIMクラス名またはWQLクエリを指定して、リモートまたはローカルコンピュータからシステム情報を取得します。

**主要な操作・処理内容**：
1. **クラス指定による取得**：`-ClassName`パラメータでWMI/CIMクラス（例：Win32_OperatingSystem）を指定し、全インスタンスを取得
2. **クエリ指定による取得**：`-Query`パラメータでWQLクエリを指定し、フィルタリングされた結果を取得
3. **プロトコル自動選択**：CimRM → CimDCOM → Wmi → PowerShellRemotingの順で接続を試行
4. **接続結果キャッシュ**：成功/失敗したプロトコルを記憶し、次回以降の接続を最適化
5. **認証情報管理**：成功/失敗した認証情報を自動的にキャッシュ

**画面遷移**：本コマンドはスタンドアロンのデータ取得コマンドです。CM接続管理コマンド群（`Test-DbaCmConnection`など）で事前に接続を構成することが可能です。取得したシステム情報は、他のdbatoolsコマンドやPowerShellスクリプトで後続処理に使用できます。

**権限による表示制御**：リモートコンピュータへのアクセスには、対象マシンでの管理者権限または適切なWMI/CIM権限が必要です。クエリするWMI名前空間やクラスによって追加の権限が必要な場合があります。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 94 | Get-DbaCmObject | 主機能 | WMI/CIMオブジェクトの取得 |
| 93 | Get-DbaCmConnection | 補助機能 | 接続キャッシュの確認 |
| 239 | Test-DbaCmConnection | 補助機能 | 接続プロトコルの事前テスト |
| 217 | Set-DbaCmConnection | 補助機能 | 接続設定の事前構成 |

## 画面種別

データ取得（Query/Retrieval）

## URL/ルーティング

PowerShellコマンド: `Get-DbaCmObject`
ドキュメントURL: https://dbatools.io/Get-DbaCmObject

## 入出力項目

### パラメータ（Classパラメータセット）

| パラメータ名 | 必須 | 型 | デフォルト値 | 説明 |
|-------------|------|-----|-------------|------|
| ClassName | Yes | String | - | 取得するWMI/CIMクラス名（例：Win32_OperatingSystem） |
| ComputerName | No | DbaCmConnectionParameter[] | $env:COMPUTERNAME | 対象コンピュータ |
| Credential | No | PSCredential | - | 接続に使用する認証情報 |
| Namespace | No | String | "root\cimv2" | WMI名前空間パス |
| DoNotUse | No | ManagementConnectionType[] | None | 除外する接続プロトコル |
| Force | No | Switch | - | 失敗済み接続の再試行を強制 |
| SilentlyContinue | No | Switch | - | エラー時に処理を継続 |
| EnableException | No | Switch | $false | 例外を有効化 |

### パラメータ（Queryパラメータセット）

| パラメータ名 | 必須 | 型 | デフォルト値 | 説明 |
|-------------|------|-----|-------------|------|
| Query | Yes | String | - | WQLクエリ文字列 |
| ComputerName | No | DbaCmConnectionParameter[] | $env:COMPUTERNAME | 対象コンピュータ |
| Credential | No | PSCredential | - | 接続に使用する認証情報 |
| Namespace | No | String | "root\cimv2" | WMI名前空間パス |
| DoNotUse | No | ManagementConnectionType[] | None | 除外する接続プロトコル |
| Force | No | Switch | - | 失敗済み接続の再試行を強制 |
| SilentlyContinue | No | Switch | - | エラー時に処理を継続 |
| EnableException | No | Switch | $false | 例外を有効化 |

## 表示項目

出力はクエリするWMI/CIMクラスによって異なります。

### 共通出力型

- `System.Management.ManagementObject`（WMI経由の場合）
- `Microsoft.Management.Infrastructure.CimInstance`（CIM経由の場合）

### 代表的なクラス別出力プロパティ

#### Win32_OperatingSystem

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| Name | String | OS名 |
| Caption | String | OS説明 |
| Version | String | バージョン番号 |
| BuildNumber | String | ビルド番号 |
| OSArchitecture | String | アーキテクチャ（64-bit等） |
| FreePhysicalMemory | UInt64 | 空きメモリ（KB） |
| TotalVisibleMemorySize | UInt64 | 総メモリ（KB） |
| SystemDrive | String | システムドライブ |
| WindowsDirectory | String | Windowsディレクトリパス |

#### Win32_ComputerSystem

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| Name | String | コンピュータ名 |
| DNSHostName | String | DNS名 |
| Domain | String | ドメイン名 |
| Manufacturer | String | 製造元 |
| Model | String | モデル名 |
| SystemType | String | システムタイプ |
| NumberOfProcessors | UInt32 | 物理プロセッサ数 |
| NumberOfLogicalProcessors | UInt32 | 論理プロセッサ数 |
| TotalPhysicalMemory | UInt64 | 総物理メモリ（バイト） |

#### Win32_Service

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| Name | String | サービス名 |
| DisplayName | String | 表示名 |
| State | String | 状態（Running/Stopped等） |
| StartMode | String | 起動モード（Auto/Manual等） |
| Status | String | ステータス |
| PathName | String | 実行ファイルパス |
| StartName | String | 起動アカウント |
| Description | String | 説明 |

## イベント仕様

### 1-コマンド実行時（メイン処理フロー）

1. **接続オブジェクト解決**：`ComputerName`パラメータからDbaCmConnectionParameterオブジェクトを取得
2. **認証情報取得**：`Connection.GetCredential($Credential)`で有効な認証情報を取得
3. **有効プロトコル判定**：接続オブジェクトの設定に基づき使用可能なプロトコルを列挙
4. **除外プロトコル適用**：`DoNotUse`パラメータで指定されたプロトコルを除外
5. **プロトコル選択ループ**：
   - `Connection.GetConnectionType()`で次に試行するプロトコルを取得
   - プロトコルに応じた接続処理を実行
   - 成功時：結果をパイプラインに出力、接続成功を記録
   - 失敗時：エラー種別に応じて次のプロトコルを試行または処理終了
6. **キャッシュ更新**：接続結果をConnectionHostキャッシュに保存

### 2-CimRM接続時

1. `Connection.GetCimRMInstance()`または`Connection.QueryCimRMInstance()`を呼び出し
2. 成功時：`Connection.ReportSuccess('CimRM')`、`Connection.AddGoodCredential()`
3. 認証失敗時：`Connection.AddBadCredential()`、処理終了
4. 接続失敗時：`Connection.ReportFailure('CimRM')`、次のプロトコルへ

### 3-CimDCOM接続時

1. `Connection.GetCimDCOMInstance()`または`Connection.QueryCimDCOMInstance()`を呼び出し
2. 成功/失敗処理はCimRMと同様

### 4-WMI接続時

1. `Get-WmiObject`コマンドレットを使用
2. splatで`ComputerName`、`ClassName`/`Query`、`Credential`、`Namespace`を渡す
3. 成功/失敗処理は他のプロトコルと同様

### 5-PowerShellRemoting接続時

1. `Invoke-Command2`でリモートセッションを確立
2. ScriptBlockで`Get-WmiObject`を実行
3. 成功/失敗処理は他のプロトコルと同様

## データベース更新仕様

### 操作別データベース影響一覧

本コマンドはSQL Serverデータベースを操作しません。ただし、以下のキャッシュを更新します。

| 操作（イベント） | 対象 | 操作種別 | 概要 |
|----------------|------|---------|------|
| 接続成功時 | ConnectionHost.Connections | UPDATE | プロトコル成功状態と認証情報を更新 |
| 接続失敗時 | ConnectionHost.Connections | UPDATE | プロトコル失敗状態を記録 |
| 認証失敗時 | ManagementConnection.KnownBadCredentials | UPDATE | 失敗した認証情報を追加 |

## メッセージ仕様

| 種別 | 条件 | メッセージ |
|------|------|-----------|
| Error | 入力解釈失敗 | "Failed to interpret input: {入力値}" |
| Error | 接続不可 | "[{コンピュータ名}] Unable to find a connection to the target system. Ensure the name is typed correctly, and the server allows any of the following protocols: {プロトコル一覧}" |
| Error | 認証失敗 | "[{コンピュータ名}] Invalid connection credentials" |
| Error | 無効な名前空間 | "[{コンピュータ名}] Invalid namespace: {名前空間}" |
| Error | 無効なクラス名 | "[{コンピュータ名}] Invalid class name ({クラス名}), not found in current namespace ({名前空間})" |
| Error | アクセス拒否 | "[{コンピュータ名}] Access to computer granted, but access to {名前空間}\{クラス名} denied" |
| Error | WMIプロバイダエラー | "[{コンピュータ名}] Failed to access: {クラス名}, in namespace: {名前空間} - There was a provider error. This indicates a potential issue with WMI on the server side." |
| Verbose | CimRM試行 | "[{コンピュータ名}] Accessing computer using Cim over WinRM" |
| Verbose | CimRM成功 | "[{コンピュータ名}] Accessing computer using Cim over WinRM - Success" |
| Verbose | CimRM失敗 | "[{コンピュータ名}] Accessing computer using Cim over WinRM - Failed" |
| Verbose | CimDCOM試行 | "[{コンピュータ名}] Accessing computer using Cim over DCOM" |
| Verbose | WMI試行 | "[{コンピュータ名}] Accessing computer using WMI" |
| Verbose | PSRemoting試行 | "[{コンピュータ名}] Accessing computer using PowerShell Remoting" |

## 例外処理

| 例外状況 | エラーコード | 処理 |
|---------|-------------|------|
| 入力解釈失敗 | - | Stop-Function + Continue（次のコンピュータへ） |
| 認証失敗 | 0x8007052e, 0x80070005 | Stop-Function + Continue（BadCredentialに追加） |
| 無効な名前空間 | 0x8004100e | Stop-Function + Continue |
| 無効なクラス名 | 0x80041010 | Stop-Function + Continue |
| アクセス拒否 | 0x80041013 | Stop-Function + Continue |
| 接続タイムアウト | - | ReportFailure + 次のプロトコルへ |
| 全プロトコル失敗 | - | Stop-Function + Continue |

### CIMエラーコード一覧

内部関数`Resolve-CimError`で以下のエラーコードを解釈：

| コード | 説明 |
|--------|------|
| 1 | 一般的なランタイムエラー |
| 2 | アクセス拒否 |
| 3 | 無効な名前空間 |
| 4 | 無効なパラメータ |
| 5 | 無効なクラス名 |
| 6 | オブジェクトが見つからない |
| 7 | 操作がサポートされていない |
| 14 | 無効なクエリ言語 |
| 15 | 無効なクエリ文字列 |
| 16 | 無効なメソッド |

## 備考

- プロトコル優先順位: CimRM > CimDCOM > Wmi > PowerShellRemoting
- `DoNotUse`パラメータで特定のプロトコルを除外可能
- `-Force`で以前失敗した接続の再試行を強制
- `-SilentlyContinue`でエラーを非終了エラーに変換（複数サーバー処理時に有用）
- Friedrich Weinmann (@FredWeinmann) が開発
- キャッシュ動作は`ComputerManagement.Cache.Disable.All`で無効化可能

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

WMI/CIM接続で使用されるデータ構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | 出力型の説明（60-73行目） |
| 1-2 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | パラメータ定義（88-104行目） |

**読解のコツ**: 出力型はクエリするWMI/CIMクラスに依存します。`System.Management.ManagementObject`（WMI）または`Microsoft.Management.Infrastructure.CimInstance`（CIM）が返されます。

#### Step 2: エラー解決関数を理解する

CIMエラーの解釈を行う内部関数を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | Resolve-CimError関数（114-241行目） |

**主要処理フロー**:
1. **165-186行目**: CIMエラーコード別メッセージマップ
2. **193-221行目**: エラーコード1（一般エラー）の詳細分類
3. **234-240行目**: エラー解析結果オブジェクトの生成

#### Step 3: メイン処理ループを理解する

processブロックのメイン処理フローを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | 接続準備処理（248-282行目） |
| 3-2 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | プロトコル選択ループ（284-439行目） |

**主要処理フロー**:
- **252行目**: コンピュータ名を小文字に正規化
- **259行目**: 有効な認証情報を取得
- **273-278行目**: 有効なプロトコルを列挙
- **285行目**: `Connection.GetConnectionType()`でプロトコルを選択
- **291-321行目**: CimRM処理
- **323-352行目**: CimDCOM処理
- **354-406行目**: WMI処理
- **409-437行目**: PowerShellRemoting処理

#### Step 4: 各プロトコル処理の詳細を理解する

4つのプロトコルそれぞれの処理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | CimRM処理（293-320行目） |
| 4-2 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | CimDCOM処理（325-351行目） |
| 4-3 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | WMI処理（355-405行目） |
| 4-4 | Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | PowerShellRemoting処理（410-436行目） |

**処理パターン共通点**:
1. 接続試行のVerboseログ出力
2. クラス取得またはクエリ実行
3. 成功時：ReportSuccess + AddGoodCredential + continue main
4. 認証失敗時：AddBadCredential + Stop-Function
5. 接続失敗時：ReportFailure + continue sub（次のプロトコル）

### プログラム呼び出し階層図

```
Get-DbaCmObject
    |
    |-- begin
    |       |
    |       +-- Resolve-CimError (内部関数定義)
    |               |-- CIMエラーコード解釈
    |               +-- エラー詳細オブジェクト生成
    |
    +-- process (メインループ: :main)
            |
            |-- Connection.GetCredential($Credential)
            |       +-- 有効な認証情報を取得
            |
            |-- :sub (プロトコル選択ループ)
                    |
                    |-- Connection.GetConnectionType()
                    |       +-- 次に試行するプロトコルを決定
                    |
                    |-- switch ($conType)
                            |
                            |-- CimRM
                            |       |-- Connection.GetCimRMInstance() / QueryCimRMInstance()
                            |       |-- ReportSuccess('CimRM')
                            |       +-- AddGoodCredential($cred)
                            |
                            |-- CimDCOM
                            |       |-- Connection.GetCimDCOMInstance() / QueryCimDCOMInstance()
                            |       |-- ReportSuccess('CimDCOM')
                            |       +-- AddGoodCredential($cred)
                            |
                            |-- Wmi
                            |       |-- Get-WmiObject @parameters
                            |       |-- ReportSuccess('Wmi')
                            |       +-- AddGoodCredential($cred)
                            |
                            +-- PowerShellRemoting
                                    |-- Invoke-Command2 @parameters
                                    |       +-- Get-WmiObject (リモート実行)
                                    |-- ReportSuccess('PowerShellRemoting')
                                    +-- AddGoodCredential($cred)
```

### データフロー図

```
[入力]                          [処理]                              [出力]

-ClassName / -Query ────────────┐
                                |
-ComputerName ──────────────────┼──▶ Get-DbaCmObject
                                |           |
-Credential ────────────────────┤           |
                                |           ▼
-Namespace ─────────────────────┤    ┌─────────────────────────────┐
                                |    │ プロトコル選択              │
-DoNotUse ──────────────────────┘    │                             │
                                     │  1. CimRM (WinRM)           │
                                     │  2. CimDCOM (DCOM)          │
                                     │  3. Wmi (従来WMI)           │
                                     │  4. PowerShellRemoting      │
                                     └──────────────┬──────────────┘
                                                    |
                                                    ▼
                                     ┌─────────────────────────────┐
                                     │ WMI/CIM クエリ実行          │
                                     │ - Win32_* クラス            │
                                     │ - root\cimv2 名前空間       │
                                     └──────────────┬──────────────┘
                                                    |
                    ┌───────────────────────────────┴───────────────────────────────┐
                    |                                                               |
                    ▼                                                               ▼
        [ConnectionHost.Connections]                                    [パイプライン出力]
        - CimRM: Success/Error                                          ManagementObject
        - CimDCOM: Success/Error                                        または
        - Wmi: Success/Error                                            CimInstance
        - PowerShellRemoting: Success/Error
        - GoodCredentials / BadCredentials
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaCmObject.ps1 | `public/Get-DbaCmObject.ps1` | ソース | メインコマンド実装（442行） |
| Get-DbaCmConnection.ps1 | `public/Get-DbaCmConnection.ps1` | ソース | 接続キャッシュ確認 |
| Test-DbaCmConnection.ps1 | `public/Test-DbaCmConnection.ps1` | ソース | 接続プロトコルテスト |
| Set-DbaCmConnection.ps1 | `public/Set-DbaCmConnection.ps1` | ソース | 接続設定変更 |
| Invoke-Command2 | 内部 | ソース | PowerShellリモーティングラッパー |
| ConnectionHost | 内部C#クラス | ライブラリ | 接続キャッシュ管理 |
| ManagementConnection | 内部C#クラス | ライブラリ | 接続情報とプロトコルテスト結果 |
