如何用LINQ对WMI ManagementObjectCollection和Process数组按命令行排序
按命令行排序WMI对象与Process数组的实现方案
要实现按命令行字母排序,并让WMI对象集合与Process数组顺序完全匹配,你可以按以下方式修改代码:
1. 将WMI集合转为可排序列表并按命令行排序
ManagementObjectCollection本身不支持直接LINQ排序,先把它转成泛型列表,再按CommandLine字段排序,同时处理可能的空值避免异常:
// 转换WMI集合为泛型列表,按命令行排序(空命令行排到最后) var sortedWmiList = aobjWMIs.Cast<ManagementObject>() .OrderBy(obj => obj["CommandLine"]?.ToString() ?? string.Empty) .ToList();
2. 根据排序后的WMI列表同步Process数组顺序
先把Process数组转成以进程ID为键的字典提升匹配效率,再根据排序后的WMI对象的ProcessID,生成对应顺序的Process数组:
// 创建进程ID到Process对象的映射 var processById = aprc.ToDictionary(p => p.Id); // 按排序后的WMI列表顺序,匹配对应的Process对象 var sortedProcesses = sortedWmiList .Select(wmi => { int pid = Convert.ToInt32(wmi["ProcessID"]); processById.TryGetValue(pid, out var proc); return proc; }) .Where(proc => proc != null) // 过滤理论上不会出现的匹配失败情况 .ToArray();
完整修改后的代码
替换原代码中注释部分的内容,完整代码如下:
ManagementObjectSearcher objWMISearcher = new ManagementObjectSearcher( "SELECT ProcessID, CommandLine FROM Win32_Process WHERE Name = \"" + strModule + ".exe\""); ManagementObjectCollection aobjWMIs = objWMISearcher.Get(); Process[] aprc = Process.GetProcessesByName(strModule).ToArray(); // 按命令行排序WMI对象并同步Process数组顺序 var sortedWmiList = aobjWMIs.Cast<ManagementObject>() .OrderBy(obj => obj["CommandLine"]?.ToString() ?? string.Empty) .ToList(); var processById = aprc.ToDictionary(p => p.Id); var sortedProcesses = sortedWmiList .Select(wmi => { int pid = Convert.ToInt32(wmi["ProcessID"]); processById.TryGetValue(pid, out var proc); return proc; }) .Where(proc => proc != null) .ToArray(); int nInstance = -1; foreach (ManagementObject objWMI in sortedWmiList) { nInstance++; var currentProcess = sortedProcesses[nInstance]; // 在这里操作objWMI和currentProcess即可 }
关键说明
- 使用
Cast<ManagementObject>()是因为ManagementObjectCollection是非泛型集合,转成泛型后才能使用LINQ排序方法。 - 处理
CommandLine为空的情况,用?? string.Empty确保排序逻辑不会因空引用报错。 - 字典映射的方式避免了每次遍历都在数组中查找进程,在实例较多时能提升性能。
内容的提问来源于stack exchange,提问作者WingedKnight
相关产品推荐
相关产品推荐

