# 機能設計書 131-Get-DbaManagementObject

## 概要

本ドキュメントは、dbatools PowerShellモジュールの`Get-DbaManagementObject`コマンドレットに関する機能設計書です。このコマンドレットは、SQL Server Management Object (SMO) アセンブリのインストール状況とロード状態を検出する機能を提供します。

### 本機能の処理概要

**業務上の目的・背景**：SQL Serverの管理をPowerShellで行う場合、SMO (SQL Server Management Object) ライブラリは必須のコンポーネントです。しかし、複数のSQL Serverバージョンが混在する環境では、異なるバージョンのSMOが競合し、予期しない動作やエラーを引き起こすことがあります。本機能は、システムにインストールされているSMOアセンブリを検出し、バージョン競合のトラブルシューティングを支援します。

**機能の利用シーン**：
- SQL Server管理スクリプト開発時にSMOライブラリのバージョンを確認したい場合
- 異なるSQL Serverツール間での動作不一致を調査する場合
- 複数サーバー間でSMOのインストール状況を比較・監査する場合
- PowerShellスクリプトで特定バージョンのSMOを読み込む必要がある場合

**主要な処理内容**：
1. 現在のPowerShellセッションで読み込まれているSMO、SqlClient、SNI関連アセンブリを検出
2. ローカルのPowerShellインストールディレクトリからSMOアセンブリを検索
3. グローバルアセンブリキャッシュ(GAC)内のSMOアセンブリをスキャン
4. SNI (SQL Network Interface) モジュールの検出
5. 各アセンブリのバージョン、パス、ロード状態、ロード用コマンドを出力

**関連システム・外部連携**：
- Windowsレジストリ（GAC情報の取得）
- リモートコンピュータへのPowerShell Remoting (Invoke-Command2)
- AppDomain (現在読み込まれているアセンブリの検出)

**権限による制御**：リモートコンピュータを指定した場合、リモートコンピュータへの管理者権限とPowerShell Remotingの有効化が必要です。

## 関連画面

本機能はコマンドラインツールであり、画面機能マッピングに該当する関連画面はありません。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | PowerShellコマンドラインで実行 |

## 機能種別

データ取得 / 診断・トラブルシューティング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ComputerName | DbaInstanceParameter[] | No | SMOアセンブリをスキャンするサーバー名。デフォルトはローカルコンピュータ | パイプライン入力可 |
| Credential | PSCredential | No | リモートコンピュータへの接続に使用するWindows資格情報 | - |
| VersionNumber | int | No | 特定のメジャーバージョン番号でフィルタリング（例: 13=SQL 2016, 14=2017, 15=2019） | 0以上の整数 |
| EnableException | switch | No | 例外処理を有効化し、try/catchで例外をキャッチ可能にする | - |

### 入力データソース

- ローカルまたはリモートコンピュータのファイルシステム（GAC、PowerShellディレクトリ）
- 現在のAppDomainに読み込まれているアセンブリ
- 現在のプロセスのモジュール情報（SNI検出用）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | アセンブリが存在するコンピュータ名 |
| Version | string | アセンブリまたはモジュールのバージョン番号 |
| Loaded | bool | 現在のPowerShellセッションに読み込まれているかどうか |
| Path | string | アセンブリのファイルパス（GACの場合はnull） |
| LoadTemplate | string | Add-Typeを使用してアセンブリを読み込むPowerShellコマンド |

### 出力先

PowerShellパイプライン（PSCustomObject）

## 処理フロー

### 処理シーケンス

```
1. パラメータの初期化
   └─ VersionNumberが指定されていない場合は0に設定

2. スクリプトブロックの定義
   └─ 実際の検索処理を含むスクリプトブロックを準備

3. 各コンピュータに対して処理
   ├─ ローカルコンピュータの場合
   │     └─ Invoke-Commandでスクリプトブロック実行
   └─ リモートコンピュータの場合
         └─ Invoke-Command2で資格情報付きでスクリプトブロック実行

4. スクリプトブロック内の処理
   ├─ 4.1 現在読み込まれているアセンブリをAppDomainから検出
   ├─ 4.2 SNIモジュールをプロセスモジュールから検出
   ├─ 4.3 ローカルSMOライブラリの検出とバージョン取得
   ├─ 4.4 GAC内のSMOアセンブリをスキャン（Windows限定）
   └─ 4.5 検出された各アセンブリの情報をPSCustomObjectとして出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[パラメータ初期化]
    B --> C{各ComputerNameに対して}
    C --> D{ローカル/リモート?}
    D -->|ローカル| E[Invoke-Command実行]
    D -->|リモート| F[Invoke-Command2実行]
    E --> G[スクリプトブロック実行]
    F --> G
    G --> H[AppDomainから読み込み済みアセンブリ検出]
    H --> I[SNIモジュール検出]
    I --> J{Windows?}
    J -->|Yes| K[GAC内SMOスキャン]
    J -->|No| L[スキップ]
    K --> M[結果出力]
    L --> M
    M --> N{次のコンピュータ?}
    N -->|Yes| C
    N -->|No| O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | バージョンフィルタリング | VersionNumber指定時、メジャーバージョンが一致するアセンブリのみ返却 | VersionNumber > 0 |
| BR-002 | GAC検索対象OS | GACのスキャンはWindowsでのみ実行 | !$IsLinux かつ !$IsMacOs |
| BR-003 | ロード状態判定 | メジャー.マイナーバージョンが一致する場合にLoadedをtrueに設定 | アセンブリ検出時 |
| BR-004 | 重複排除 | ローカルファイルで既にカバーされているアセンブリは重複出力しない | 読み込み済みアセンブリ処理時 |

### 計算ロジック

バージョン比較ロジック：
- メジャーバージョンとマイナーバージョンを比較して同一アセンブリを判定
- バージョン文字列はAssemblyのFullNameから正規表現で抽出 `Version=([^,]+)`

## データベース操作仕様

本機能はデータベースへの直接操作を行いません。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 接続エラー | リモートコンピュータへの接続失敗 | Stop-Functionで警告を表示し次のコンピュータへ継続 |
| - | 権限エラー | リモートレジストリへのアクセス権不足 | 適切な資格情報を指定 |
| - | SNI検出エラー | プロセスモジュール取得失敗 | Write-Verboseでエラーログ、処理は継続 |

### リトライ仕様

リトライ処理は実装されていません。接続エラー時は次のコンピュータへスキップします。

## トランザクション仕様

データベース操作がないため、トランザクション管理は不要です。

## パフォーマンス要件

- 各コンピュータに対するスキャンは数秒程度で完了することを想定
- リモートコンピュータへのアクセスはネットワーク状況に依存

## セキュリティ考慮事項

- リモートコンピュータへのアクセスにはWindows認証を使用
- 資格情報はSecureStringとして保護
- PowerShell Remotingの有効化が必要（リモート実行時）

## 備考

- Linux/macOSではGACスキャンはスキップされる
- SQL Server 2016のSMOはバージョン13、SQL Server 2017は14、SQL Server 2019は15
- LoadTemplateプロパティを使用して、検出されたアセンブリを簡単に読み込み可能

---

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

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

### 推奨読解順序

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

PSCustomObjectとして出力される構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 140-146行目: ローカルSMO検出時の出力構造 |
| 1-2 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 231-237行目: GAC検出時の出力構造 |
| 1-3 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 293-299行目: SNIモジュール検出時の出力構造 |

**読解のコツ**: 出力が3種類（ローカル、GAC、SNI）あり、それぞれPathプロパティの扱いが異なることに注目。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 67-75行目: パラメータ定義とデフォルト値 |
| 2-2 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 304-318行目: processブロックでのメイン処理フロー |

**主要処理フロー**:
1. **77-80行目**: beginブロックでVersionNumberのデフォルト設定
2. **304-317行目**: 各コンピュータに対してローカル/リモート判定し適切なInvokeを実行

#### Step 3: スクリプトブロック内のアセンブリ検出処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 86行目: AppDomainから読み込み済みアセンブリを取得するフィルタ条件 |
| 3-2 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 91-100行目: バージョン抽出のロジック |
| 3-3 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 109-117行目: SNIモジュール検出 |

**読解のコツ**: アセンブリのFullNameからバージョンを抽出する正規表現 `Version=([^,]+)` に注目。

#### Step 4: GAC検索処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | 205-256行目: GAC内SMOアセンブリのスキャン処理 |

**主要処理フロー**:
- **206行目**: 標準GAC パス `$env:SystemRoot\assembly\GAC_MSIL\Microsoft.SqlServer.Smo`
- **210行目**: 代替GAC パス `.NET assembly\GAC_MSIL`
- **219-255行目**: バージョン抽出とPSCustomObject出力

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

```
Get-DbaManagementObject
    │
    ├─ begin ブロック
    │      └─ スクリプトブロック ($scriptBlock) 定義
    │
    └─ process ブロック
           │
           └─ foreach ($computer in $ComputerName)
                  │
                  ├─ [ローカル] Invoke-Command -Scriptblock $scriptBlock
                  │
                  └─ [リモート] Invoke-Command2
                         │
                         └─ $scriptBlock 実行
                                ├─ AppDomain.GetAssemblies() - 読み込み済み検出
                                ├─ Get-Process.Modules - SNI検出
                                ├─ Get-ChildItem (ローカルSMO)
                                └─ Get-ChildItem (GAC)
```

### データフロー図

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

ComputerName ───────▶ スクリプトブロック実行 ───────▶ PSCustomObject[]
                            │
                            ├─ AppDomain ──▶ 読み込み済みアセンブリ情報
                            │
                            ├─ Process.Modules ──▶ SNIモジュール情報
                            │
                            ├─ PowerShell Dir ──▶ ローカルSMO情報
                            │
                            └─ GAC ──▶ インストール済みSMO情報
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaManagementObject.ps1 | `public/Get-DbaManagementObject.ps1` | ソース | メイン処理 |
| Invoke-Command2.ps1 | `private/functions/Invoke-Command2.ps1` | ソース | リモート実行ヘルパー |
| Stop-Function.ps1 | `private/functions/flowcontrol/Stop-Function.ps1` | ソース | エラー処理 |
| Write-Message.ps1 | `private/functions/flowcontrol/Write-Message.ps1` | ソース | ログ出力 |
