2

I couldn't find any close answers to this, so I'm consulting the experience of SO users:

Scenario:

I have two small C# winforms applications where one behaves as a server or host, the other as a client. They share data via SQL Server, in terms of configuration settings.

I am currently launching the client application (which only needs to run periodically) from the server application via Process.Start() and terminating it via Process.CloseMainWindow() (after finding it in the process list).

While it seems clean enough, I wondered if there's a better way.

Question:

Which way would be best to instruct the client application to shut down:

  • Continue using Process.CloseMainWindow()?
  • Implement WCF between the applications? (I would need help on how to do this.)
  • Set a variable in SQL that the client application checks for?
  • Some other way?
JYelton
  • 35,664
  • 27
  • 132
  • 191
  • 1
    `Process.CloseMainWindow()` seems good enough (closing the main window will exit most applications). But why not remember the process that you started, e.g. in a class field or local variable instead of searching it in the process list? – Dirk Vollmar May 13 '10 at 22:07
  • That would be an improvement! When I start it, I just call Process.Start("app.exe") but .Start() doesn't return a process ID. How best do I remember the process to later terminate? – JYelton May 13 '10 at 22:25
  • Simply store the `Process` returned by `Process.Start` or create a new `Process` instance as described in the sample here: http://msdn.microsoft.com/en-us/library/e8zac0ca%28VS.90%29.aspx – Dirk Vollmar May 13 '10 at 22:31

3 Answers3

1
  • Some other way?

You can use .Net Remoting.

However, you should probably use WCF instead.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • I think this is a valid answer but I would also like to add that Microsoft recommends the use of WCF over Remoting, see http://stackoverflow.com/questions/1294494/is-net-remoting-really-deprecated/1294532#1294532 and http://msdn.microsoft.com/en-us/library/72x4h507%28VS.85%29.aspx. – Dirk Vollmar May 13 '10 at 22:05
  • For such a simple bit of information, WCF seems very complicated to me, perhaps it is overkill; on the other hand, .NET remoting seems easier (so far) though I dislike the idea of using something that's "on its way out." – JYelton May 13 '10 at 22:08
  • I realize that WCF is a better choice. I'm just presenting another option. – SLaks May 13 '10 at 22:13
  • Perhaps I should ask a separate question about WCF: Is it possible to set up between two winforms applications alone? And thanks for the info. – JYelton May 13 '10 at 22:25
1

Given that Process.CloseMainWindow() works indicates that both programs run on the same machine. Given that a true service cannot start programs that are visible on the desktop anymore indicates that your server program runs as a regular user app.

It now makes no longer any sense to have separate programs. Simply have the server create a visible window. Interaction is trivial since everything runs in one program and has access to all state of that program.

If the server processing gets in the way of keeping the client window alive then display that window on a thread. This helper class gets the job done:

using System;
using System.Threading;
using System.Windows.Forms;

static class ClientView {
    private static Form mView;

    public static void Start(Form view) {
        if (Busy) throw new InvalidOperationException("View already running");
        mView = view;
        mView.FormClosed += (o, e) => { mView = null; }
        Thread t = new Thread(() => Application.Run(view));
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }
    public static void Stop() {
        if (Busy) mView.Invoke(new MethodInvoker(() => mView.Close()));
    }
    public static bool Busy { get { return mView != null; } }
}

Sample usage:

ClientView.Start(new ClientForm());
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I have some reasons for having them be separate applications, but this is a valid and useful idea. – JYelton May 17 '10 at 14:43
1

Given that Process.Start(string)

A new Process component that is associated with the process resource, or null, if no process resource is started (for example, if an existing process is reused).

Process myProcess = Process.Start("client.exe");

You can then use this value to call CloseMainWindow:

myProcess.CloseMainWindow();

The only overload that doesn't return a Process component is the parameterless method.

(BTW I didn't read the comments on the question until after I posted this answer)

ChrisF
  • 134,786
  • 31
  • 255
  • 325