# 画面設計書 241-プロダクトキー取得

## 概要

本ドキュメントは、dbatools PowerShellモジュールの `Get-DbaProductKey` コマンドに関する画面設計書です。SQL Serverインスタンスのプロダクトキーを取得する機能を提供します。

### 本画面の処理概要

`Get-DbaProductKey` コマンドは、対象コンピュータ上にインストールされたSQL Serverインスタンスのプロダクトキーをレジストリから取得・復号化する機能を提供します。

**業務上の目的・背景**：企業においてSQL Serverライセンスのコンプライアンス監査、資産管理、マイグレーション計画時のライセンス棚卸しは重要な業務です。本コマンドは、複数サーバーにまたがるSQL Serverインスタンスのプロダクトキーを一括で取得し、ライセンス管理の効率化と監査対応を支援します。特に大規模環境でのライセンス棚卸しや、監査人への提出資料作成時に有用です。

**画面へのアクセス方法**：PowerShellコンソールまたはPowerShell ISEから `Get-DbaProductKey` コマンドを直接実行します。パイプライン入力もサポートしており、他のコマンドの出力を受け取ることも可能です。

**主要な操作・処理内容**：
1. 対象コンピュータの指定（ComputerNameパラメータ）
2. SQL Serverインスタンスへの接続とバージョン/エディション情報の取得
3. レジストリからDigitalProductIDバイナリデータの読み取り
4. プロダクトキーの復号化（バージョンに応じたアルゴリズム使用）
5. Express Editionの自動識別（プロダクトキー不要のため）
6. 結果のオブジェクト出力

**画面遷移**：CLIコマンドのため画面遷移はありません。他のdbatoolsコマンドとパイプラインで連携可能です。`Get-DbaRegistryRoot` コマンドを内部で呼び出してレジストリルートを取得します。

**権限による表示制御**：対象サーバーへのWindows管理者権限またはリモートレジストリアクセス権限が必要です。SQL Serverへの接続には適切な認証情報が必要です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 140 | Get-DbaProductKey | 主機能 | プロダクトキーの取得 |
| 145 | Get-DbaRegistryRoot | 補助機能 | レジストリルートパスの取得 |
| - | Connect-DbaInstance | 補助機能 | SQL Serverインスタンスへの接続 |
| - | Invoke-Command2 | 補助機能 | リモートコンピュータでのスクリプト実行 |

## 画面種別

CLI（コマンドラインインターフェース）/ 情報取得系

## URL/ルーティング

PowerShellコマンド: `Get-DbaProductKey`

## 入出力項目

### 入力パラメータ

| パラメータ名 | 型 | 必須 | パイプライン | 説明 |
|-------------|----|----|-------------|------|
| ComputerName | DbaInstanceParameter[] | Yes | Yes | SQL Serverインスタンスまたはコンピュータ名 |
| SqlCredential | PSCredential | No | No | SQL Server認証用の資格情報 |
| Credential | PSCredential | No | No | Windows認証用の資格情報 |
| EnableException | switch | No | No | 例外を詳細表示するフラグ |

## 表示項目

### 出力オブジェクト（PSCustomObject）

| 項目名 | 型 | 説明 |
|--------|----|----|
| ComputerName | string | SQL Serverホストのコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全修飾SQL Serverインスタンス名（computer\instance形式） |
| Version | string | SQL Serverバージョン名（例: "SQL Server 2019"） |
| Edition | string | SQL Serverエディション（Enterprise, Standard, Express等） |
| Key | string | プロダクトキー（XXXXX-XXXXX-XXXXX-XXXXX-XXXXX形式）またはエラーメッセージ |

## イベント仕様

### 1-コマンド実行

コマンド実行時の処理フロー:

1. **入力検証**: ComputerNameパラメータの値をループ処理
2. **レジストリルート取得**: `Get-DbaRegistryRoot` を呼び出してSQL Serverインスタンスのレジストリパスを取得
3. **インスタンス接続**: `Connect-DbaInstance` でSQL Serverに接続しバージョン情報取得
4. **リモート実行**: `Invoke-Command2` でターゲットコンピュータ上のスクリプトブロックを実行
5. **キー復号化**: `Unlock-SqlInstanceKey` 関数でDigitalProductIDを復号化
6. **結果出力**: PSCustomObjectとして結果を出力

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| コマンド実行 | - | SELECT | データベースへの書き込みなし（読み取り専用） |

### テーブル別更新項目詳細

本コマンドはデータベースへの更新を行いません。SQL Serverへの接続はバージョン/エディション情報の取得のみに使用されます。

## メッセージ仕様

| メッセージID | レベル | メッセージ内容 | 発生条件 |
|-------------|--------|--------------|----------|
| - | Warning | Can't access registry for {ComputerName}. Is the Remote Registry service started? | リモートレジストリにアクセスできない場合 |
| - | Warning | No instances found on {ComputerName} | レジストリルートが取得できない場合 |
| - | Error | Failure | SQL Server接続に失敗した場合 |
| - | Info | SQL Server Express Edition | Express Editionの場合（キーは不要） |
| - | Info | Could not read Product Key from registry on {ComputerName} | レジストリからキーを読み取れない場合 |
| - | Info | Cannot decode product key. | キーの復号化に失敗した場合 |

## 例外処理

| 例外種別 | 発生条件 | 処理内容 |
|---------|---------|---------|
| 接続エラー | リモートレジストリサービスが停止 | 警告メッセージを表示し、次のコンピュータへ続行 |
| 接続エラー | SQL Serverへの接続失敗 | Stop-Functionでエラー記録、次のインスタンスへ続行 |
| 復号化エラー | DigitalProductIDの復号化失敗 | "Cannot decode product key."を返却 |
| バージョン制約 | SQL Server 2005未満 | MinimumVersion 9で接続時にエラー |

## 備考

- SQL Server 2005以降をサポート（MinimumVersion 9）
- Express Editionはプロダクトキーが不要のため「SQL Server Express Edition」を返却
- クラスタ構成インスタンスもサポート
- プロダクトキーの復号化アルゴリズムはSQL Serverバージョンに応じて異なる（v11以降とv10以前で処理が異なる）
- リモートレジストリサービスが対象コンピュータで起動している必要あり

---

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

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

### 推奨読解順序

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

出力オブジェクトの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaProductKey.ps1 | `public/Get-DbaProductKey.ps1` | 202-209行目: 出力PSCustomObjectの構造（ComputerName, InstanceName, SqlInstance, Version, Edition, Key） |

**読解のコツ**: PowerShellの`[PSCustomObject]@{}`記法で定義されたオブジェクト構造を確認。各プロパティの値がどこから取得されるかを追跡する。

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

処理の起点となる関数の構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaProductKey.ps1 | `public/Get-DbaProductKey.ps1` | 56-64行目: パラメータ定義、173-211行目: processブロックのメインロジック |

**主要処理フロー**:
1. **173-174行目**: ComputerNameパラメータのforeachループ開始
2. **175-179行目**: Get-DbaRegistryRootでレジストリルート取得
3. **186-191行目**: Connect-DbaInstanceでSQL Server接続
4. **196-200行目**: Invoke-Command2でリモートスクリプト実行
5. **202-209行目**: PSCustomObject作成と出力

#### Step 3: キー復号化ロジックを理解する

プロダクトキー復号化の核心部分を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Get-DbaProductKey.ps1 | `public/Get-DbaProductKey.ps1` | 67-170行目: $scriptBlockの内容、特にUnlock-SqlInstanceKey関数 |

**主要処理フロー**:
- **72-119行目**: Unlock-SqlInstanceKey関数 - DigitalProductIDバイナリからキー文字列への変換
- **80-84行目**: バージョンに応じたバイナリ配列の範囲選択（v11以上: 0-66、v10以下: 52-66）
- **85行目**: 許可文字セット（B,C,D,F,G,H,J,K,M,P,Q,R,T,V,W,X,Y,2,3,4,6,7,8,9）
- **120-138行目**: レジストリパス決定ロジック（v9, v10, v11+で異なる）
- **140-164行目**: Express Edition判定とキー取得処理

#### Step 4: 依存コマンドを理解する

内部で呼び出されるコマンドを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Get-DbaRegistryRoot.ps1 | `public/Get-DbaRegistryRoot.ps1` | SQL ServerインスタンスのレジストリルートパスをWMIから取得する処理 |

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

```
Get-DbaProductKey
    │
    ├─ Get-DbaRegistryRoot
    │      └─ Invoke-ManagedComputerCommand (WMI経由でレジストリパス取得)
    │
    ├─ Connect-DbaInstance
    │      └─ SQL Server接続、バージョン/エディション情報取得
    │
    └─ Invoke-Command2
           └─ $scriptBlock (リモート実行)
                  ├─ レジストリ読み取り (Microsoft.Win32.RegistryKey)
                  └─ Unlock-SqlInstanceKey (キー復号化)
```

### データフロー図

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

ComputerName ───▶ Get-DbaRegistryRoot ───▶ レジストリルート
      │                                           │
      └───▶ Connect-DbaInstance ───▶ Version, Edition
                    │                            │
                    └───▶ Invoke-Command2 ───▶ DigitalProductID
                                │                    │
                                └─ Unlock-SqlInstanceKey
                                         │
                                         ▼
                                    PSCustomObject
                                    (ComputerName, InstanceName,
                                     SqlInstance, Version, Edition, Key)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaProductKey.ps1 | `public/Get-DbaProductKey.ps1` | ソース | メインコマンド実装 |
| Get-DbaRegistryRoot.ps1 | `public/Get-DbaRegistryRoot.ps1` | ソース | レジストリルートパス取得 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続 |
| Invoke-Command2.ps1 | `internal/functions/Invoke-Command2.ps1` | ソース | リモートコマンド実行ラッパー |
