Geeks With Blogs
David Douglass .NET on My Mind

Most developers instruct Visual Studio to make local copies of DLLs.  Whenever Visual Studio can detect a dependency between an executable and a DLL, it will copy the DLL into the directory where the executable is written.  But Visual Studio can’t always see the dependencies.  The typical solution for this situation is to do the copy by some other means.

If the copy gets forgotten, you’ll usually find out at runtime when the CLR throws an exception because it can’t locate the DLL.  Sometimes though, with remoting, the CLR won’t raise an exception due to the missing DLL, it will simply fail silently.  This occurs when using the OneWayAttribute.  OneWay is fire and forget; give it your best shot.  When the server receives a request it can’t fulfill, it just skips it.  The code below demonstrates this.  There are 3 projects in the solution: Shared, Client, and Server.  The namspaces identify which project a component is in.

// interface that the client will get a reference to
using System;
using System.Runtime.Remoting.Messaging;

namespace Shared {
 public interface IRemote {
  [OneWay]
  void ConsoleWrite(string message);
 }
}

// object that will be instantiated by the server
using System;

namespace Shared {
 [Serializable]
 public class Remotable : MarshalByRefObject, IRemote {
  public void ConsoleWrite(string message) {
   Console.WriteLine(message);
  }
 }
}

// the program that asks the server to instantiate the
// remotable object and run a function on it
using System;
using Shared;
using System.Runtime.Remoting;

namespace Client {
 class Caller {
  [STAThread]
  static void Main(string[] args) {
   IRemote remoteObject;
   try {
    remoteObject = (IRemote) Activator.GetObject(typeof(IRemote), "tcp://localhost:50000/Remotable.rem");
   } catch (Exception ex) {
    Console.WriteLine("can't create remotable object: " + ex.Message);
    Console.ReadLine();
    return;
   }
   if (remoteObject == null) {
    Console.WriteLine("remotable object is null");
    Console.ReadLine();
    return;
   }
   try {
    remoteObject.ConsoleWrite("called from Client.Caller");
   } catch (Exception ex) {
    Console.WriteLine("can't call remotable object: " + ex.Message);
    Console.ReadLine();
    return;
   }
   Console.WriteLine("remotable object called; press return to terminate");
   Console.ReadLine();
  }
 }
}

<?xml version="1.0" encoding="utf-8" ?>
<!-- configuration that tells the server where to listen
  and how to find the remotable object -->
<configuration>
 <system.runtime.remoting>
  <application>
   <channels>
    <channel ref="tcp" port="50000" />
   </channels>
   <service>
    <wellknown mode="SingleCall" type="Shared.Remotable, Shared" objectUri="Remotable.rem" />
   </service>
  </application>
 </system.runtime.remoting>
</configuration>

// the server that hosts the remotable object
using System;
using System.Runtime.Remoting;

namespace Server {
 class Remotable {
  [STAThread]
  static void Main(string[] args) {
   RemotingConfiguration.Configure("Server.exe.config");
   Console.WriteLine("waiting for invocations; press return to terminate");
   Console.ReadLine();
  }
 }
}

What to do?

• Don’t use OneWay.  This will make the remote call synchronous and the client will receive an exception when it makes the call to the remote function.
• Add a reference to the Shared project to the Server project, with Copy Local set to true.  Doing so will cause Visual Studio to copy Shared.dll to the Server executable directory, even through Visual Studio doesn’t see any dependency.

Posted on Thursday, April 6, 2006 8:24 AM | Back to top


Comments on this post: Silence of the Remoting Server

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © David Douglass | Powered by: GeeksWithBlogs.net