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

求助:基于PowerShell的XAML ListView进程终止功能失效

解决PowerShell XAML ListView终止选中进程失败问题

问题概述

开发了一个带按钮的WPF ListView界面,用于展示名称匹配powershell*或pwsh*的进程,但点击按钮无法终止选中进程,测试时Write-Host输出为空,仅$procids能正常返回进程ID。

错误分析

代码存在以下关键问题:

  • 事件绑定时机错误:在$xamlForm.showdialog()之后才绑定按钮点击事件,此时对话框已启动,事件未被注册。
  • 选中项获取方式错误:使用CurrentItem而非SelectedItem获取选中项,且字符串插值写法错误,无法正确读取属性值。
  • 进程终止方法错误:Processid.remove不是合法的进程终止方法,未调用正确的终止命令。
  • 错误引用WinForms API:界面基于WPF,却调用WinForms的DoEvents,属于API误用。
  • 进程获取逻辑冗余:重复调用Get-CimInstance,且Get-Process -id $cim参数错误,$cim是实例数组而非单个ID。

修正后的完整代码

[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
$input = @'
<Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="End Processes" Height="450" Width="870">
    <Grid>
        <Button Name="btnEndProc" Content="End Process" HorizontalAlignment="Left" Height="45" Margin="112,341,0,0" VerticalAlignment="Top" Width="110"/>
        <ListView Name="listdisk" HorizontalAlignment="Left" Height="200" Margin="12,107,-140,0" VerticalAlignment="Top" Width="840" SelectionMode="Single">
           <ListView.View>
                <GridView>
                    <GridViewColumn Header="Process ID" DisplayMemberBinding ="{Binding ProcessID}" Width="100"/>
                    <GridViewColumn Header="Name" DisplayMemberBinding ="{Binding Name}" Width="255"/>
                    <GridViewColumn Header="Handle Count" DisplayMemberBinding ="{Binding HandleCount}" Width="105"/>
                    <GridViewColumn Header="Working Set Size" DisplayMemberBinding ="{Binding Workingsetsize}" Width="100"/>
                    <GridViewColumn Header="Virtual Size" DisplayMemberBinding ="{Binding VirtualSize}" Width="105"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>
'@

# 解析XAML
[xml]$xaml = $input
$xmlreader=(New-Object System.Xml.XmlNodeReader $xaml)
$xamlForm=[Windows.Markup.XamlReader]::Load($xmlReader)

# 绑定控件变量
$xaml.SelectNodes("//*[@Name]") | ForEach-Object {
    Set-variable -name $_.Name -Value $xamlForm.Findname($_.Name)
}

# 获取目标进程
$cimProcesses = Get-CimInstance -ClassName Win32_Process -Filter "Name like 'Powershell%' or Name like 'pwsh%'" 
$listdisk.ItemsSource = $cimProcesses

# 绑定按钮点击事件(必须在showdialog之前)
$btnEndProc.add_click({
    $selectedItem = $listdisk.SelectedItem
    if ($selectedItem) {
        $processId = $selectedItem.ProcessID
        Write-Host "终止进程ID: $processId"
        # 方式1:用Stop-Process终止
        Stop-Process -Id $processId -Force -ErrorAction SilentlyContinue
        # 方式2:用CIM方法终止(二选一即可)
        # Stop-CimInstance -InputObject $selectedItem -ErrorAction SilentlyContinue
        
        # 刷新列表
        $listdisk.ItemsSource = Get-CimInstance -ClassName Win32_Process -Filter "Name like 'Powershell%' or Name like 'pwsh%'"
    } else {
        Write-Host "未选中任何进程"
    }
})

# 显示窗口
$xamlForm.Activate()
$xamlForm.ShowDialog() | Out-Null

关键修正说明

  1. 调整事件绑定顺序:将按钮点击事件绑定代码移至ShowDialog()之前,确保事件在窗口启动前注册成功。
  2. 正确获取选中项:使用$listdisk.SelectedItem获取用户选中的进程实例,添加空值判断避免报错。
  3. 合法终止进程:使用Stop-Process或Stop-CimInstance命令终止进程,添加-Force确保强制终止,-ErrorAction SilentlyContinue忽略不存在的进程错误。
  4. 刷新列表:终止进程后重新获取进程列表并绑定到ListView,更新界面显示。
  5. 优化XAML:为ListView添加SelectionMode="Single"明确单选模式,移除无用的local命名空间。
  6. 简化进程获取逻辑:仅调用一次Get-CimInstance并赋值给变量,避免重复查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:34:51