# Finder（クラシック）用のWindowsでのリモートアクションのスクリプト作成

{% hint style="info" %}
Nexthink FinderはWindows専用のデスクトップアプリケーションであり、その機能は現在Nexthinkウェブインターフェース内で利用可能です。 Nexthinkはブラウザから直接使用できるようになり、ほとんどの機能は追加のデスクトップアプリケーションを必要としなくなりました。
{% endhint %}

Windowsのリモートアクションのペイロードは、従業員のデバイスで実行されるPowerShellスクリプトです。 PowerShellはMicrosoftのスクリプト言語であり、タスク自動化と設定管理に適しており、Windowsデバイスの.NET Framework上に構築されています。 したがって、PowerShellはデバイスからオンデマンドデータを取得したり、自己修復タスクを実行したり、デバイスの設定を変更したりするのに最適であり、これらはリモートアクションの典型的な使用事例です。

この記事では、読者がPowerShellスクリプトに精通していることを前提としています。

リモートアクションのスクリプト作成に関する詳細情報はコミュニティで確認できます：

* [Nexthink Act スクリプティングのベストプラクティス](https://community.nexthink.com/s/article/115005865769-Nexthink-Act-Scripting)
* [Nexthink Act セキュリティホワイトペーパー](https://community.nexthink.com/s/article/115005773929-Nexthink-Act-Security)
* [リモートアクションのコミュニティグループ](https://community.nexthink.com/s/group/0F92p000000kI80CAE)

## エンコーディング <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-encoding" id="writingscriptsforremoteactionsonwindowsforfinder-classic-encoding"></a>

Remote Actions用の独自のPowerShellスクリプトを作成するには、スクリプトのテキストを含むファイルをUTF-8のバイトオーダーマーク (BOM) 付きでエンコードします。 BOMはファイルの先頭にある必要があるUnicode文字で、UTF-8ドキュメントでは次の3バイトの16進数シーケンスとして表されます：EF BB BF。

コードの各行の終わりには、Windowsシステムでの通常の文字シーケンス：CR+LFを使用します。

スクリプトファイルに正しいエンコーディングを提供しない場合、リモートアクションが従業員デバイスで実行できなくなります。

## 独自のスクリプトに署名する <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-signingyourownscripts" id="writingscriptsforremoteactionsonwindowsforfinder-classic-signingyourownscripts"></a>

セキュリティ上の理由から、Nexthinkは作成したすべてのスクリプトに署名することを強く推奨しています。 署名されていないスクリプトは、プレプロダクション環境でのテストにのみ適しています。

PowerShellスクリプトに署名するには、次のように[Set-Authenticode](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-authenticodesignature?view=powershell-7)コマンドを使用します：

1. コード署名証明書を次から取得します：
   * [PowerShell 証明書プロバイダー](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/about/about_certificate_provider?view=powershell-7):\
     `$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert`
   * PFXファイル:\
     `$cert = Get-PfxCertificate -FilePath C:\Test\Mysign.pfx`
2. リモートアクション用のスクリプト、例えば `remoteaction.ps1`に、コード署名証明書を使って署名し、有効期限切れ後も動作を維持するためにタイムスタンプを追加します。 以下の例ではDigiCertタイムスタンプサーバーを使用しています: `Set-AuthenticodeSignature -FilePath .\remoteaction.ps1 -Certificate $cert -IncludeChain All -TimestampServer "http://timestamp.digicert.com"`
3. オプション：スクリプト内の署名を検証します。 `Get-AuthenticodeSignature .\remoteaction.ps1 -Verbose | fl`

## コード署名証明書の展開 <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-deployingthecode-signingcertificate" id="writingscriptsforremoteactionsonwindowsforfinder-classic-deployingthecode-signingcertificate"></a>

デフォルトポリシーにより、Nexthink Libraryからの公式のリモートアクションはデバイス上で追加の設定なしに実行できます。 独自のリモートアクション用スクリプトを作成して署名することを選択する場合は、その署名証明書をMicrosoft Windowsの**ローカルコンピューター > 信頼された発行元**証明書ストアに追加します。

{% hint style="warning" %}
コード署名証明書をMicrosoft Windowsの**ローカルコンピューター >** **信頼された発行元**ストアに追加しない場合、次のエラーが生成されます：**リモートアクションを実行できませんでした：スクリプト署名が無効、または証明書が信頼されていません。**
{% endhint %}

さらに、スクリプトに署名するための証明書がプライベートCAによって生成されたもので、Windowsのローカルコンピューターの信頼されたルート証明機関の証明書ストアにルート証明書が存在しない場合は、そのルート証明書をローカルコンピューターの信頼されたルート証明機関の証明書ストアに追加します。 同様に、中間証明書を使用してスクリプトに署名した場合は、その中間証明書の完全なチェーンをローカルコンピューターの中間証明機関の証明書ストアに含めます：

1. 管理者としてMicrosoft Windowsにログインします。
2. **Win+R**キーを押して実行ダイアログを開きます。
   1. **certlm.msc**と入力します。
   2. **OK**をクリックします。
3. プログラムがデバイスに変更を加えることを許可するには、**はい**をクリックします。
4. 左側のリストで、例えば**信頼された発行元**などの目的の証明書ストアの名前を右クリックします。
   1. コンテキストメニューから\*\*すべてのタスク > インポート...\*\*を選択して証明書インポートウィザードを開始します。
5. ウィザードを開始するには、**次へ**をクリックします。
6. **参照**をクリックして証明書ファイルを選択します。
7. **次へ**をクリックします。
8. 証明書を以下のストアにすべて配置のダイアログウィンドウで提案された証明書ストアを受け入れるには、**次へ**をクリックします。
9. インポートする証明書を確認し、**完了**をクリックします。

<figure><img src="https://3549141153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FeLm8O7QKZDn6z806e7Sv%2Fuploads%2Fgit-blob-45054cb238221b18beef7f77c319d9fe742ffa7d%2Fra-1699365242%20(1).png?alt=media" alt="Certificates" width="760"><figcaption></figcaption></figure>

各デバイスに証明書を個別にインポートするのではなく、管理ツールを使用して同時にすべてのデバイスに証明書を展開することを、Nexthinkは推奨しています。 例えば、Active DirectoryのGroup Policy Objects (GPOs) を使用してこれを達成します。

## 一般的なスクリプトを作成する <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-writinggenericscripts" id="writingscriptsforremoteactionsonwindowsforfinder-classic-writinggenericscripts"></a>

特定の使用ケースに適応するために、スクリプトを一般的に記述することができます。 スクリプトを一般化するために、PowerShellスクリプトの先頭で形式的なパラメータを宣言します。 スクリプトを含むリモートアクションを編集する際にFinderでパラメータに実際の値を提供します。

スクリプトを一般化することは、カスタマイズが必要なデジタル署名付きスクリプトにおいて特に有用です。 スクリプトが署名されていると、そのテキスト内容の変更は署名を破損させます。 署名付きスクリプトを一般化することにより、パラメータを通じてそのカスタマイズを可能にします。 パラメータを使用することで、スクリプトのテキストは変更されないため、デジタル署名は有効なままです。 リモートアクションがスクリプトに渡すパラメータの値は、その実際の動作を決定します。

例えば、一般的なレジストリキーから読み取るスクリプトを作成するには、スクリプトの中でレジストリ内のキーへのパスを含むパラメータを宣言します。 このようにして、同じスクリプトを使って異なるレジストリキーから読むために、いくつかのリモートアクションがスクリプト内のパラメータへの異なるパスを提供することで利用できます。

PowerShellスクリプトの通常の方法で、スクリプトの開始時にパラメーターを宣言します。

```
param(
    [string]$filePath,
    [string]$regPath
)
```

リモートアクションの設定時にスクリプトをアップロードすると、システムはインポートされたPowerShellスクリプトのパラメータを認識し、それらを**パラメータ**セクションにリストします。 各パラメータ名の右側に表示されるテキスト入力ボックスにパラメータの実際の値を入力します。 実際の値は常にテキストとしてスクリプトに渡されることに注意してください：もしスクリプトが**string**以外の型でパラメータを宣言している場合、スクリプトが期待する型に変換できる値を提供することを保証してください。

## 出力変数 <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-outputvariables" id="writingscriptsforremoteactionsonwindowsforfinder-classic-outputvariables"></a>

スクリプトの実行によって生成される出力を、データ層でオンデマンドとして保存したい場合があります。 そのために、NexthinkはCollectorと同時に従業員デバイスにインストールされる.NETアセンブリ(`nxtremoteactions.dll`)を提供しています。 アセンブリには、データ層に結果を書き込むためのメソッドを提供する**Nxt**というクラスが含まれています。

リモートアクション用のPowerShellスクリプトの冒頭に以下の行を追加して、**Nxt**クラスを使用します：

`Add-Type -Path $env:NEXTHINK\RemoteActions\nxtremoteactions.dll`

Nxtクラスのメソッドを使用して、必要な出力を書き込みます。 すべての書き込みメソッドは2つの引数を受け入れます：出力の名前と書き込む値です。 例えば、データ層にファイルのサイズを書き込む場合：

`[Nxt]::WriteOutputSize("FileSize", $fileSize)`

リモートアクションの設定時にスクリプトをアップロードすると、システムはスクリプト内の出力を書く呼び出しを認識し、スクリプトテキストの下の**出力**セクション内に出力変数をリストします。 調査やメトリクスで参照する方法を示すために、出力ラベルを設定します。

各書き込みメソッドの末尾は出力のタイプを示します。 使用可能なメソッドと書き込まれる値の対応するPowerShellのタイプを以下の表で確認してください：

| Nxt書き込みメソッド           | PowerShellタイプ | 制約                                                          |
| --------------------- | ------------- | ----------------------------------------------------------- |
| WriteOutputString     | \[string]     | 0 - 1024文字（出力が大きい場合は切り捨て）                                   |
| WriteOutputBool       | \[bool]       | true / false                                                |
| WriteOutputUInt32     | \[uint32]     | <ul><li>最小: 0</li><li>最大: 4 294 967 295</li></ul>           |
| WriteOutputFloat      | \[float]      | <ul><li>最小: -3.4E+38</li><li>最大: 3.4E+38</li></ul>          |
| WriteOutputSize       | \[float]      | <ul><li>最小: 0</li><li>最大: 3.4E+38</li></ul>                 |
| WriteOutputRatio      | \[float]      |                                                             |
| WriteOutputBitRate    | \[float]      |                                                             |
| WriteOutputDateTime   | \[DateTime]   | DD.MM.YYYY\@HH:MM                                           |
| WriteOutputDuration   | \[TimeSpan]   | <ul><li>最小: 0 ms</li><li>最大: 49日</li><li>精度はミリ秒単位</li></ul> |
| WriteOutputStringList | \[string\[]]  | stringと同じ                                                   |

## 自己支援シナリオで従業員と対話する <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-interactingwithemployeesinself-helpscenario" id="writingscriptsforremoteactionsonwindowsforfinder-classic-interactingwithemployeesinself-helpscenario"></a>

従業員が問題を自分で解決するのを助けるために、リモートアクションをキャンペーンと組み合わせます。 リモートアクションと組み合わせることで、従業員に問題の検出を通知し、その解決に導くことができます。

デバイスを使用している従業員のデスクトップにキャンペーンを表示するには：

* キャンペーンには**リモートアクション**トリガーがあり、公開されている必要があります。
* リモートアクションのスクリプトは次のいずれかで実行できます：
  * 特別な権限を必要としない場合は、従業員のコンテキストで。
  * 管理者権限を必要とする場合は、ローカルシステムアカウントのコンテキストで。

### キャンペーンのUIDを取得する <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-obtainingtheuidofacampaign" id="writingscriptsforremoteactionsonwindowsforfinder-classic-obtainingtheuidofacampaign"></a>

リモートアクションからキャンペーンを実行する方法には、キャンペーンのUIDを引数として渡す必要があります。

リモートアクションにキャンペーン識別子を渡すには、リモートアクションのスクリプト内で必要なキャンペーンごとにパラメータを宣言します。 リモートアクションを編集する際に、実際の値としてUIDをパラメータに使用します。

キャンペーンのUIDを取得し、リモートアクションにパラメータとして渡すには：

1. キャンペーンとリモートアクションを編集する権限を持つユーザーとしてFinderにログインします。
2. 左側のメニューの**キャンペーン**セクションで、リモートアクションから起動したいキャンペーンの名前を右クリックします。
3. **エクスポート > キャンペーンUidをクリップボードへ**を選択して、キャンペーンのUIDをコピーします。
4. 左側のメニューの**リモートアクション**セクションで、キャンペーンを実行するリモートアクションの名前をダブルクリックして編集します。 リモートアクションには、キャンペーンのUIDを格納するためのパラメータを宣言するスクリプトが含まれている必要があります。
5. スクリプトの下にある**パラメータ**セクションで、キャンペーンのUIDを保持するパラメータを選択します。
6. **Ctrl+V**を押してキャンペーンの実際のUIDを貼り付け、対応するパラメータに割り当てます。

### リモートアクションのスクリプトからキャンペーンを実行する <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-runningacampaignfromthescriptofaremoteactio" id="writingscriptsforremoteactionsonwindowsforfinder-classic-runningacampaignfromthescriptofaremoteactio"></a>

キャンペーンと対話するために、リモートアクションスクリプトは、Collectorと共に従業員デバイスにインストールされる.NETアセンブリ(`nxtcampaignaction.dll`)を読み込む必要があります。 アセンブリには、キャンペーンの実行を制御し、従業員からの応答を取得するためのメソッドを提供する**Nxt.CampaignAction**クラスが含まれています。

アセンブリを読み込むには、スクリプトの冒頭に以下の行を追加します：

`Add-Type -Path $env:NEXTHINK\RemoteActions\nxtcampaignaction.dll`

キャンペーンを制御するための**Nxt.CampaignAction**メソッドは次の通りです：

`NxTrayResp RunCampaign(string campaignUid)`

`campaignUid`で識別されるキャンペーンを実行し、従業員がキャンペーンの回答を終了するまで待ちます。 `campaignUid`引数にはUIDが含まれます。 応答を`NxTrayResp`型のオブジェクトで返します。

`NxTrayResp RunCampaign(string campaignUid, int timeout)`

`campaignUid`で識別されるキャンペーンを実行し、従業員がキャンペーンの回答を終了するか、指定された`timeout` (秒単位) 期間が経過するまで待ちます。 応答を`NxTrayResp`型のオブジェクトで返します。

`RunStandAloneCampaign(string campaignUid)`

`campaignUid`で識別されるキャンペーンを実行します。

`string GetResponseStatus(NxTrayResp response)`

`NxTrayResp`型の応答オブジェクトが与えられた場合、そのキャンペーンのステータスを反映する文字列を返します。 ステータスの可能な値：

* **fully**: 従業員がキャンペーンの質問に完全に回答しました。
* **declined**: 従業員がキャンペーンへの参加を拒否しました。
* **延期**: その従業員はキャンペーンへの参加に同意しました。
* **タイムアウト**: システムが従業員が回答を終える前にキャンペーンをタイムアウトしました。
* **接続失敗**: Collector コンポーネント間の通信に技術的なエラーがあったため、キャンペーン通知を制御する Collector コンポーネントへの接続がスクリプトでできませんでした。
* **通知失敗**: スクリプトがキャンペーンを成功裏に表示できなかった原因は以下の一つまたは複数です：
  * キャンペーンが存在しないか、公開されていないため、プラットフォームからキャンペーン定義を取得できませんでした。
  * 別のキャンペーンが既に従業員に表示されています。
  * Collector のフォーカス保護または「邪魔しない」ルールのため、緊急でないキャンペーンを表示することができません。 詳細については、[キャンペーンの受信レートを制限する](https://docs.nexthink.com/platform/ja/user-guide/campaigns/managing-campaigns/creating-campaigns/limiting-the-reception-rate-of-campaigns) ドキュメントをご参照ください。

`string[] GetResponseAnswer(NxTrayResp response, string questionLabel)`

`NxTrayResp` 型の応答オブジェクトとキャンペーン内の質問を識別するラベルを受け取ると、メソッドは従業員からの応答を返します。

* 単一回答の質問の場合、返される文字列配列は1つの要素だけを持ちます。
* 複数回答の質問の場合、返される文字列配列は、従業員が選択した回答の数だけ要素を持ちます。 任意の自由記述テキストは無視されます。
* 例えば、ステータスが「完全」ではない場合など、従業員がキャンペーンに完全に回答していない場合、返される文字列配列は空です。 任意の自由記述テキストは無視されます。

{% hint style="info" %}
セキュリティ上の理由から、自己援助シナリオのリモートアクションは、複数の回答や意見尺度質問の任意の自由記述答案を無視します。 したがって、自己援助シナリオでのみ使用されるキャンペーンには、任意の自由記述答案を含めることは無意味です。
{% endhint %}

### コード例 <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-codeexample" id="writingscriptsforremoteactionsonwindowsforfinder-classic-codeexample"></a>

この例では、*yes* のような可能な回答がある単一回答キャンペーンを作成したと仮定します：

```
Add-Type -Path "$env:NEXTHINK\RemoteActions\nxtcampaignaction.dll"

$CampaignUid  = "<UID of a single-answer campaign>"
$maxWaitTimeinSeconds = 60

$result = [Nxt.CampaignAction]::RunCampaign($CampaignUid, $maxWaitTimeinSeconds)
$status = [Nxt.CampaignAction]::GetResponseStatus($result)

if ($status -eq "fully") {
    $questionName = "question1"
    $choiceName =[Nxt.CampaignAction]::GetResponseAnswer($result, $questionName)
 if ($choiceName -eq "yes") {
        # user has confirmed - let's do some actions:
        Start-Process notepad.exe
    }
}
```

## エラーハンドリング <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-errorhandling" id="writingscriptsforremoteactionsonwindowsforfinder-classic-errorhandling"></a>

Nexthink は、スクリプトを実行した PowerShell プロセスの戻り値に基づいて、リモートアクションの実行が成功したかどうかを検出します：

* 終了コードの値が0であることは、実行が成功したことを示します。
* 非ゼロの値はエラーを示します。

しかし、PowerShell の未処理例外は、適切な終了コードを返すことなくスクリプトを終了させる可能性があります。 予期しないエラーを処理するために、Nexthink は以下のコードスニペットで全てのスクリプトの本文を始めることを推奨します：

```
 trap {
     $host.ui.WriteErrorLine($_.ToString())
     exit 1
 }
```

あらゆる形式のパラメータ宣言の後に続く、必要なDLL依存関係のインクルージョンの下にこのデフォルトのエラーハンドラーを配置します。

## パフォーマンス測定 <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-performancemeasurement" id="writingscriptsforremoteactionsonwindowsforfinder-classic-performancemeasurement"></a>

スクリプトのパフォーマンスとリソース消費を測定するために、[コレクター構成ツール](https://docs.nexthink.com/platform/ja/configuring_nexthink/bringing-data-into-your-nexthink-instance/deploying-nexthink-in-non-vdi-environment/installing-collector/windows-collector-references/collector-configuration-tool-for-windows.md)を使ってCollectorのログをデバッグモードでオンにします。

`nxtcfg.exe /s logmode=2`

出力は、[nxtcod.log ファイル](https://docs.nexthink.com/platform/ja/user-guide/remote-actions/remote-actions-in-finder-classic/broken-reference)に保存されます。

{% hint style="info" %}
この記事で説明されている操作は、Nexthink エンジニアまたは Nexthink 認定パートナーによってのみ実行されるべきです。

必要に応じて、Nexthink 認定パートナーにお問い合わせください。
{% endhint %}

### パフォーマンス測定 <a href="#writingscriptsforremoteactionsonwindowsforfinder-classic-performancemeasurement.1" id="writingscriptsforremoteactionsonwindowsforfinder-classic-performancemeasurement.1"></a>

スクリプトのパフォーマンスとリソース消費を測定するために、[コレクター構成ツール](https://docs.nexthink.com/platform/ja/configuring_nexthink/bringing-data-into-your-nexthink-instance/deploying-nexthink-in-non-vdi-environment/installing-collector/windows-collector-references/collector-configuration-tool-for-windows.md)を使ってCollectorのログをデバッグモードでオンにします。

`nxtcfg.exe /s logmode=2`

出力は、[nxtcod.log ファイル](https://docs.nexthink.com/platform/ja/user-guide/remote-actions/remote-actions-in-finder-classic/broken-reference)に保存されます。

{% hint style="info" %}
この記事で説明されている操作は、Nexthink エンジニアまたは Nexthink 認定パートナーによってのみ実行されるべきです。

必要に応じて、Nexthink 認定パートナーにお問い合わせください。
{% endhint %}
