PowerShell Azure Functions をローカルでデバッグする

Azure Functions を使用すると、PowerShell スクリプトとして関数を開発できます。

次の標準開発ツールを使用して、PowerShell スクリプトと同様に、PowerShell 関数をローカルでデバッグできます。

  • Visual Studio Code: 完全な PowerShell 開発エクスペリエンスを提供する PowerShell 拡張機能を備えた、Microsoft の無料の軽量でオープン ソースのテキスト エディター。
  • PowerShell コンソール: 他の PowerShell プロセスのデバッグに使用するのと同じコマンドを使用してデバッグします。

Azure Functions Core Tools では 、PowerShell 関数を含む Azure Functions のローカル デバッグがサポートされています。

関数アプリの例

この記事で使用する関数アプリには、HTTP によってトリガーされる関数が 1 つあり、次のファイルがあります。

PSFunctionApp
 | - HttpTriggerFunction
 | | - run.ps1
 | | - function.json
 | - local.settings.json
 | - host.json
 | - profile.ps1

この関数アプリは、 PowerShell クイック スタートを完了したときに取得する関数アプリと似ています。

run.ps1の関数コードは、次のスクリプトのようになります。

param($Request)

$name = $Request.Query.Name

if($name) {
    $status = 200
    $body = "Hello $name"
}
else {
    $status = 400
    $body = "Please pass a name on the query string or in the request body."
}

Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = $status
    Body = $body
})

アタッチ ポイントを設定する

PowerShell 関数をデバッグするには、デバッガーをアタッチするために関数を停止する必要があります。 Wait-Debugger コマンドレットは実行を停止し、デバッガーを待機します。

PowerShell 7 を使用する場合、コードに Wait-Debugger 呼び出しを追加する必要はありません。

必要なのは、次のように、Wait-Debugger ステートメントのすぐ上に if コマンドレットの呼び出しを追加することです。

param($Request)

$name = $Request.Query.Name

# This is where we will wait for the debugger to attach
Wait-Debugger

if($name) {
    $status = 200
    $body = "Hello $name"
}
# ...

デバッグは、 if ステートメントから開始します。

Wait-Debuggerを配置すると、Visual Studio Code または PowerShell コンソールを使用して関数をデバッグできるようになりました。

Visual Studio Code でのデバッグ

Visual Studio Code で PowerShell 関数をデバッグするには、次のものがインストールされている必要があります。

これらの依存関係をインストールした後、既存の PowerShell Functions プロジェクトを読み込むか、 最初の PowerShell Functions プロジェクトを作成します

プロジェクトに必要な構成ファイルがない場合は、それらを追加するように求められます。

PowerShell のバージョンを設定する

PowerShell Core は、Windows PowerShell と並行してインストールされます。 PowerShell Core を PowerShell バージョンとして設定し、Visual Studio Code 用の PowerShell 拡張機能で使用します。

  1. F1 キーを押してコマンド パレットを表示し、 Sessionを検索します。

  2. [PowerShell: セッションメニューの表示] を選択します

  3. 現在のセッションPowerShell Core 6 でない場合は、[切り替え: PowerShell Core 6] を選択します。

PowerShell ファイルを開くと、ウィンドウの右下にバージョンが緑色で表示されます。 このテキストを選択すると、セッション メニューも表示されます。 詳細については、「 拡張機能で使用する PowerShell のバージョンの選択」を参照してください

関数アプリを起動する

デバッガーをアタッチする関数で Wait-Debugger が設定されていることを確認します。 Wait-Debugger追加すると、Visual Studio Code を使用して関数アプリをデバッグできます。

[デバッグ] ウィンドウを選択し、[Attach to PowerShell function]\(PowerShell 関数にアタッチする\) を選択します。

デバッガー

F5 キーを押してデバッグを開始することもできます。

デバッグ開始操作では、次のタスクが実行されます。

  • ターミナルで func extensions install 実行して、関数アプリに必要なすべての Azure Functions 拡張機能をインストールします。
  • ターミナルで func host start を実行して、Functions ホストで関数アプリを起動します。
  • Functions ランタイム内の PowerShell 実行空間に PowerShell デバッガーをアタッチします。

Visual Studio Code で正しいデバッグ エクスペリエンスを確保するには、PSWorkerInProcConcurrencyUpperBound が 1 に設定されていることを確認する必要があります。 これが既定値です。

関数アプリが実行されている場合、HTTP によってトリガーされる関数を呼び出すには、別の PowerShell コンソールが必要です。

この場合、PowerShell コンソールはクライアントです。 Invoke-RestMethodは、関数をトリガーするために使用されます。

PowerShell コンソールで、次のコマンドを実行します。

Invoke-RestMethod "http://localhost:7071/api/HttpTrigger?Name=Functions"

応答がすぐに返されないことがわかります。 これは、 Wait-Debugger がデバッガーをアタッチし、PowerShell の実行ができるだけ早く中断モードになったためです。 これは、後で説明する BreakAll の概念が原因です。 continue ボタンを押すと、デバッガーはWait-Debuggerの直後の行で中断するようになりました。

この時点で、デバッガーがアタッチされ、すべての通常のデバッガー操作を実行できます。 Visual Studio Code でデバッガーを使用する方法の詳細については、 公式ドキュメントを参照してください

スクリプトの実行を継続し、完全に呼び出すと、次のような結果が得られます。

  • Invoke-RestMethodを実行した PowerShell コンソールが結果を返しました
  • Visual Studio Code の PowerShell 統合コンソールは、スクリプトの実行を待機しています

後で同じ関数を呼び出すと、PowerShell 拡張機能のデバッガーは Wait-Debuggerの直後に中断されます。

PowerShell コンソールでのデバッグ

このセクションでは、 Azure Functions Core Tools のドキュメント を読み、 func host start コマンドを使用して関数アプリを起動する方法を把握していることを前提としています。

コンソールを開き、関数アプリのディレクトリに cd し、次のコマンドを実行します。

func host start

関数アプリが実行され、 Wait-Debugger が設定された状態で、プロセスにアタッチできます。 さらに 2 つの PowerShell コンソールが必要です。

コンソールの 1 つがクライアントとして機能します。 ここから、 Invoke-RestMethod を呼び出して関数をトリガーします。 たとえば、次のコマンドを実行できます。

Invoke-RestMethod "http://localhost:7071/api/HttpTrigger?Name=Functions"

応答が返されないことがわかります。これは、 Wait-Debuggerの結果です。 PowerShell の実行空間は、デバッガーがアタッチされるのを待機しています。 それを添付しましょう。

他の PowerShell コンソールで、次のコマンドを実行します。

Get-PSHostProcessInfo

このコマンドレットは、次の出力のようなテーブルを返します。

ProcessName ProcessId AppDomainName
----------- --------- -------------
dotnet          49988 None
pwsh            43796 None
pwsh            49970 None
pwsh             3533 None
pwsh            79544 None
pwsh            34881 None
pwsh            32071 None
pwsh            88785 None

テーブル内のProcessIdProcessNameの項目について、dotnetを書き留めておきます。 このプロセスはあなたの関数アプリです。

次に、次のスニペットを実行します。

# This enters into the Azure Functions PowerShell process.
# Put your value of `ProcessId` here.
Enter-PSHostProcess -Id $ProcessId

# This triggers the debugger.
Debug-Runspace 1

起動すると、デバッガーが中断され、次のような出力が表示されます。

Debugging Runspace: Runspace1

To end the debugging session type the 'Detach' command at the debugger prompt, or type 'Ctrl+C' otherwise.

At /Path/To/PSFunctionApp/HttpTriggerFunction/run.ps1:13 char:1
+ if($name) { ...
+ ~~~~~~~~~~~
[DBG]: [Process:49988]: [Runspace1]: PS /Path/To/PSFunctionApp>>

この時点で、 PowerShell デバッガーのブレークポイントで停止します。 ここから、通常のすべてのデバッグ操作、ステップ オーバー、ステップ イン、続行、終了などを実行できます。 コンソールで使用できるデバッグ コマンドの完全なセットを表示するには、 h または ? コマンドを実行します。

Set-PSBreakpoint コマンドレットを使用して、このレベルでブレークポイントを設定することもできます。

スクリプトを完全に実行すると、次のことに気づくでしょう。

  • Invoke-RestMethodを実行した PowerShell コンソールから結果が返されるようになりました。
  • Debug-Runspace実行した PowerShell コンソールは、スクリプトの実行を待機しています。

同じ関数を (たとえば Invoke-RestMethod を使用して) 再度呼び出すことができます。デバッガーは、 Wait-Debugger コマンドの直後に中断します。

デバッグに関する考慮事項

Functions コードをデバッグするときは、次の問題に注意してください。

BreakAll 予期しない場所でデバッガーが中断する可能性があります

PowerShell 拡張機能では Debug-Runspaceが使用され、PowerShell の BreakAll 機能に依存します。 この機能は、実行される最初のコマンドで停止するように PowerShell に指示します。 この動作により、デバッグされた実行空間内にブレークポイントを設定できます。

Azure Functions ランタイムは、 run.ps1 スクリプトを実際に呼び出す前にいくつかのコマンドを実行するため、デバッガーが最終的に Microsoft.Azure.Functions.PowerShellWorker.psm1 または Microsoft.Azure.Functions.PowerShellWorker.psd1内で中断される可能性があります。

この中断が発生した場合は、 continue または c コマンドを実行して、このブレークポイントをスキップします。 その後、予想されるブレークポイントで停止します。

トラブルシューティング

デバッグ中に問題が発生した場合は、次のことを確認する必要があります。

アクション
ターミナルから func --version を実行します。 funcが見つからないというエラーが発生した場合、ローカルのpath変数にコア ツール (func.exe) が見つからない可能性があります。 Core Tools を再インストールします
Visual Studio Code では、既定のターミナルが func.exeにアクセスできる必要があります。 Linux 用 Windows サブシステム (WSL) など、Core Tools がインストールされていない既定のターミナルを使用していないことを確認します。 Visual Studio Code の既定のシェルを PowerShell 7 (推奨) または Windows PowerShell 5.1 に設定します。

次のステップ

PowerShell を使用した Functions の開発の詳細については、 Azure Functions PowerShell 開発者ガイドを参照してください。