I am trying to integrate some new code I wrote for programmatically interacting with Exchange 2010 via Remote Powershell into an existing WinForms application. My code works in an isolated test application, but when I run the code in the context of my app the call to Runspace.Open()
blocks for a very long time -- well past the OpenTimeout
value of 60 seconds which I am specifying in the WSManConnectionInfo
instance. To me, this suggests that there is something in our application code which is creating the issue but I'm having trouble narrowing down what those potential causes could be. The application is multithreaded and uses both BackgroundThreadWorker
and the ThreadPool
; in fact, my code runs via the ThreadPool
in the application. But I've already tried simulating this in my test harness and the code works fine when called as a callback from the ThreadPool
too.
Here's the code (with error handling removed and constant definitions put nearby):
const string EXCHANGE_PS_URI_FORMAT = "http://{0}/PowerShell/";
string uriString = string.Format(EXCHANGE_PS_URI_FORMAT, HostName);
Uri connectionUri = new Uri(uriString);
PSCredential creds = new PSCredential(username, securePwd);
const string EXCHANGE_PS_SCHEMA_URL =
"http://schemas.microsoft.com/powershell/Microsoft.Exchange";
WSManConnectionInfo connectionInfo =
new WSManConnectionInfo(connectionUri, EXCHANGE_PS_SCHEMA_URL, creds);
const int DEFAULT_OPEN_TIMEOUT = 1 * 60 * 1000; // 1 minute
connectionInfo.OpenTimeout = DEFAULT_OPEN_TIMEOUT;
const int DEFAULT_OPERATION_TIMEOUT = 4 * 60 * 1000; // 4 minutes
connectionInfo.OperationTimeout = DEFAULT_OPERATION_TIMEOUT;
using (Runspace rs = RunspaceFactory.CreateRunspace(connectionInfo))
{
// BUGBUG: WHY IS THIS FAILING TO RETURN?
rs.Open(); // <-- HANGS HERE
ICollection<PSObject> newReqResults = null;
PipelineReader<object> newReqErrors = null;
try
{
using (Pipeline pipeline = rs.CreatePipeline())
{
// cmd instance is already instantiated with cmdlet info, params, etc.
pipeline.Commands.Add(cmd);
//Invoke the command and return the results and errors
newReqResults = pipeline.Invoke();
newReqErrors = pipeline.Error;
}
}
// Code to parse results and/or errors...
The call stack when the code hangs on the Runspace.Open()
seems to show that the internal .NET code is stuck on a wait call, but I'm at a loss on how to proceed. As I said earlier, this code works fine in my test app even if called as a ThreadPool callback, so I'm wondering what could be in our main app code that could be causing this (synchronization context or the thread identity or something else?) Any help would be greatly appreciated. Please let me know if I've neglected to include some relevant info and I'm happy to include it. Thanks!
[In a sleep, wait, or join]
mscorlib.dll!System.Threading.WaitHandle.WaitOne(long timeout, bool exitContext) + 0x2f bytes
mscorlib.dll!System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, bool exitContext) + 0x25 bytes
mscorlib.dll!System.Threading.WaitHandle.WaitOne() + 0xd bytes
System.Management.Automation.dll!System.Management.Automation.Runspaces.AsyncResult.EndInvoke() + 0x14 bytes
System.Management.Automation.dll!System.Management.Automation.Runspaces.Internal.RunspacePoolInternal.EndOpen(System.IAsyncResult asyncResult) + 0xb2 bytes
System.Management.Automation.dll!System.Management.Automation.Runspaces.Internal.RemoteRunspacePoolInternal.Open() + 0x1a bytes
System.Management.Automation.dll!System.Management.Automation.Runspaces.RunspacePool.Open() + 0x48 bytes
System.Management.Automation.dll!System.Management.Automation.RemoteRunspace.Open() + 0x73 bytes