Test-NetConnection通过C# RunspacePool调用返回结果不一致问题排查
Let's break down why you're seeing this 50/50 split in results when calling Test-NetConnection via C# RunspacePool, and how to fix it.
First, some context: When you run Test-NetConnection directly in PowerShell, you're seeing a formatted view of the output object (only 9 properties, defined by PowerShell's built-in formatting rules in NetTCPIP.format.ps1xml). The actual TestNetConnectionResult object returned by the command has 32 properties total. The inconsistency you're seeing comes down to whether your RunspacePool instance is using the formatted view or accessing the raw object's full property set.
Likely Causes
Runspace Formatting Data Loading State
RunspacePool manages a pool of Runspace instances. When a Runspace first executesTest-NetConnection, it loads the required formatting data to display the default 9 properties. If your pool has multiple Runspaces, some may have already loaded this data (returning 9 results) while others haven't (falling back to showing all 32 properties). Since Runspace allocation is random, you get that 50% split.Uncertain Output Handling in Your Code
If your C# code is processing thePSObjectresults without explicitly defining which properties to retrieve, it might sometimes pull the formatted view (from a pre-initialized Runspace) and other times enumerate all raw properties (from a fresh Runspace). There's no explicit| Select *in your command, but the Runspace's state dictates how the output is interpreted.Race Conditions with Concurrent Runspace Use
If multiple threads are using the same RunspacePool simultaneously, you might be hitting edge cases where a Runspace's formatting state isn't fully initialized before your command executes, leading to inconsistent results.
Fixes to Resolve the Inconsistency
1. Explicitly Select the Properties You Need
The most reliable fix is to force PowerShell to return only the 9 properties you expect by adding | Select-Object to your command. This bypasses any formatting state issues entirely:
Test-NetConnection -ComputerName 'D123' -InformationLevel Detailed | Select-Object RemoteAddress, RemotePort, InterfaceAlias, SourceAddress, NameResolutionSucceeded, PingSucceeded, TcpTestSucceeded, TraceRoute, Detailed
In your C# code, this translates to chaining the Select-Object command:
using (var runspacePool = RunspaceFactory.CreateRunspacePool()) { runspacePool.Open(); using (var ps = PowerShell.Create()) { ps.RunspacePool = runspacePool; ps.AddCommand("Test-NetConnection") .AddParameter("ComputerName", "D123") .AddParameter("InformationLevel", "Detailed") .AddCommand("Select-Object") .AddParameter("Property", new[] { "RemoteAddress", "RemotePort", "InterfaceAlias", "SourceAddress", "NameResolutionSucceeded", "PingSucceeded", "TcpTestSucceeded", "TraceRoute", "Detailed" }); var results = ps.Invoke(); // Process results - each PSObject will have exactly 9 properties } runspacePool.Close(); }
2. Pre-Initialize RunspacePool with Required Formatting Data
If you want to stick with the default view without explicitly selecting properties, you can pre-load the formatting data for all Runspaces in the pool. Run a dummy command to initialize the NetTCPIP module before executing your actual test:
using (var runspacePool = RunspaceFactory.CreateRunspacePool()) { runspacePool.Open(); // Pre-load formatting data for Test-NetConnection using (var initPs = PowerShell.Create()) { initPs.RunspacePool = runspacePool; initPs.AddCommand("Import-Module").AddParameter("Name", "NetTCPIP"); initPs.Invoke(); } // Now execute your actual command using (var ps = PowerShell.Create()) { ps.RunspacePool = runspacePool; ps.AddCommand("Test-NetConnection") .AddParameter("ComputerName", "D123") .AddParameter("InformationLevel", "Detailed"); var results = ps.Invoke(); // Results should consistently use the default 9-property view } runspacePool.Close(); }
3. Validate Thread Safety
Ensure your code isn't accessing the same PowerShell instance or RunspacePool from multiple threads concurrently. Each PowerShell instance should be used by one thread at a time to avoid state corruption.
Verify the Root Cause
To confirm this is about formatting vs raw properties, run these commands directly in PowerShell:
Test-NetConnection -ComputerName 'D123' -InformationLevel Detailed(shows 9 properties)Test-NetConnection -ComputerName 'D123' -InformationLevel Detailed | Get-Member(lists all 32 properties)
This confirms the object itself has 32 properties—your C# code was just sometimes seeing the full set, sometimes the formatted subset.
内容的提问来源于stack exchange,提问作者Erik

