tags:

views:

527

answers:

4

How would you open a file (that has a known file/app association in the registry) into a "running instance" of the application it's supposed to open in? An example would be, I have Excel open and I click on an XLS file.....the file opens up in the current Excel instance. I want to do this for a custom application...how does the eventing/messaging work that "tells" the current instance that it needs to open a file? Is there a "file watcher" that looks for a request to do so etc? Thanks..

+1  A: 

The way I'd do it is like this:

  1. First thing in the main method, check the process list for an existing instance of the application.
  2. If found, send the filename/path to the already running instance using your favorite interprocess communication method (sending windows messages, remoting, wcf, etc.)
  3. Close the new process that windows tried to start (since the existing instance already handled the file open operation
Joel Martinez
@casperOne, meh, even if there are a few thousand processes running, how long could it take? if it becomes a problem and startup time is important for his app, he could do it in a sep thread and just interrupt normal startup if an existing instance is found.
Joel Martinez
Scanning the process list is a wasteful procedure. What you really should do is have a Mutex which is acquired by the application when it runs. If you can't obtain it, then another instance is running. THEN you use a messaging tool to indicate to the original instance the new parameters.
casperOne
@Joel: Well, I was working up to a point, which was, the majority of this work has been done for you, wrapped up in the WindowsFormsApplicationBase class. A comment like "how long could it take" is also quite ignorant, because the overhead is not always a function of the number of processes.
casperOne
@Joel: Because if you have the chance to reduce the operation from O(n) time to O(1), and it's an easy win, then there is no reason not to take it (if they serve the same purpose).
casperOne
speed and permissions aside, how reliable is scanning the process list? isn't it just the executeable's filename? what if i rename it?
Lucas
+7  A: 

What you want to do is inherit a class from WindowsFormsApplicationBase, setting the protected IsSingleInstance property to true:

// This should all be refactored to make it less tightly-coupled, obviously.
class MyWindowsApplicationBase : WindowsFormsApplicationBase
{
  internal MyWindowsApplicationBase() : base()
  {
    // This is a single instance application.
    this.IsSingleInstance = true;

    // Set to the instance of your form to run.
    this.MainForm = new MyForm();
  }
}

The Main method of your app then looks like this:

// This should all be refactored to make it less tightly-coupled, obviously.
public static void Main(string args[])
{
  // Process the args.
  <process args here>

  // Create the application base.
  MyWindowsApplicationBase base = new MyWindowsApplicationBase();

  // <1> Set the StartupNextInstance event handler.
  base.StartupNextInstance = <event handler code>;

  // Show the main form of the app.
  base.Run(args);
}

Note the section marked <1>. You set this up with an event handler for the StartupNextInstanceEvent. This event is fired when the next instance of your app is fired when you have a single instance application (which you specified in the constructor of MyWindowsApplicationBase). The event handler will pass an EventArgs-derived class which will have the command line arguments which you can then process in the running instance of your app.

Then, all you have to do is set the file associations normally for the file types you want your app to process, and you are set.

casperOne
Including a reference to the VisualBasic dll from C# seems wierd, to me, so I usually go the global Mutex route, but this is definitely easier. +1
Lucas
@Lucas: I had that reaction initially, but it's a standard part of the framework (it's distributed with every install) so that helped ease my feelings on that matter.
casperOne
+2  A: 

Looks like what you are looking for is creating a single instance application. This can be done in C# by using WindowsFormsApplicationBase located in Microsoft.VisualBasic.dll

For details, take a look at: http://www.hanselman.com/blog/TheWeeklySourceCode31SingleInstanceWinFormsAndMicrosoftVisualBasicdll.aspx or search for WindowsFormsApplicationBase

foson
+1 for linking to Hanselman :P
Lucas
A: 

Windows uses DDE for this purpose.

Dynamic Data Exchange (DDE) is a technology for communication between multiple applications under Microsoft Windows or OS/2.

Registry associations for word or office files usually have DDE commands in addition to the usual file association (to be executed if the app already is running).

So you can host a DDE server in your C# app to implement this functionality.

Rinat Abdullin