views:

24

answers:

1

I have a DLL written in Visual C++ and an application written in C#. The application that is written in C# already uses IPC between multiple instances of itself so that it only ever runs one instance (it attempts to start an IPC server, and if it can't assumes there's already one running, in which case it sends the command line arguments over IPC to the existing application).

Now I want to send commands from a Visual C++, however, even when I create a type definition in Visual C++ that matches the one in C# (on an implementation level), it rejects the connection because they are fundamentally still two different types (from two different assemblies).

I thought about using Reflection in Visual C++ to fetch the type from the C# assembly, but I can't do that because then I'd have to ship the assembly along side the DLL (which defeats the purpose of the DLL being an API to the application).

I'm not sure of any other way I could really do it, other than store the class in yet another DLL and make both the application and the API DLL reference the class in that, but this is also not an ideal solution as I'd like a single API DLL to distribute.

Are there any suggestions as to how I can connect over IPC (other forms of communication like TCP are not permitted) to send requests to the application?

A: 

The solution was to place the InterProcess class in the API DLL and simply make the C# application use the DLL as a reference to bring in the class.

It is also important to note that in order to initialize the shared object correctly, I had to initialize the server side of the sharing in a separate AppDomain and make the C# application a client like so (this is a new version of the previous paste):

try
{
    // Set up an interprocess object which will handle instructions
    // from the client and pass them onto the main Manager object.
    this.m_ServerDomain = AppDomain.CreateDomain("roketpack_server");
    this.m_ServerDomain.DoCallBack(() =>
        {
            // We must give clients the permission to serialize delegates.
            BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
            serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            IpcServerChannel ipc = new IpcServerChannel("roketpack", "roketpack", serverProv);
            ChannelServices.RegisterChannel(ipc, true);

            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(API.InterProcess),
                "InterProcessManager",
                WellKnownObjectMode.Singleton);
        });

    // Now initialize the object.
    IpcClientChannel client = new IpcClientChannel();
    ChannelServices.RegisterChannel(client, true);
    this.m_InterProcess = (API.InterProcess)Activator.GetObject(
        typeof(API.InterProcess),
        "ipc://" + name + "/InterProcessManager");
    InterProcessHandle.Manager = this;
    this.m_InterProcess.SetCalls(InterProcessHandle.CallURL,
                    InterProcessHandle.IsLatestVersion,
                    InterProcessHandle.RequestUpdate);

    return true;
}
catch (RemotingException)
{
    // The server appears to be already running.  Connect to
    // the channel as a client and send instructions back
    // to the server.
    IpcClientChannel client = new IpcClientChannel();
    ChannelServices.RegisterChannel(client, true);

    API.InterProcess i = (API.InterProcess)Activator.GetObject(
        typeof(API.InterProcess),
        "ipc://" + name + "/InterProcessManager");

    if (i == null)
    {
        Errors.Raise(Errors.ErrorType.ERROR_CAN_NOT_START_OR_CONNECT_TO_IPC);
        return false;
    }

    if (Environment.GetCommandLineArgs().Length > 1)
        i.CallURL(Environment.GetCommandLineArgs()[1]);

    return false;
}

I hope this solution helps someone else :)

Hach-Que