You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在PowerShell中使用WebView2的GetCookiesAsync时出现冻结问题

解决PowerShell中WebView2调用GetCookiesAsync导致的冻结问题

问题原因

你当前的代码在NavigationCompleted事件处理中使用GetAwaiter().GetResult()同步等待异步任务完成,这会引发UI线程死锁:

  • NavigationCompleted事件运行在UI线程上
  • GetCookiesAsync的后续回调需要回到UI线程执行
  • 同步等待会阻塞UI线程,导致WebView2无法处理后续操作,最终界面冻结

正确实现方式

需要避免在UI线程中同步等待异步任务,改用异步事件监听的方式获取Cookie,同时使用全局变量存储结果以便后续调用。

修改后的完整脚本

#Based on https://stackoverflow.com/questions/66106927/webview2-in-powershell-winform-gui
#----------------------------------------------
#region Import the Assemblies
#----------------------------------------------
[void][reflection.assembly]::LoadFile("$PSScriptRoot\assemblies\Microsoft.Web.WebView2.Winforms.dll")
[void][reflection.assembly]::LoadFile("$PSScriptRoot\assemblies\Microsoft.Web.WebView2.Core.dll")
[void][reflection.assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][reflection.assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
#endregion Import Assemblies

#----------------------------------------------
#region Generated Form Objects
#----------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$form1 = New-Object 'System.Windows.Forms.Form'
$buttonRefresh = New-Object 'System.Windows.Forms.Button'
$buttonGo = New-Object 'System.Windows.Forms.Button'
$textbox1 = New-Object 'System.Windows.Forms.TextBox'
[Microsoft.Web.WebView2.WinForms.WebView2] $webview = New-Object 'Microsoft.Web.WebView2.WinForms.WebView2'
$webview.CreationProperties = New-Object 'Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties'
$webview.CreationProperties.UserDataFolder = $PSScriptRoot;
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
#endregion Generated Form Objects

# 全局变量存储Cookie结果
$global:authCookies = $null

#----------------------------------------------
# User Generated Script
#----------------------------------------------

$form1_Load={
    $webview.Source = ([uri]::new($textbox1.Text))
    $webview.Visible = $true
}

$buttonGo_Click={
    $webview.Source = [System.Uri] $textbox1.Text
}

$webview_SourceChanged={
    $form1.Text = $webview.Source.AbsoluteUri
}

$coreWebView2Initialized = { 
    $cookieManager = $webview.CoreWebView2.CookieManager;
    $cookie = $cookieManager.CreateCookie("name", "value", "example.com", "/")
    $cookieManager.AddOrUpdateCookie($cookie);
}

$webview_OnNavigationCompleted={
    # 启动异步Cookie获取任务,不阻塞UI线程
    $getCookiesTask = $webview.CoreWebView2.CookieManager.GetCookiesAsync("")
    
    # 监听任务完成事件,异步处理结果
    Register-ObjectEvent -InputObject $getCookiesTask -EventName Completed -Action {
        $global:authCookies = $EventArgs.Result
        Write-Host "成功获取到 $($global:authCookies.Count) 个Cookie"
        
        # 可选:将Cookie转换为REST API可用的格式
        $cookieHeader = ($global:authCookies | ForEach-Object { "$($_.Name)=$($_.Value)" }) -join "; "
        Write-Host "Cookie请求头格式: $cookieHeader"
    } | Out-Null
} 

# --End User Generated Script--

#----------------------------------------------
#region Generated Events
#----------------------------------------------

$Form_StateCorrection_Load=
{
    #Correct the initial state of the form to prevent the .Net maximized form issue
    $form1.WindowState = $InitialFormWindowState
}

$Form_Cleanup_FormClosed=
{
    #Remove all event handlers from the controls
    try
    {
        $buttonGo.remove_Click($buttonGo_Click)
        $webview.remove_SourceChanged($webview_SourceChanged)
        $form1.remove_Load($form1_Load)
        $form1.remove_Load($Form_StateCorrection_Load)
        $form1.remove_FormClosed($Form_Cleanup_FormClosed)
    }
    catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
}
#endregion Generated Events

#----------------------------------------------
#region Generated Form Code
#----------------------------------------------
$form1.SuspendLayout()
$form1.Controls.Add($buttonRefresh)
$form1.Controls.Add($buttonGo)
$form1.Controls.Add($textbox1)
$form1.Controls.Add($webview)
$form1.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$form1.AutoScaleMode = 'Font'
$form1.ClientSize = New-Object System.Drawing.Size(619, 413)
$form1.Name = 'form1'
$form1.Text = 'Form'
$form1.add_Load($form1_Load)
#
# buttonRefresh
#
$buttonRefresh.Location = New-Object System.Drawing.Point(13, 13)
$buttonRefresh.Name = 'buttonRefresh'
$buttonRefresh.Size = New-Object System.Drawing.Size(75, 23)
$buttonRefresh.TabIndex = 3
$buttonRefresh.Text = 'Refresh'
$buttonRefresh.UseVisualStyleBackColor = $True
#
# buttonGo
#
$buttonGo.Location = New-Object System.Drawing.Point(538, 9)
$buttonGo.Name = 'buttonGo'
$buttonGo.Size = New-Object System.Drawing.Size(75, 23)
$buttonGo.TabIndex = 2
$buttonGo.Text = 'Go'
$buttonGo.UseVisualStyleBackColor = $True
$buttonGo.add_Click($buttonGo_Click)
#
# textbox1
#
$textbox1.Location = New-Object System.Drawing.Point(96, 13)
$textbox1.Name = 'textbox1'
$textbox1.Size = New-Object System.Drawing.Size(435, 20)
$textbox1.TabIndex = 1
$textbox1.Text = 'https://www.bing.com'
#
# webview
#
$webview.Location = New-Object System.Drawing.Point(0, 49)
$webview.Name = 'webview'
$webview.Size = New-Object System.Drawing.Size(619, 364)
$webview.TabIndex = 0
$webview.ZoomFactor = 1
$webview.add_SourceChanged($webview_SourceChanged)

#Actions with cookies
$webview.add_NavigationCompleted($webview_OnNavigationCompleted)
$webview.add_CoreWebView2InitializationCompleted($coreWebView2Initialized)

$form1.ResumeLayout()
#endregion Generated Form Code

#----------------------------------------------

#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($Form_StateCorrection_Load)
#Clean up the control events
$form1.add_FormClosed($Form_Cleanup_FormClosed)
#Show the Form
$form1.ShowDialog()

# 窗体关闭后输出Cookie
if ($global:authCookies) {
    Write-Host "`n获取到的Cookie列表:"
    $global:authCookies | Select-Object Name, Value, Domain, Path | Format-Table -AutoSize
}
Read-Host

关键修改点

  1. 新增全局变量$global:authCookies存储Cookie结果,避免局部变量作用域问题
  2. 在NavigationCompleted事件中,不再同步等待任务完成,而是通过Register-ObjectEvent监听异步任务的Completed事件
  3. 任务完成后异步处理Cookie结果,同时提供了转换为REST API请求头格式的示例

补充说明

  • 若需要针对特定域名获取Cookie,可将GetCookiesAsync("")中的空字符串替换为目标域名(如"https://your-app-domain.com")
  • 全局变量$global:authCookies可直接用于后续的REST API请求,例如:
    $headers = @{
        "Cookie" = ($global:authCookies | ForEach-Object { "$($_.Name)=$($_.Value)" }) -join "; "
    }
    Invoke-RestMethod -Uri "https://your-api-endpoint" -Headers $headers
    

内容的提问来源于stack exchange,提问作者TedJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 05:24:56