I have a program that is able to expose itself as a self hosted WCF service. It does this when it's started as a process with certain parameters. In the past I've passed in a port for it to host on but I want to change that so it finds an available port and then returns that to the caller. (It also sets up a SessionBound End Point but that's incidental to this question). It self hosts to do this using the following code (this is working fine):-
Uri baseAddress = new Uri("net.tcp://localhost:0/AquatorXVService");
m_host = new ServiceHost(typeof(AquatorXV.Server.AquatorXVServiceInstance), baseAddress);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
m_host.Description.Behaviors.Add(smb);
m_host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
NetTcpBinding endPointBinding = new NetTcpBinding()
{
MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
SendTimeout = TimeSpan.MaxValue,
OpenTimeout = new TimeSpan(0, 0, 20)
};
ServiceEndpoint endPoint = m_host.AddServiceEndpoint(typeof(AquatorXVServiceInterface.IAquatorXVServiceInstance), endPointBinding, baseAddress);
endPoint.ListenUriMode = ListenUriMode.Unique;
ServiceDebugBehavior debug = m_host.Description.Behaviors.Find<ServiceDebugBehavior>();
if (debug == null)
m_host.Description.Behaviors.Add( new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });
else if (!debug.IncludeExceptionDetailInFaults)
debug.IncludeExceptionDetailInFaults = true;
m_host.Open();
int port = m_host.ChannelDispatchers.First().Listener.Uri.Port;
//Start the session bound factory service
Uri sessionBoundFactoryBaseAddress = new Uri("net.tcp://localhost:" + port.ToString() + "/AquatorXVSessionBoundFactoryService");
m_sessionBoundFactoryHost = new ServiceHost(typeof(AquatorXV.Server.SessionBoundFactory), sessionBoundFactoryBaseAddress);
ServiceMetadataBehavior smbFactory = new ServiceMetadataBehavior();
smbFactory.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
m_sessionBoundFactoryHost.Description.Behaviors.Add(smbFactory);
m_sessionBoundFactoryHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
m_sessionBoundFactoryHost.AddServiceEndpoint(typeof(AquatorXVServiceInterface.ISessionBoundFactory), new NetTcpBinding(), sessionBoundFactoryBaseAddress);
m_sessionBoundFactoryHost.Open();
return port;
Ultimately, port is set as the return value of Main().
On the client side it starts the program as a process. It then needs to access the port number so it can connect to it. Here's what I've been trying to do:-
ProcessStartInfo psi = new ProcessStartInfo(exePath, $"/remotingWCF") { UseShellExecute = false };
mProcess = Process.Start(psi);
mProcess.WaitForInputIdle();
mPort = mProcess.ExitCode;
CreateWCFClient(mPort);
The problem is that this fails when trying to access mProcess.ExitCode with a message: InvalidOperationException - Process Must Exit before requested information can be determined.
Googling around suggests that I use WaitForExit instead of WaitForInputIdle but that requires the program to actually be shut down before I can access ExitCode. I need to get the port from the running program.
I think this means that I won't be able to use ExitCode as a way to get the port back but I can't find a different mechanism. Can anyone suggest a way I can return a value from Process.Start without waiting for the program to close?