Solved

.NET Remoting with  Windows Forms

Posted on 2004-10-14
30
553 Views
Last Modified: 2008-03-17
I have looked through various tutorials and figured out how to get one of them working.. made a little sample with the following setup:

1) Server (console app, with console.readline()  to keep the listener open)
2) Client (console app that calls the remote code)
3) Class library which is the remote vb.net  code.  


What I don't understand is how am I going to use Remoting to send a signal from my Windows Service to the system tray icon..(Windows form) ?    When the Service becomes active I want it to send a message to the desktop (System Tray) so that the System Tray can change its icon into an 'active' mode, or I will have alittle msn like window pop up.  

What I know:    put the server code in the system tray project,  client code in the Service.

What I need to know:   When the Client calls the Remote Code, how can I get this code (which is just a class library)  to pop up a window or do something as mentioned above?   I couldn't get the remote code to work any other way than just a class library, is there a way to have my entire form the remote code?  (I tried that but then couldn't reference it in the server because i can only reference .dll , and the .exe wasn't a proper format I guess).

Any help would be appreciated.  Thanks.



This is the code:


Class library ###########################################
Public Class SampleRemoter : Inherits MarshalByRefObject

    Public Function getUser() As String
        Return Environment.MachineName
    End Function

End Class
###################################################

Server###############################################

Class RemotingServer

    Shared Sub Main(ByVal args() As String)

        Console.WriteLine("Registering our remote object...")
        RemotingConfiguration.RegisterWellKnownServiceType(GetType(SampleRemoter), "SampleRemoter", WellKnownObjectMode.SingleCall)
        Console.WriteLine("Create and register a channel...")
        Dim ch As New TcpServerChannel(8080)
        ChannelServices.RegisterChannel(ch)
        Console.Read()

    End Sub

End Class

###################################################

Client ###############################################

    Shared Sub Main(ByVal args() As String)
        Try
            Console.WriteLine("Registering Channel...")
            Dim ch As New TcpClientChannel
            ChannelServices.RegisterChannel(ch)
            Console.WriteLine("Registering remote object in local domain...")
            RemotingConfiguration.RegisterWellKnownClientType(GetType(SampleRemoter), "tcp://localhost:8080/SampleRemoter")
            Console.WriteLine(" Create remote object and execute method")
            Dim sr As New SampleRemoter
            Dim username As String = sr.getUser()
            Console.WriteLine("Machine name of remote machine = " & username)
        Catch ex As Exception
            Console.WriteLine(ex.ToString())
        Finally
            Console.Read()
        End Try


###################################################

0
Comment
Question by:bswiftly
  • 15
  • 11
  • 3
  • +1
30 Comments
 
LVL 4

Expert Comment

by:Jigit
Comment Utility
bswiftly, you can use System.Windows.Forms.Timer object from your System Tray app and perform some checks in your internal file, or registry setting which are set by the Windows Service.

HTH,
Jigit
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
there must be a better way.. I'm looking to be able to send events directly to it without having to poll a local file or registry.  
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Are these going to be on the same machine or separate machines?

Bob
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
they are both on the same machine.  I have had some help outside this site and what I have been able to do is create a wrapper for my form class.  The wrapper inherits the MarshalByRefObject class and then calls the pop up to display.  The Remoting Server is the forms project with the NotifyIcon object.  

So in other words I have resolved this issue, but will still give points for someone who can give me a way to change the notifyIcon.   Is there a way to return a variable from the remote code to the remoting server and have the remoting server do something accordingly? (i see how this may not be possible due to potential security risks..)

0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Why are you using Remoting if the 2 applications are on the same machine?  That sounds like a lot of overhead to me.

Bob
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
I have a Windows Service.  It can't have visual elements.  So I created a System tray app.. (NotifyIcon class)  that will be the controller for the Service.  This all works without remoting.

However,  when I want to have the service notify the desktop of its state, there is no way to do this other than remoting, or my own TCP/IP connectivity, or something that would incur more overhead is to have the system tray query a file every 5 seconds, as Jigit suggested.  

Do you have a  more efficient implementation of this that I could use?
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Does your System Tray application have a form?

Bob
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
http://www.thinktecture.com/Resources/RemotingFAQ/RemotingUseCases.html

this is a good article to read on .NET Remoting.  The author, Ingo Rammer, has a few books published on .NET Remoting, and suggests that this is a good use of Remoting.
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
Yes, my systray app does have a form.  It is currently invisible (I just created a windows forms app, not a console app, because originally to test the pop up window I used the form).   How do you suggest the windows service sends events to the systray app to have the form slide up?

0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
I am thinking of a way to send a message, not through MSMQ, but through the normal Windows message (WndProc), as long as you can get a handle to the Window.

Bob
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
But then how do I ensure where the message is coming from?  

I think that way would have just as much overhead as using Remoting?  After all, all remoting does is TCP commands.  The server just holds a reference to the memory allocation for the remote code..  In my trials the code is very quick and works well.

Ingo Rammer got back to me and said I should be able to use most Windows.Forms classes directly as Remote Hosts because most of them derive from MarshalByRefObject, however I haven't been able to import forms projects into my client, so this is not a possibility yet.

0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
All very good points, so let's get back to the matter at hand.  

Would something like this work:

http://www.dotnet247.com/247reference/msgs/12/60499.aspx

Why would you use the "Invoke" method instead of the Remote
Asynchronous Programming Paradigm? What is the difference between the
two? Does the RemoteAsyncDelegate give you anything?

Their example in the MSDN is something like..

Dim RemoteCallback As New AsyncCallback(AddressOf Me.OurCallBack)
Dim RemoteDel As New RemoteAsyncDelegate(AddressOf obj.RemoteMethod)
Dim RemAr As IAsyncResult = RemoteDel.BeginInvoke(RemoteCallback,
Nothing)
RemAr.AsyncWaitHandle.WaitOne()

Bob
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
I'm not really sure.. I'm new to Remoting.. even found out about it while researching what I wanted to do here.

I found this quote at teh botton of the page where you got that code snippet off msdn:
"Note that if the client is a context-bound class that requires a synchronized context, the callback function is dispatched through the .NET remoting context infrastructure. "

So that offers some insight, although I'm not sure how much sense I can make of it... not sure what a context bound class is or if what I have IS one?


I'm not sure how to implement this remotecallback .. how would that interact ?  Have you actually used this before?
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Do you have Ingo Rammer's .NET Remoting book?

Bob
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 1

Author Comment

by:bswiftly
Comment Utility
No I don't, there is a new version that we might pick up, but isn't available yet.
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
I have it on the shelf, so I thought a good reference in the book might help.  I don't do remoting very much, so the specifics escape me.

Bob
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
Maybe I will email Ingo the link to this article and see if he has time to reply :)
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Now that would be the best solution.  Get it right from the real Remoting expert :)

Bob
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
If you find some specifics on this, I would be very interested.

Bob
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
I have emailed him and he will either reply here or I will post his email reply for him.   I think its bedtime in Austria so we may have to wait till tomorrow.
0
 
LVL 1

Accepted Solution

by:
rammeri earned 125 total points
Comment Utility
Bedtime? It's around 7pm here ... we're just starting, right? ;-)

Bob: Thanks! Great to hear that you like the book!

Re your Qs: Remoting of events is always a little bit cumbersome. In this case, however it might make perfect sense as you are running client and server on the same machine. (Just make sure that rejectRemoteRequest is set to "true" in the server side config ... else everybody on your network can connect to your service!) Of course you could also implement your service as a COM+ EnterpriseService with RunAsService=true ... but that's a completely different story ;-). If you are not familiar with E/S or COM+, this will be harder.

You should be able to either use an AsyncCallback (but you'd have to define it as a public Event in the server side class) *or* you can use any other delegate/event.

BUT: There's a drawback. You have to pass the events through a shim layer, as otherwise, the server would need to have the client-side EXE available in its directory. (You can see an example of this at http://www.ingorammer.com/Book/EventsEnhanced.zip). In addition, starting with version 1.1 of the .NET Framework, you will have to specify typeFilterLevel="full" as illustrated at http://www.thinktecture.com/Resources/RemotingFAQ/Changes2003.html.

I hope this is enough to get you started.

BTW: The second edition is not yet available. I've today sent in the drafts of the final chapters. We only have to finish work ont he new "reference" section/appendixes. I guess we'll work on this section for about a week or two. After this, there are several review cycles so that it might still take two or three months before the book hits the stores. (Printing and distribution alone takes about 2-4 weeks ... paper is slow ;-))

-Ingo
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
well i've been hacking away at this all day.. can't seem to get it working.  Ingo, I haven't actually looked at your code above, I'm still trying to just get the popup window working from my windows service.  I had it working from a test application, but when i  put the client in the windows service I can't see the remote code being run.. I have a method that writes to the eventlog and I am using that to place checkpoints as I run it.. (debugging is a pain!)

I'm wondering if there is an easy way of debugging the remote code file?

Or is this realising its being called from a windows service and therefore not allowing a visual element to be displayed?
0
 
LVL 1

Expert Comment

by:rammeri
Comment Utility
For debugging, you have to first simply start your Windows Service using Service Control Manager. In VS.NET you can then select Debug->Attach and select the EXE of your windows service. This attaches the VS.NET debugger to the running instance of your Windows Service. Afterwards, you can use breakpoints, etc. just as if it were a "regular" application.

(BTW: I'll be travelling for the next few days an won't be able to respond to this thread. If you didn't find a solution by Saturday, just email me your code and I'll have a look at it)

In general: I would design the Windows Service as your Remoting server and the systray app as a client.

Cheers,
-Ingo
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
I know how to debug windows services.. its the remote code library that I am having probs with.

Why would you have the remoting server on the windows service?  That kind of defeats the purpose of what I'm trying to do doesn't it?  The whole issue with this is to create a form pop up when something happens with the windows service.. I can't have visual elements in the windows service so i thought of using remoting to notify the systray application and have it (or now the remote code) display the popup.

0
 
LVL 1

Expert Comment

by:rammeri
Comment Utility
Sorry - I routinely meet developers who don't know how to debug a Svc ... ;-)

Re client/server: Simply because more than one listener could be active. For example with Windows XP "Fast User Switching" or Terminal Services. In this case, it's better if you allow multiple clients to receive notifications from one server. (i.e. subscribe the client to an event of the Windows Service)

-Ingo
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
Hey, thanks for your help.. haven't tried implementing your "shim layer" to get notifications directly to  the systray Icon, but I do now have a little popup working.  Systray as the remoting host and Win. Service as the client... it works great!  I might be able to find some time to try that shim layer thing soon, so I'll keep this question open for now in case I have other questions.  

ps. If you have an email list for notifications of when your new book is printed and shipped, feel free to put me on it :)
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Me too :)

Bob
0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
Well I have a working sample, converted it to VB (unfortunately we use VB), and implemented it in windows forms.  Didn't use the Client listener app or code to implement that in the server because I will not need this for the systray Icon.

One interesting thing, is that the config file is case sensitive even in VB!  A second is that VB automatically gives you a namespace in the properties window that doesn't appear in the code.. so when you specify Namespace Server.. in your code.. it is redundant..  (dumb VB!)

One problem that I did have however, which will be the last problem hopefully.. in order to get this Systray working with the features I want, is that I want to be able to manipulate the context menu and displayed image of the icon, when specific events are received from the Windows service.  Because I can't inherit more than one interface, my remote code has to be in a separate class from the Form code (Systray icon).  I have tested to see if I could make a shared (static) label, and set that label from the other class but this didn't work.  

How would I do this... anyone?

0
 
LVL 1

Author Comment

by:bswiftly
Comment Utility
nevermind.. i'm guessing that is what the EventListener part of the code is for..   will have to implement that now to test it!
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Normally the drop down box control found in the .Net framework tools is able to select just one data and value at a time, which is displayed on the text area.   But what if you want to have multiple values to be selected in the drop down box? As …
This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now