Can I open one batch of files from Explorer in one instance of my app, and a separate batch in a second instance?

StackOverflow https://stackoverflow.com/questions/16695957

  •  30-05-2022
  •  | 
  •  

Question

(First: I know this is very similar to a lot of other questions, but I have a secondary requirement that I haven't seen elsewhere.)

I'm creating an app where the user can do some work on a file (adjusting metadata, sending to another location, possibly some other things in the future). In a lot of cases, the same actions are going to happen to a lot of files at once, so what I want to do is, if the user has multiple files selected, they can right-click and use an action of some sort from that context menu, and all selected files & folders will be passed to my app for bulk processing.

Now here's the tricky bit - while the user's doing this bulk processing on one set of files, they might go off and select a different set of files and set up another bulk processing action on them, and I need to keep the two batches separate because the actions taken on the first batch are not likely to be appropriate for the second batch.

That second requirement is where I'm running into problems. I can't just do a normal singleton, because the two batches will get lumped together into one batch, which would be a Very Bad Thing(tm) for my users. But so far, I haven't found any elegant way to open one batch of files in one instance, and a later batch in a new instance.

I've come up with a couple options... First, when my app starts I could look up other instances, communicate with each of them in turn to find out when they were started, and if the times were close enough together, shut down this instance in favour of the older one. A second option would be to somehow add a unique operation identifier to the command line arguments; similarly to the first option, when the app starts it would look for other instances of itself and try to find the one that's the master (probably using the identifier as part of a mutex name to make it easy to figure out which one was first). Another option might be to create a shell extension to bundle up the list for me and pass the list to my app all at once (don't know for sure if this would work, to be honest...)

Of the ideas I've come up with, #2 is definitely my preference if it works. It keeps all the code in C#, which means anyone on my team could maintain it, and it also provides a way to definitively group the commands into batches. The only problem is that I don't know of a way to add some ID to the args for each instance that'll be consistent for all attempts to start my app from a single right-click action, but different for each time the user does a separate right-click + open (or whatever). Maybe I could do that through a shell extension...?

If anyone has any suggestions on how to make this happen, I would really appreciate it. I'd prefer a reasonably elegant, robust solution that's easy to maintain rather than the bull-in-a-china-shop type of code I'm liable to end up with if I have to just hack my way to a solution.

Was it helpful?

Solution

Here's what I've come up with...

I took the code sample from C++ Windows Shell context menu handler (CppShellExtContextMenuHandler) and adjusted it considerably. I started by making it act on * and Directory, because in my case the user should be able to perform this action on any combination of files and folders. Next, instead of popping up a message box with the command, I changed it to use CreateProcess with a redirected stdin (as per the example here). Once the process is created, I write the list of files to the pipe, one per line. (I'm going to try changing that to write the list of files to the pipe before starting the process, to avoid the potential race issue.) My target application simply reads in the console line by line until it runs out of data, and uses that list of files.

It's a longer and more perilous process than I'd like - I crashed the shell a couple times during testing because of oversights in coding the extension! - but it gives me exactly what I want, which is the ability to right-click a set of files in Explorer, have them all open in the same instance of my app, and then right-click on a different set of files and have them open in a separate instance.

Of course, just because I have an answer doesn't mean it's the answer. I'm not going to mark this as the final answer for a little while, in case anyone else comes along with something better. Heck, even if you don't think your answer is better, I'd love to hear it! It's always fun to see how other people approach a problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top