locked
.Net Remoting over App Domains in the same process

    Question

  • Hi all,

    For automated testing of a remoting server over IPC, I wanted to create and configure a remote object in a separate app domain, and then get a remoting proxy and invoke it. I keep getting the same problem, so I have created some demo code to illustrate it:

    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Reflection; 
    using System.Runtime.Remoting.Channels; 
    using System.Collections; 
    using System.Runtime.Remoting.Channels.Ipc; 
    using System.Runtime.Remoting; 
    using System.Threading; 
    using System.Diagnostics; 
     
    namespace RemotingAppDomainDemo 
        public class Program 
        { 
            static void Main(string[] args) 
            { 
                AppDomain serverDomain = AppDomain.CreateDomain("Server Domain"); 
     
                try 
                { 
                    Server s = (Server)serverDomain.CreateInstanceAndUnwrap( 
                        Assembly.GetExecutingAssembly().FullName,  
                        typeof(Server).FullName); 
     
                    Thread serverThread = new Thread(new ThreadStart(s.Run)); 
                    serverThread.IsBackground = true
                    serverThread.Start(); 
     
                    Thread.Sleep(100); 
     
                    foreach (IChannel channel in ChannelServices.RegisteredChannels) 
                    { 
                        Console.WriteLine(channel.ChannelName); 
                    } 
     
                    foreach (WellKnownServiceTypeEntry entry in       
                        RemotingConfiguration.GetRegisteredWellKnownServiceTypes()) 
                    { 
                        Console.WriteLine(entry.ObjectUri); 
                    } 
     
                    Server server = (Server)Activator.GetObject( 
                        typeof(Server),  
                        "ipc://local/RemotingAppDomainDemo/Server"); 
     
                    Console.WriteLine(server.GetString()); 
     
                    Console.ReadKey(); 
                } 
                catch (Exception ex) 
                { 
                    Debug.WriteLine(ex); 
                } 
                finally 
                { 
                    AppDomain.Unload(serverDomain); 
                } 
            } 
     
            private class Server : MarshalByRefObject 
            { 
                public Server() 
                { } 
     
                public string GetString() 
                { 
                    return "Hello"
                } 
     
                public void Run() 
                { 
                    BinaryClientFormatterSinkProvider clientProvider = new  
                        BinaryClientFormatterSinkProvider(); 
                    BinaryServerFormatterSinkProvider serverProvider = new  
                        BinaryServerFormatterSinkProvider(); 
     
                    IDictionary props = new Hashtable(); 
                    props["portName"] = "local/RemotingAppDomainDemo"
                    IpcChannel chan = new IpcChannel(props, clientProvider, serverProvider); 
                    ChannelServices.RegisterChannel(chan, true); 
     
                    RemotingConfiguration.RegisterWellKnownServiceType( 
                        typeof(Server), "Server", WellKnownObjectMode.SingleCall); 
     
                    foreach (IChannel channel in ChannelServices.RegisteredChannels) 
                    { 
                        Console.WriteLine(channel.ChannelName); 
                    } 
     
                    foreach (WellKnownServiceTypeEntry entry in  
                        RemotingConfiguration.GetRegisteredWellKnownServiceTypes()) 
                    { 
                        Console.WriteLine(entry.ObjectUri); 
                    } 
     
                    while (true
                    {
                        Thread.sleep(10);
                    }; 
                } 
            } 
        } 
     


    Running this gives the exception:

    System.Runtime.Remoting.RemotingException: Failed to connect to an IPC Port: The system cannot find the file specified.
     

    Server stack trace:
       at System.Runtime.Remoting.Channels.Ipc.IpcPort.Connect(String portName, Boolean secure, TokenImpersonationLevel impersonationLevel, Int32 timeout)
       at System.Runtime.Remoting.Channels.Ipc.ConnectionCache.GetConnection(String portName, Boolean secure, TokenImpersonationLevel level, Int32 timeout)
       at System.Runtime.Remoting.Channels.Ipc.IpcClientTransportSink.ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, ITransportHeaders& responseHeaders, Stream& responseStream)
       at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg)

    Exception rethrown at [0]:
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at RemotingAppDomainDemo.Program.Server.GetString()
       at RemotingAppDomainDemo.Program.Main(String[] args) in D:\Workspace\trunk\RemotingAppDomainDemo\RemotingAppDomainDemo\Program.cs:line 41

    I get the same error even without kicking off a separate thread to run the configuration code (and without the infinite loop (crude I know, but it is only for demo) to keep the second thread alive. I don't think I really need this second thread; this is a sign I am starting to clutch at straws;-)

    Any clues as to what is the problem? I suspect it is probably more my poor understanding of app domains than a remoting problem. Originally I though it was a security problem for the second app domain, but then I would expect to get some type of security error returned.

    All help gratefully received,

    Mark
    Wednesday, February 18, 2009 2:24 PM

Answers

  • I was wrong; it was remoting, not the app domain that was causing the problem. It is caused by defining the IPC channel with "local/" in it. Don't know why this is a problem; will ask in a separate post.

    Working solution minus the thread - I knew I didn't need it ;-)

    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Reflection; 
    using System.Runtime.Remoting.Channels; 
    using System.Collections; 
    using System.Runtime.Remoting.Channels.Ipc; 
    using System.Runtime.Remoting; 
    using System.Threading; 
    using System.Diagnostics; 
     
    namespace RemotingAppDomainDemo 
        public class Program 
        { 
            static void Main(string[] args) 
            { 
                AppDomain serverDomain = AppDomain.CreateDomain("Server Domain"); 
     
                try 
                { 
                    Server s = (Server)serverDomain.CreateInstanceAndUnwrap( 
                        Assembly.GetExecutingAssembly().FullName, 
                        typeof(Server).FullName); 
     
                    s.Publish(); 
     
                    Server server = (Server)Activator.GetObject( 
                        typeof(Server), 
                        "ipc://local\\RemotingAppDomainDemo/Server"); 
     
                    Console.WriteLine(server.GetString()); 
     
                    Console.ReadKey(); 
                } 
                catch (Exception ex) 
                { 
                    Debug.WriteLine(ex); 
                } 
                finally 
                { 
                    AppDomain.Unload(serverDomain); 
                } 
            } 
     
            private class Server : MarshalByRefObject 
            { 
                public Server() 
                { } 
     
                public string GetString() 
                { 
                    return "Hello"
                } 
     
                public void Publish() 
                { 
                    BinaryClientFormatterSinkProvider clientProvider = new 
                        BinaryClientFormatterSinkProvider(); 
                    BinaryServerFormatterSinkProvider serverProvider = new 
                        BinaryServerFormatterSinkProvider(); 
     
                    IDictionary props = new Hashtable(); 
                    props["portName"] = "local\\RemotingAppDomainDemo"
                    IpcChannel chan = new IpcChannel(props, clientProvider, serverProvider); 
                    ChannelServices.RegisterChannel(chan, false); 
     
                    RemotingConfiguration.RegisterWellKnownServiceType( 
                        typeof(Server), "Server", WellKnownObjectMode.SingleCall); 
                } 
            } 
        } 

    • Marked as answer by MarkFalconer Wednesday, February 18, 2009 3:33 PM
    Wednesday, February 18, 2009 3:32 PM

All replies

  • I was wrong; it was remoting, not the app domain that was causing the problem. It is caused by defining the IPC channel with "local/" in it. Don't know why this is a problem; will ask in a separate post.

    Working solution minus the thread - I knew I didn't need it ;-)

    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Reflection; 
    using System.Runtime.Remoting.Channels; 
    using System.Collections; 
    using System.Runtime.Remoting.Channels.Ipc; 
    using System.Runtime.Remoting; 
    using System.Threading; 
    using System.Diagnostics; 
     
    namespace RemotingAppDomainDemo 
        public class Program 
        { 
            static void Main(string[] args) 
            { 
                AppDomain serverDomain = AppDomain.CreateDomain("Server Domain"); 
     
                try 
                { 
                    Server s = (Server)serverDomain.CreateInstanceAndUnwrap( 
                        Assembly.GetExecutingAssembly().FullName, 
                        typeof(Server).FullName); 
     
                    s.Publish(); 
     
                    Server server = (Server)Activator.GetObject( 
                        typeof(Server), 
                        "ipc://local\\RemotingAppDomainDemo/Server"); 
     
                    Console.WriteLine(server.GetString()); 
     
                    Console.ReadKey(); 
                } 
                catch (Exception ex) 
                { 
                    Debug.WriteLine(ex); 
                } 
                finally 
                { 
                    AppDomain.Unload(serverDomain); 
                } 
            } 
     
            private class Server : MarshalByRefObject 
            { 
                public Server() 
                { } 
     
                public string GetString() 
                { 
                    return "Hello"
                } 
     
                public void Publish() 
                { 
                    BinaryClientFormatterSinkProvider clientProvider = new 
                        BinaryClientFormatterSinkProvider(); 
                    BinaryServerFormatterSinkProvider serverProvider = new 
                        BinaryServerFormatterSinkProvider(); 
     
                    IDictionary props = new Hashtable(); 
                    props["portName"] = "local\\RemotingAppDomainDemo"
                    IpcChannel chan = new IpcChannel(props, clientProvider, serverProvider); 
                    ChannelServices.RegisterChannel(chan, false); 
     
                    RemotingConfiguration.RegisterWellKnownServiceType( 
                        typeof(Server), "Server", WellKnownObjectMode.SingleCall); 
                } 
            } 
        } 

    • Marked as answer by MarkFalconer Wednesday, February 18, 2009 3:33 PM
    Wednesday, February 18, 2009 3:32 PM
  • Posted related quetion at http://social.msdn.microsoft.com/Forums/en-US/netfxremoting/thread/dc46b90a-245f-44f9-a12b-b3fb158398a8/?ffpr=0.
    It seems that any forward slash '/' in a channel portName gives problems.
    Thursday, February 19, 2009 2:26 PM