0

Context:

I'm working with some old robotics software which is able to get information from a COM object if it implements some predefined interfaces. Since this old software runs on Windows 2000, I want to use DCOM to (try to) avoid having to compile something for Windows 2000. (I am aware that the program that has to be called probably needs to work, or at least exist, on the Windows 2000 computer as well)

The other computer will be called through DCOM and will process an image using a configured set of steps. I would like a GUI to show the incoming and outgoing images and the ability to change the steps it undertakes.


Problem

The image processor needs to implement two interfaces, but Interface1 contains a Load function, as does the Form, but both need to remain accessible so I don't think I can use the new keyword. Therefore the code below will not work.

public class ServerForm : Form, Interface1, Interface2 { }

I can split them like this:

public class ServerForm : Form { }

public class MyImageProcessor : Interface1, Interface2 { }

But I'll still need to access the Form from the MyImageProcessor class. I tried passing the Form to the MyImageProcessor through the constructor like this:

static class Program {
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            ServerForm sv = new ServerForm();
            MyImageProcessor mip = new MyImageProcessor(sv);
            Application.Run(sv);
        }
    } 

But when I use regasm CSharpServer.exe /regfile:CSharpServer.reg, to check which keys are added to the registry, only the ServerForm shows up and not the ImageProcessor.

How can I solve this problem?

Daniël J
  • 107
  • 10
  • You can implement an interface privately: https://blogs.msdn.microsoft.com/johnwpowell/2008/06/13/how-to-implement-an-interface-without-making-members-public-using-explicit-interface-implementation/ – Simon Mourier Feb 28 '18 at 09:10
  • 1
    You expect the robotics software to create an instance of your class by passing a Form object. That is not going to work, it doesn't know beans about forms. The hard rule is that an object can only be [ComVisible(true)] when it has a public constructor that takes no arguments. There is a lot more to this question, creating an out-of-process server in C# is quite complicated and brittle and not directly supported. Google that first before you burn a lot of possibly wasted time on this. – Hans Passant Feb 28 '18 at 09:28
  • @SimonMourier I'm afraid that won't work, because I can't change the code of the classes that make use of these functions, but thank's for learning me something new! – Daniël J Mar 01 '18 at 09:48
  • @HansPassant You are absolutely right. Your comment indeed made me realise there's much more that I don't know yet. I have come up with a temporary solution to this problem, but I'm sure more will follow and I will contact the robotics manufacturer to see if they can help. – Daniël J Mar 01 '18 at 09:51

1 Answers1

0

This solution fixes both of the problems stated above: Both load functions will remain available and the correct registry keys are generated, but I don't if it will give any problems with COM later, yet. (It probably will)

I have split it in two classes. The ServerForm is generated and run from the constructor of MyImageProcessor.

public class MyImageProcessor : Interface1, Interface2{
    private static ServerForm sv;      

    public MyImageProcessor () {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        sv = new ServerForm();
        Application.Run(sv);
    }
}

and

public class ServerForm : Form {
        public ServerForm() {
            InitializeComponent();
        }
}

I would like to stress that this fixes the problems for now, if I get everything working I'll try to update this post.

Daniël J
  • 107
  • 10