在本地调试 PowerShell Azure FunctionsDebug PowerShell Azure Functions locally

Azure Functions 允许你将函数作为 PowerShell 脚本进行开发。Azure Functions lets you develop your functions as PowerShell scripts.

你可以使用以下标准开发工具,就像调试任何 PowerShell 脚本一样在本地调试 PowerShell 函数:You can debug your PowerShell functions locally as you would any PowerShell scripts using the following standard development tools:

  • Visual Studio Code:Microsoft 提供的轻型且开源的免费文本编辑器,其中包含 PowerShell 扩展,该扩展提供完整的 PowerShell 开发体验。Visual Studio Code: Microsoft's free, lightweight, and open-source text editor with the PowerShell extension that offers a full PowerShell development experience.
  • PowerShell 控制台:使用你在调试任何其他 PowerShell 进程时会所用的命令进行调试。A PowerShell console: Debug using the same commands you would use to debug any other PowerShell process.

Azure Functions Core Tools 支持对 Azure Functions(包括 PowerShell 函数)进行本地调试。Azure Functions Core Tools supports local debugging of Azure Functions, including PowerShell functions.

示例函数应用Example function app

本文中使用的函数应用具有单个 HTTP 触发的函数,并且包含以下文件:The function app used in this article has a single HTTP triggered function and has the following files:

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

此函数应用与你完成 PowerShell 快速入门后得到的应用类似。This function app is similar to the one you get when you complete the PowerShell quickstart.

run.ps1 中的函数代码类似于以下脚本:The function code in run.ps1 looks like the following script:

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
})

设置附加点Set the attach point

若要调试任何 PowerShell 函数,需要停止该函数才能附加调试程序。To debug any PowerShell function, the function needs to stop for the debugger to be attached. Wait-Debugger cmdlet 会停止执行操作并等待调试程序。The Wait-Debugger cmdlet stops execution and waits for the debugger.

备注

使用 PowerShell 7 时,不需要在代码中添加 Wait-Debugger 调用。When using PowerShell 7, you don't need to add the Wait-Debugger call in your code.

你需要做的所有工作是在 if 语句的上方添加对 Wait-Debugger cmdlet 的调用,如下所示:All you need to do is add a call to the Wait-Debugger cmdlet just above the if statement, as follows:

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 语句开始。Debugging starts at the if statement.

有了 Wait-Debugger,你现在就可以使用 Visual Studio Code 或 PowerShell 控制台来调试函数。With Wait-Debugger in place, you can now debug the functions using either Visual Studio Code or a PowerShell console.

在 Visual Studio Code 中进行调试Debug in Visual Studio Code

若要在 Visual Studio Code 中调试 PowerShell 函数,必须安装以下各项:To debug your PowerShell functions in Visual Studio Code, you must have the following installed:

安装这些依赖项后,请加载现有的 PowerShell Functions 项目,或者创建你的第一个 PowerShell Functions 项目After installing these dependencies, load an existing PowerShell Functions project, or create your first PowerShell Functions project.

备注

如果你的项目没有所需的配置文件,则系统会提示你添加它们。Should your project not have the needed configuration files, you are prompted to add them.

设置 PowerShell 版本Set the PowerShell version

PowerShell Core 与 Windows PowerShell 一起安装。PowerShell Core installs side by side with Windows PowerShell. 将 PowerShell Core 设置为要与适用于 Visual Studio Code 的 PowerShell 扩展一起使用的 PowerShell 版本。Set PowerShell Core as the PowerShell version to use with the PowerShell extension for Visual Studio Code.

  1. 按 F1 显示命令面板,然后搜索 SessionPress F1 to display the command pallet, then search for Session.

  2. 选择“PowerShell:显示会话菜单”。Choose PowerShell: Show Session Menu.

  3. 如果你的 当前会话 不是 PowerShell Core 6,请选择“切换到:PowerShell Core 6”。If your Current session isn't PowerShell Core 6, choose Switch to: PowerShell Core 6.

打开 PowerShell 文件后,你会看到版本以绿色显示在窗口右下角。When you have a PowerShell file open, you see the version displayed in green at the bottom right of the window. 选择此文本还会显示会话菜单。Selecting this text also displays the session menu. 若要了解详细信息,请参阅选择要与扩展一起使用的 PowerShell 版本To learn more, see the Choosing a version of PowerShell to use with the extension.

启动函数应用Start the function app

验证在要附加调试程序的函数中是否设置了 Wait-DebuggerVerify that Wait-Debugger is set in the function where you want to attach the debugger. 添加 Wait-Debugger 后,可以使用 Visual Studio Code 调试你的函数应用。With Wait-Debugger added, you can debug your function app using Visual Studio Code.

选择“调试”窗格,然后选择“附加到 PowerShell 函数”。Choose the Debug pane and then Attach to PowerShell function.

调试器

还可以按 F5 键开始调试。You can also press the F5 key to start debugging.

启动调试操作将执行以下任务:The start debugging operation does the following tasks:

  • 在终端中运行 func extensions install 以安装你的函数应用所需的任何 Azure Functions 扩展。Runs func extensions install in the terminal to install any Azure Functions extensions required by your function app.
  • 在终端中运行 func host start 以在 Functions 主机中启动函数应用。Runs func host start in the terminal to start the function app in the Functions host.
  • 将 PowerShell 调试程序附加到 Functions 运行时中的 PowerShell 运行空间。Attach the PowerShell debugger to the PowerShell runspace within the Functions runtime.

备注

你需要确保 PSWorkerInProcConcurrencyUpperBound 设置为 1,以确保 Visual Studio Code 中的调试体验正确。You need to ensure PSWorkerInProcConcurrencyUpperBound is set to 1 to ensure correct debugging experience in Visual Studio Code. 这是默认设置。This is the default.

在函数应用运行时,你需要一个单独的 PowerShell 控制台来调用 HTTP 触发的函数。With your function app running, you need a separate PowerShell console to call the HTTP triggered function.

在这种情况下,PowerShell 控制台就是客户端。In this case, the PowerShell console is the client. Invoke-RestMethod 用来触发函数。The Invoke-RestMethod is used to trigger the function.

在 PowerShell 控制台中运行以下命令:In a PowerShell console, run the following command:

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

你会注意到没有立即返回响应。You'll notice that a response isn't immediately returned. 这是因为 Wait-Debugger 已附加了调试程序,并且 PowerShell 执行已尽快进入中断模式。That's because Wait-Debugger has attached the debugger and PowerShell execution went into break mode as soon as it could. 这是由 BreakAll 概念导致的,下文中将解释此概念。This is because of the BreakAll concept, which is explained later. 按下 continue 按钮后,调试程序现在会在行上的 Wait-Debugger 后立即中断。After you press the continue button, the debugger now breaks on the line right after Wait-Debugger.

此时,调试程序已附加,你可以执行所有正常的调试程序操作。At this point, the debugger is attached and you can do all the normal debugger operations. 有关在 Visual Studio Code 中使用调试程序的详细信息,请参阅官方文档For more information on using the debugger in Visual Studio Code, see the official documentation.

继续操作并完全调用脚本后,你会注意到:After you continue and fully invoke your script, you'll notice that:

  • 执行 Invoke-RestMethod 的 PowerShell 控制台返回了结果The PowerShell console that did the Invoke-RestMethod has returned a result
  • Visual Studio Code 中的 PowerShell 集成控制台正在等待脚本执行The PowerShell Integrated Console in Visual Studio Code is waiting for a script to be executed

以后调用同一函数时,PowerShell 扩展中的调试程序会在 Wait-Debugger 后立即中断。Later when you invoke the same function, the debugger in PowerShell extension breaks right after the Wait-Debugger.

在 PowerShell 控制台中进行调试Debugging in a PowerShell Console

备注

本部分假设你已阅读 Azure Functions Core Tools 文档,并且知道如何使用 func host start 命令来启动函数应用。This section assumes you have read the Azure Functions Core Tools docs and know how to use the func host start command to start your function app.

打开一个控制台,cd 到你的函数应用的目录中,并运行以下命令:Open up a console, cd into the directory of your function app, and run the following command:

func host start

当函数应用运行起来且 Wait-Debugger 就位后,你可以附加到进程。With the function app running and the Wait-Debugger in place, you can attach to the process. 你需要另外两个 PowerShell 控制台。You do need two more PowerShell consoles.

其中一个控制台充当客户端。One of the consoles acts as the client. 在此控制台中,你调用 Invoke-RestMethod 来触发函数。From this, you call Invoke-RestMethod to trigger the function. 例如,你可以运行以下命令:For example, you can run the following command:

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

你会注意到,它没有返回响应,这是由 Wait-Debugger 导致的。You'll notice that it doesn't return a response, which is a result of the Wait-Debugger. PowerShell 运行空间现在正在等待调试程序附加到其中。The PowerShell runspace is now waiting for a debugger to be attached. 接下来,我们来附加该调试程序。Let's get that attached.

在另一个 PowerShell 控制台中运行以下命令:In the other PowerShell console, run the following command:

Get-PSHostProcessInfo

此 cmdlet 会返回一个表,该表类似于以下输出:This cmdlet returns a table that looks like the following output:

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

记下表中 ProcessNamedotnet 的项的 ProcessIdMake note of the ProcessId for the item in the table with the ProcessName as dotnet. 此进程是你的函数应用。This process is your function app.

接下来,运行以下代码片段:Next, run the following snippet:

# 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

启动后,调试程序会中断,并显示类似于以下输出的内容:Once started, the debugger breaks and shows something like the following output:

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 调试程序中的断点处停止。At this point, you're stopped at a breakpoint in the PowerShell debugger. 在这里,你可以执行所有常用的调试操作:单步跳过、单步执行、继续、退出以及其他操作。From here, you can do all of the usual debug operations, step over, step into, continue, quit, and others. 若要查看控制台中可用的完整调试命令集,请运行 h? 命令。To see the complete set of debug commands available in the console, run the h or ? commands.

还可以通过 Set-PSBreakpoint cmdlet 在此级别设置断点。You can also set breakpoints at this level with the Set-PSBreakpoint cmdlet.

继续操作并完全调用脚本后,你会注意到:Once you continue and fully invoke your script, you'll notice that:

  • 你在其中执行了 Invoke-RestMethod 的 PowerShell 控制台现在返回了结果。The PowerShell console where you executed Invoke-RestMethod has now returned a result.
  • 你在其中执行了 Debug-Runspace 的 PowerShell 控制台正在等待脚本执行。The PowerShell console where you executed Debug-Runspace is waiting for a script to be executed.

你可以再次调用同一函数(例如,使用 Invoke-RestMethod 来调用),调试程序会在 Wait-Debugger 命令后立即进入。You can invoke the same function again (using Invoke-RestMethod for example) and the debugger breaks in right after the Wait-Debugger command.

调试注意事项Considerations for debugging

在调试 Functions 代码时,请注意以下问题。Keep in mind the following issues when debugging your Functions code.

BreakAll 可能会导致调试程序在意外的位置进入BreakAll might cause your debugger to break in an unexpected place

PowerShell 扩展使用 Debug-Runspace,后者又依赖于 PowerShell 的 BreakAll 功能。The PowerShell extension uses Debug-Runspace, which in turn relies on PowerShell's BreakAll feature. 此功能告知 PowerShell 在执行的第一个命令处停止。This feature tells PowerShell to stop at the first command that is executed. 此行为使你有机会在所调试的运行空间内设置断点。This behavior gives you the opportunity to set breakpoints within the debugged runspace.

在实际调用你的 run.ps1 脚本之前,Azure Functions 运行时会运行几个命令,因此,调试程序最终可能会在 Microsoft.Azure.Functions.PowerShellWorker.psm1Microsoft.Azure.Functions.PowerShellWorker.psd1 内中断。The Azure Functions runtime runs a few commands before actually invoking your run.ps1 script, so it's possible that the debugger ends up breaking within the Microsoft.Azure.Functions.PowerShellWorker.psm1 or Microsoft.Azure.Functions.PowerShellWorker.psd1.

如果发生此中断,请运行 continuec 命令来跳过此断点。Should this break happen, run the continue or c command to skip over this breakpoint. 然后,你在预期的断点处停止。You then stop at the expected breakpoint.

疑难解答Troubleshooting

如果在调试过程中遇到困难,应检查以下各项:If you have difficulties during debugging, you should check for the following:

检查Check 操作Action
在终端中运行 func --versionRun func --version from the terminal. 如果出现“找不到 func”错误,则可能是因为本地 path 变量缺少 Core Tools (func.exe)。If you get an error that func can't be found, Core Tools (func.exe) may be missing from the local path variable. 重新安装 Core ToolsReinstall Core Tools.
在 Visual Studio Code 中,默认终端需要有权访问 func.exe。In Visual Studio Code, the default terminal needs to have access to func.exe. 请确保使用的不是未安装 Core Tools 的默认终端,例如适用于 Linux 的 Windows 子系统 (WSL)。Make sure you aren't using a default terminal that doesn't have Core Tools installed, such as Windows Subsystem for Linux (WSL). 将 Visual Studio Code 中的默认 shell 设置为 PowerShell 7(推荐)或 Windows PowerShell 5.1。Set the default shell in Visual Studio Code to either PowerShell 7 (recommended) or Windows PowerShell 5.1.

后续步骤Next steps

若要详细了解如何使用 PowerShell 开发 Functions,请参阅 Azure Functions PowerShell 开发人员指南To learn more about developing Functions using PowerShell, see Azure Functions PowerShell developer guide.