You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WPF中获取进程远程IP后MessageBox无显示?代码排查求助

问题分析与修复方案

先来说说你的代码里几个关键问题,这就是导致MessageBox要么不弹要么没内容的核心原因:

1. 页面加载事件绑定错误

你的Page类里用了Window_Loaded方法,但WPF的Page控件的加载事件是Loaded。如果你的XAML里没有把这个方法正确绑定到Page的Loaded事件上,这段代码根本不会执行,自然不会弹出MessageBox。

检查你的Pageone.xaml,确保根元素有这样的绑定:

<Page x:Class="YourNamespace.Pageone"
      ...
      Loaded="Window_Loaded">

或者更规范的,把方法名改成Page_Loaded,再绑定对应事件。

2. Netstat输出解析逻辑严重错位

你处理netstat输出的方式会导致DataTable里的列数据完全错位,尤其是UDP协议的行,直接导致PID匹配失败:

  • Split(' ')分割行时,因为netstat的列之间是多个空格,会生成大量空元素。虽然你过滤了空元素,但填充DataRow的逻辑是循环所有列,找到空的就赋值,这会打乱列的顺序。
  • 针对UDP跳过State列的判断逻辑无效:赋值Protocol列之前就判断dr["Protocol"].ToString() == "UDP",此时dr["Protocol"]还是DBNull.Value,判断永远不成立,UDP行的PID会被错误填充到State列里,后续PID匹配完全不对。

3. 未处理进程已退出的异常

调用Process.GetProcessById(int.Parse(dr["PID"].ToString()))时,如果这个PID对应的进程已经退出,会直接抛出ArgumentException,导致整个解析流程中断,DataTable无法完成填充,自然匹配不到数据。

4. 匹配逻辑不完整且有漏洞

  • 你只实现了PID的匹配,完全没处理procName的匹配(你的需求是procidprocname匹配);
  • 找到匹配行后没有终止循环,后续匹配的行会覆盖remoteIp的值;
  • remoteIp初始化为空字符串,没有匹配到任何行时,MessageBox就会显示空内容。

修复后的完整代码

public partial class Pageone : Page
{
    public Pageone(MainWindow mainWindow)
    {
        InitializeComponent();
    }

    private string remoteIp;

    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        var window = (MainWindow)Application.Current.MainWindow;
        string targetProcName = window.proc1;
        int targetProcPid = window.proc2;
        string targetProcPidStr = targetProcPid.ToString();

        // 先确认获取到的进程信息是否正确
        MessageBox.Show($"目标进程名:{targetProcName}\n目标PID:{targetProcPidStr}");

        DataTable dt = new DataTable();
        dt.Columns.AddRange(new DataColumn[]
        {
            new DataColumn("Protocol"),
            new DataColumn("Local Address"),
            new DataColumn("Foreign Address"),
            new DataColumn("State"),
            new DataColumn("PID"),
            new DataColumn("Process Name"),
        });

        using (Process ns = new Process())
        {
            ProcessStartInfo psi = new ProcessStartInfo("netstat.exe", "-ano")
            {
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true // 不显示命令行窗口
            };
            ns.StartInfo = psi;
            ns.Start();

            using (StreamReader r = ns.StandardOutput)
            {
                string output = r.ReadToEnd();
                ns.WaitForExit();

                string[] lines = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string line in lines.Skip(4)) // 跳过前4行表头和空行
                {
                    // 用正则分割多个空格,直接得到干净的有效元素
                    string[] validElements = System.Text.RegularExpressions.Regex.Split(line.Trim(), @"\s+");
                    if (validElements.Length < 4) continue;

                    DataRow dr = dt.NewRow();
                    dr["Protocol"] = validElements[0];
                    dr["Local Address"] = validElements[1];
                    dr["Foreign Address"] = validElements[2];

                    if (validElements[0].Equals("TCP", StringComparison.OrdinalIgnoreCase))
                    {
                        // TCP行有State列,PID在第4位
                        dr["State"] = validElements[3];
                        dr["PID"] = validElements[4];
                    }
                    else if (validElements[0].Equals("UDP", StringComparison.OrdinalIgnoreCase))
                    {
                        // UDP行没有State列,PID在第3位
                        dr["State"] = DBNull.Value;
                        dr["PID"] = validElements[3];
                    }
                    else
                    {
                        // 忽略其他协议(比如ICMP)
                        continue;
                    }

                    // 安全获取进程名,避免PID不存在的异常
                    try
                    {
                        using (Process proc = Process.GetProcessById(int.Parse(dr["PID"].ToString())))
                        {
                            dr["Process Name"] = proc.ProcessName;
                        }
                    }
                    catch (ArgumentException)
                    {
                        dr["Process Name"] = "未知进程(已退出)";
                    }

                    dt.Rows.Add(dr);
                }
            }
        }

        // 匹配逻辑:优先匹配PID,再匹配进程名,找到第一个匹配项就停止
        foreach (DataRow row in dt.Rows)
        {
            string rowPid = row["PID"].ToString();
            string rowProcName = row["Process Name"].ToString();

            if (rowPid == targetProcPidStr || rowProcName.Equals(targetProcName, StringComparison.OrdinalIgnoreCase))
            {
                remoteIp = row["Foreign Address"].ToString();
                break; // 找到匹配项后立即退出循环,避免被后续行覆盖
            }
        }

        // 处理未匹配到的情况
        if (string.IsNullOrEmpty(remoteIp))
        {
            MessageBox.Show("未找到匹配的网络连接");
        }
        else
        {
            MessageBox.Show($"匹配到的远程IP:{remoteIp}");
        }
    }
}

关键优化点说明

  1. 事件名规范:把Window_Loaded改成Page_Loaded,确保和XAML里的Loaded事件绑定对应;
  2. 正则分割netstat输出:用Regex.Split(line.Trim(), @"\s+")直接分割多个空格,得到干净的有效元素,彻底避免列错位;
  3. 区分TCP/UDP解析:根据协议类型分别处理列索引,确保PID和其他列数据准确对应;
  4. 异常处理:用try-catch包裹Process.GetProcessById,避免进程已退出导致的解析中断;
  5. 完善匹配逻辑:同时支持PID和进程名匹配,找到第一个匹配项就停止循环,避免值被覆盖;
  6. 未匹配提示:如果没有找到任何匹配,给出明确提示,而不是显示空内容;
  7. 添加CreateNoWindow:避免运行netstat时弹出命令行窗口,提升用户体验。

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

火山引擎 最新活动