The recurring pattern seem to be that a client channel (used by the client to
connect with the remote object server) must be registered by the
ChannelServicesclass before
Activator
can succeed.
Recall that our server code can register more than one type of channel. If we
had registered both a TCP/IP channel as well as a HTTP channel, our client code
can be done this way :
HttpClientChannel http_channel =
new
HttpClientChannel();
ChannelServices.RegisterChannel(http_channel);
IProcessActivator.IProcessActivator process_activator =
(IProcessActivator.IProcessActivator)Activator.GetObject
typeof
(IProcessActivator.IProcessActivator),
"
http://localhost:8000/ProcessActivator"
process_activator.Run(
"
IExplore.exe"
, @http:
In the course of my learning experience with .NET Remoting, I noted two
important points about the
Activator.GetObject()
method. Both are significant
findings. The first is a little odd (could signal a bug in .NET) but is not
disastrous in my opinion. The second indicates similarities between .NET Remoting, COM and the Object-Oriented features of C++ in general which gives
me a surge of confidence that the COM and C++ stuff I learnt will be
re-usable in .NET.
The First Parameter To Activator.GetObject()
In this section, I'll discuss my first observation about the
GetObject()
method. The first parameter to
GetObject()
is documented in
MSDN as :
"The type of the well-known object to which you want to connect."
In my client code, I used :
typeof(IProcessActivator.IProcessActivator)
When I first experimented with the client code, I had hoped that I can
supply another interface type (provided of course that the Remoting Object
implements that interface). To cut a long story short, I found
that, in general, this parameter seem to make no difference
whatsoever no matter what I supplied (for the first parameter) as the type I
want from the Remoting Object. This seem to be the case as long
as the supplied type is found in the Remoting server.
What
does
make a difference is the URI of the Remoting
Object that I supply as part of the URL which is supplied as the second
parameter. Here, the URI
must
be the well-known
name of the actual object that you want the server to create and
return.
The fact that the first parameter seemed insignificant may be some kind of
design oversight by the Microsoft Engineers but I could well be wrong. If any
readers out there understand the significance of the first parameter in the
context I just mentioned, please share with us :-)
The Similarities Between Activator.GetObject(), COM's CoCreateInstance() and
C++'s "new" Keyword
In this section, I'll discuss the second observation I made concerning the
Activator.GetObject()
method. Note the entire call to
Activator.GetObject()
:
IProcessActivator.IProcessActivator process_activator =
(IProcessActivator.IProcessActivator)Activator.GetObject
(
typeof
(IProcessActivator.IProcessActivator),
"
"
);
This piece of code indicates to the .NET Framework to create an object of
"class"
"ProcessActivator"
and then return to me the
IProcessActivator
interface of that object.
This same style of object creation and interfacing return is evident in COM's
CoCreateInstance()
API. For example :
::CoCreateInstance(CLSID_MyClassID, NULL, CLSCTX_INPROC_SERVER ,
IID_IMyInterface, (LPVOID *)&pIMyInterface);
Here, we tell the COM sub-system to create a COM object with class ID
CLSID_MyClassID
and then to return to us a pointer to that COM object's
IMyInterface
implementation. Notice the same style of object creation and
interface pointer return.
Finally, to present the idea solidly into the reader's mind, note C++'s
style of object creation and interface pointer return in the following
example code :
IMyInterface* pIMyInterface =
new
CMainObject();
The above code assumes, of course, that the C++ class
CMainObject
is
derived from
IMyInterface
. Here, we instantiate a new instance of the
CMainObject
class and a pointer to the
CMainObject
's
IMyInterface
vtable
is returned to
pIMyInterface
.
Notice the same general approach used in object creation and interface
pointer return in C++. It is the same as that in .NET Remoting and
This same trend of object creation is also evident in Visual Basic.
In Conclusion
I certainly hope that my article will be of benefit to other readers. I have
attempted to present my own research work and share with all my findings.
I also hope that my example code will be of practical use to projects that
require some remote controlling of machines. Such remote controlling is not
uncommon and is particularly useful in automated systems.
Drop a message to me anytime you have a good suggestion on the example code or
on Remoting in general.
Lim Bio Liong is a Specialist at a leading Software House in Singapore.
Bio has been in software development for over 10 years. He specialises in C/C++ programming and Windows software development.
Bio has also done device-driver development and enjoys low-level programming. Bio has recently picked up C# programming and has been researching in this area.
Thanks for a great article, I'm trying to get remoting straight in my head and this helped a lot.
Question though, I have tried adding a new form to the server project, I want to invoke that form from the client, so far all I get is a form that egg times and does'nt respond??
How do I do it?
Cheers
Sign in
·
View Thread
Hello,
Great article. Quick question: Since the form inherits from MarshalByRefObject, I would think it'd be easy to host a form on a server and instantiate and use it from a client application, but this doesn't seem to be the case. As soon as the form appears, it enters a "Not Responding" state, and does not update or respond to the user. I'm trying to create a multi-form application where the main window acts as a client from which you can instantiate other forms that are being hosted on the server. I hope I am explaining it well.
Anyway, the actual question:
Do you know if it's possible to do what I have explained above, and if it is, can you point me in the right direction?
Thank you for your time (and the article),
Tommy V
Sign in
·
View Thread
It sounds like the web page style serving of windows forms, I think you would like to create an application which doesn't require updates (or patches, I don't know what your aim is). If so, you really should consider to apply a web application project to achieve such an approach. Otherwise, if I could correctly understand the problem you stated, It'll be a waste of time to try to create such a design while there is one already.
E. Guldogan
Sign in
·
View Thread
When I use the server and client on the same machine, it works fine. But using the client from another machine, specify the serverIP, and receive an socket exception "No connection could be made because the target machine actively refused it". I tried to start alot of service related to the RPC and Remote access on the server machine but hopeless. Any thoughts?
Thanks alot,
LamNgo
Sign in
·
View Thread
Hello Lam Ngo,
The error message is very familiar and I have experienced it before during development of some remoting project. I'm trying to recall the reason and outcome of the error message but I know that it has nothing to do with RPC or remote access.
I do recall discovering either a bug in program code or that the server program was not started up when the client wants to connect with it.
I'll email you again once I can remember the solution to this issue.
Thanks, Lam Ngo,
Sign in
·
View Thread
Did you find a solution to the problem "No connection could be made because the target machine actively refused it", i am having the same problem. The code runs well on the same machine but does not work over my internal network. Will greatly appreciate any inputs you or anyone might have.
Thanks
Sign in
·
View Thread
Found the solution, i was making a call to the local machine instead of the remote machine(IP address)
"typeof(IProcessActivator.IProcessActivator),"tcp://localhost:5999/ProcessActivator"
Solution:...
Pass the IP address of the remote machine to the client application
"typeof(IProcessActivator.IProcessActivator),"tcp://192.168.0.104:5999/ProcessActivator"
Sign in
·
View Thread
Another possible trouble may be a firewall prevention between your client and server machines. Try to use telnet to check. On the client machine on the command prompt type "telnet <ServerIP> <ServerPort>". If you see a whole black command prompt screen that waits, that means there is no problem about any firewall. Or If "...Could not open connection to the host..." is stated by telnet, you should check the firewall(s) on the line between (and on) your client and host machines.
E. Guldogan
Sign in
·
View Thread
Thx for your article.
But I need to create 2 window services that have to communicate with each other.
I thought about using .NET Remoting but this is not possible in my mind
:
public class ServiceManager : System.ServiceProcess.ServiceBase, MarshalByRefObject
Because
MarshalByRefObject
is not an Interface.
Please help me if you have a better solution.
Sign in
·
View Thread
Hello MisterG,
First note that a Windows Service is an application, not an object. It would not make sense to derive "ServiceManager" from MarshalByRefObject.
However, you certainly can create 2 services that communicate with each other via .NET Remoting. Classes deriving from MarshalByRefObject can certainly be defined inside your Windows Service source codes and then exposed as usual via ChannelServices and RemotingConfiguration.
Regards,
Sign in
·
View Thread
Put the server code in the class constructor of the windows service. I needed to place the client code into a service controller. The client code can remain the same, but I also placed the code in a client contructor. I initially got an error about "actively not blah blah" (
sorry I cant remember ). But I think that had to do with the windows firewall running on my computer. Now I am trying to figure out how to pass an object with state information about the service.
Sign in
·
View Thread
Make your windows service both server and client. The client to communicate with the other's server.
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
Sign in
·
View Thread
Hello Hardy, MisterG,
Yes, Hardy said it right there. Basically, MisterG, you would want to use your Service Applications as platforms for hosting your special .NET Remoting Objects.
The twist here is that these Remoting Objects are not generally exposed to other applications for usage. They serve as a communications mechanism between the 2 services.
Thanks, Hardy.
Regards,
Sign in
·
View Thread
First of all, thanx for a great article on Remoting.
Second...there is one aspect of the client part that got me thinking, it even made me test if my theory was true. In the Main method for the client this code is executed:
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel);
IProcessActivator.IProcessActivator process_activator =
(IProcessActivator.IProcessActivator)Activator.GetObject
typeof(IProcessActivator.IProcessActivator),
"tcp://localhost:9000/ProcessActivator"
process_activator.Run("IExplore.exe",
@"http://www.codeproject.com");
But what got me thinking is the first two lines, where you register a new TcpClientChannel. But it really doesn't supply any new information to the framework other than that you are going to use a TcpClientChannel at some point. But that information is also supplied to the framework when you call the Activator.GetObject() method. The parameters of that method both tells it what type of channel you are going to use, and what the name of the well known object is.
I tried to do the same thing in a project of my own and skipped the registration of the TcpClientChannel and it still worked. So what do i really use the TcpClientChannel for?
/Rouzbeh
Sign in
·
View Thread
Hello Rouzbeh,
Thanks very much for sharing the very interesting observation. I also tried running the client code without the TcpClientChannel registration and it indeed worked as you reported.
I really do not know whether this confirms that the TcpClientChannel registration can be ommitted in client code which connects to well-known objects via Activator.GetObject() since this convention seem to be in use in many example codes (including those found in MSDN). Personally, I have my doubts that this is so.
Let me do some research and I'll see if there can be some explanation. Let me know if you do come up with something too, Rouzbeh.
And thanks again, for the good catch !
Best Regards,
Sign in
·
View Thread
Actually when the TcpClientChannel is registerd, it specifies on which port the client will be listening to receive the Return data if any.
As you know, port 0 means .net remoting selects a port for you.
So it is obvious that when client connects to well known objects on the server without Client port registration it works. I think, the problem would occur when you are try to return some data from the remote function back to client.
Regards,
Atul.
Sign in
·
View Thread
I m not registering TcpClientChannel and just using activator.Getobject(). But my application is working fine without any prob.and its a big application doing all kind of operations.
So i still dont understand it really needs to register or not.
thanks,
Sign in
·
View Thread
The IProcessActivator.IProcessActivator is confusing
. I think that normally you have [namespace].[class]
Can you please clarify what the first part is and what the second part is and why you called them both the same thing?
Sign in
·
View Thread
Hello,
IProcessActivator.IProcessActivator -is- in the [namespace].[class] format. The namespace is IProcessActivator and the interface name is also IProcessActivator.
Look at the IProcessActivator.cs file and you will see the following :
using System;
namespace IProcessActivator
/// <summary>
/// Summary description for interface IProcessActivator.
/// </summary>
public interface IProcessActivator
bool Run(string strProgramName, string strArgumentString);
Notice that the namespace name and the interface name are the same.
I must agree that this can potentially cause confusion even to the C# compiler. Notice in the server source codes :
using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using IProcessActivator;
namespace ProcessActivator
/// <summary>
/// Summary description for ProcessActivator.
/// </summary>
public class ProcessActivator : MarshalByRefObject,
IProcessActivator.IProcessActivator
Notice that I also had to use "IProcessActivator.IProcessActivator" as part of the derivation for the class ProcessActivator despite the fact that I have already specified the I'm using the IProcessActivator namespace :
using IProcessActivator;
The same compilation problem is faced in the client code.
If I had coded the namespace for the IProcessActivator interface as IProcessActivatorNamespace, for example :
using System;
namespace IProcessActivatorInterface
/// <summary>
/// Summary description for interface IProcessActivator.
/// </summary>
public interface IProcessActivator
bool Run(string strProgramName, string strArgumentString);
... this problem would not have occurred. I would've been able to code the client and server codes using the "IProcessActivatorInterface" namespace and I would have no need to specify the fully qualified interface name "IProcessActivatorInterface.IProcessActivator".
Thanks for reporting this problem.
Best Regards,
It is basic programming procedure to start interfaces with I. The confusion is because you are starting the namespace with I as well. You should just drop the I off the namespace and only use it on the interface.
Also, you shouldn't even need to specify
using
since it should all be in the same namespace. The only
using
should be for the remotable object.
Other than that, it seems like a decent article, except you shouldn't be reference Nish on here, except that it seems like you need his approval. Be your own person and don't use Nish as a way to grab hits.
Sign in
·
View Thread
It is basic programming procedure to start interfaces with I. The confusion is because you are starting the namespace with I as well. You should just drop the I off the namespace and only use it on the interface.
Also, you shouldn't even need to specify
using
since it should all be in the same namespace. The only
using
should be for the remotable object.
Other than that, it seems like a decent article, except you shouldn't be referencing Nish on here, except that it seems like you need his approval. Be your own person and don't use Nish as a way to grab hits.
Sign in
·
View Thread
Thanks very much for the tips. Really appreciate them
I've also just posted an update to the code project webmaster with what I hope to be an improvement to this article. Hope it comes up soon.
Best Regards,
Sign in
·
View Thread
Funnily enough I needed to write something almost exactly the same as this a month ago and my code pattern has turned out to mimic yours very closely. ( I am a .NET and C# learner so I like simple examples
)
It would be interesting for me to see some security layered upon this to protect remote access to the interface on the server side, perhaps by password, but then again I am a complete neophyte in that area too
.
Cheers
Sign in
·
View Thread
Hello Ohmigosh,
Very glad to know that my code is very similar to yours. It certainly shows that I'm on the right track
The idea about security is good. I'll see if I can come up with something along this line.
Thanks,
-Bio.
Sign in
·
View Thread
Web01
2.8:2024-01-30:1