How do I open a new document in running application without opening a new instance of the application? - c++

I have a situation that has been partially covered by other answers at SO, but I cannot find a complete answer. In short, we are trying to use URL's for our specific data types that when double clicked will open up our application and load those data sets into that app. We have this part working.
(for example, an URL might look like this: resource://shaders/basic_shader.hlsl)
What we would like to do is to prevent new instances of the application from opening when a new URL is double clicked. For example, let's say we have a URL that opens up a shader in our shader editor. When clicking this resource URL, it will open our shader editor. When a new shader URL is clicked, we'd like to be able to open up the shader in the currently running application and have it open up the new shader in a new tab in our editor.
We can easily detect if another instance of our application is running. The problem that we don't know how to easily solve is how to tell the currently running application to open up this new file for editing. This behavior is very much like the Apple Finder.
In unix, you could emulate this behavior by having your application open some named pipe and then new apps could check if this pipe is active and then send the document data down the pipe. Is there a more standard windows way of achieving this behavior?
We need a C/C++ solution. Thanks.

Named pipe is the best way.
First instance of your application opens the pipe and listens to it (use PIPE_ACCESS_INBOUND as dwOpenMode and the same code will also allow you to detect running instances).
All subsequent instances check that they are not alone, send command line argument to the pipe and shut down.

Create a named mutex when application launches as David Grant said, then before displaying the UI for the second URL, check for this mutex, if it is already created then just quit by passing the new URL to the first launched application (Have interface in the application to set the URL and tell to redirect programatically)

You can't avoid the program associated with the url to be executed.
The "windows" solutions would be to send a message (via DDE in the old days but maybe there is something more "modern" now) to the previously running application with the url then quit ...

You can acquire a named mutex upon startup and enforce it that way.
http://www.google.com/search?hl=en&q=named+mutex+single+instance
CreateMutex on MSDN

I got this working pretty well for my C++ MFC application by following Joseph Newcomer's tutorial here. He uses a named mutex that is checked on startup and a message sent to the already-running application with the new resource to be opened.

Related

How can I seamlessly and discretely communicate new URI launch parameters to a currently running application in Windows?

Case: Click a URL in the browser and a video game that is currently running on user's desktop can ingest that data and do something.
I've been working on this for some time, but I don't know if I'm on the right path.
What I currently have:
A clickable URI in a webpage that can have different arguments for the client to recieve.
The URI scheme is registered in Windows. When clicking URI in the browser it will launch a c++ console 'launcher' or 'bridge' app that is already installed on the user's PC.
This 'launcher' is a middle-man that parses the URI arguments and communicates them to the main 'user' app (a video game) via IPC named pipes.
How do I:
In terms of UX, make the whole process discrete and seamless?
Specifically, I need to:
Keep launcher hidden from the user - no pop-up.
Needs to be only capable of running a single instance, even when invoked with new URI parameters. Do I just exit the current and create a new one?
User can click another URI in the webpage and the launcher will process the new arguments without displaying itself to the user.
Tech constraints:
Windows.
Preferably needs to be C++. C# could be a possibility.
Existing example:
Zoom conferencing software appears to works similar to this.
Clicking a URL in the browser launches a 'launcher' which starts the main app to video conference.
Closing that 'launcher' will minimize it into the system tray.
Clicking on a new link while the launcher is running does not start a new launcher, but it does start a new meeting.
How does something like this normally work?
The OS automatically creates a console for /SUBSYSTEM:CONSOLE apps. It doesn't automatically create a window for /SUBSYSTEM:WINDOWS. So use /SUBSYSTEM:WINDOWS.
Then, create the named pipe before creating the main window.
If the return code tells you a new pipe was created (use FILE_FLAG_FIRST_PIPE_INSTANCE), you're the primary instance, create main window and run normally, with an OVERLAPPED read on the named pipe to receive data from future invocations.
If instead you opened an existing named pipe, write your command line through the named pipe and exit without ever creating a window.
You don't need a separate launcher at all, and actually separating the launcher from the main application creates a race condition (a second launcher starts before the first instance managed to launch the main program / before the main program is up and running, doesn't see an existing named pipe, and thinks it is the primary copy). You are better off putting both sides of the argument-forwarding logic into the main executable.

How to make application not to run a new instance when openening a new file in Qt?

For example we have a TextEditor Application. Like notepad++. We have tabs at which file content was displaying.
The default text editor in OS is set to TextEditor Application. When we open a new file application added a tab and put content to it.
How to make an application not to run a new instance when opening a new file in Qt?
Which is the best way you think?
The problem is how can you make a single-instance application. When you open a file the operating system will open the associated application and give it the file as a command line argument. You cannot simply delegate an 'open file' command to a running application through OS mechanism, you have to implement it by yourself.
At the AppWhirr project we used QLocalServer/Client to communicate between instances: when the AppWhirr app is executed it checks whether a QLocalServer with a fix ID is already taken or not. If not this instance of the application is the first/only running instance. If the ID is already taken it means another instance of the application is already running so this second instance will only do 2 things: send the given input arguments to the other instance through Qt's local client/server communication, and when it's successfully finish the communication it will quit (the second instance).
That's one solution for the problem, requires quite a bit of coding and I would not recommend it if you don't want to use local client/server communication for anything else, but it's a viable solution.
Another solution would be that the first instance of the application creates a text file at a fixed location and writes our the instance's ID. After this the second instance can read the text file and send a message to the specified ID. And of course the first instance have to remove the text-file when it quits and probably you have to implement some fail-safe code to remove the text-file in case the first instance crashes. This solution will use less resource than the first one but requires a fail-safe cleanup code.
Or as a third option you can use third-party solutions like #Matteo Italia suggested.

Control multiple program instances - open multiple files problem

This shouldn't be an unusual problem, but I cannot find anything about it at google or at other search machine.
So, I've made an application using C++ and QtCreator. I 've made a new mime type for application's project files.
My system (ubuntu 10.10), when I right click a file and I choose "Open With 'Default Application'" the it runs
Code:
default_application path/to/the/selected/file1
So, if you select multiple files and select "Open With 'Default Application'" the system will call
Code:
default_application path/to/the/selected/file1
default_application path/to/the/selected/file2
default_application path/to/the/selected/file3
So, this is a big problem for me, because I handle the concurrent processes from inside the program, so when another instance of the program is running, a warning message is appeared. So, each application's call will recognize the others as currently running applications and so it'll show the message. I'll end up with 3 Messages saying that another process of the program is running --_--'
My application handles multiple URLs this way:
Code:
myapp path/to/the/selected/file1 path/to/the/selected/file2 path/to/the/selected/file3
How can I make my code handle all these multiple instances at the same time? Everything I've tried fails, because everything I've tried requires a check from the first instance called, which is too slow and other instances come app and all together are warning about concurrent processes of the same program
So, how can I fix this? is it system depended, or can I do something with the code?
The way is to make your application recognize that there is already an instance running and make the new instance just forward a request to the first instance before dying :)
EDIT:
The way to do that is to have your first application instance behave as a server. The pseudo algo is something like :
start();
try_to_contact_master_server_instance();
if(no_master())
{
I_am_master();
start_listening_server_that_wait_for_requests();
}
else
{
send_request_to_master("open file path/to/the/selected/file1");
send_request_to_master("open file path/to/the/selected/file2");
send_request_to_master("open file path/to/the/selected/file3");
die();
}
handle_incoming_requests();
I hope it's clearer ? Tell me if you need more precisions ...
For the server part, you can do your own or use some software bus provided by the OS like dbus or whatever, but it makes your application dependent, of course.
my2c

Passing a file location to an external process using Win32/MFC

I'm trying to fulfill a client request here, and I'm not entirely sure I can actually do it. I have an MFC application that relies upon ShellExecute to open files in their appropriate viewer, which spawns multiple viewers if you try to open multiple files one after the other. If you open one .txt document, and then open another, two copies of notepad appear as expected.
The client wants us to change this functionality - Windows' functionality - to just pass file locations to any viewers that might already be opening. The first image clicked should open Image Viewer, but any other should just be opened in that existing process.
Is that kind of inter-application control/communication possible? Can I generically "pass" files to existing processes? I don't think I can. Executing a program with a file as a parameter is one thing, but passing a file to a running process is something else altogether. I'm not sure you can do that generically, I don't think that kind of functionality is anywhere in the Windows APIs.
I could be wrong, though.
This isn't possible if the viewer don't support multiple open files in same instance.
in your example: notepad will launch a new version with each file, while Notepad++ (a free editor) will open in same instance in a new tab.
The first thing you should try is calling the program again with the new parameters. If the program is written in such a way it will delegate the new parameter to the existing instance. Notepad doesn't do this, image viewer may though.
The next thing you can try is managing the life of the application by keeping track of the handle yourself. You call CreateProcess, so you create and own the handle to this process. On the next call to CreateProcess, enumerate the open windows and try to find your last handle. If the handle is found, close it and continue with your open process. You should only get one open application. For the most reliable solution, put this in a separate thread and wait for the handle (as well as a new request event) to avoid any race conditions.

Intercept windows open file

I'm trying to make a small program that could intercept the open process of a file.
The purpose is when an user double-click on a file in a given folder, windows would inform to the software, then it process that petition and return windows the data of the file.
Maybe there would be another solution like monitoring Open messages and force Windows to wait while the program prepare the contents of the file.
One application of this concept, could be to manage desencryption of a file in a transparent way to the user.
In this context, the encrypted file would be on the disk and when the user open it ( with double-click on it or with some application such as notepad ), the background process would intercept that open event, desencrypt the file and give the contents of that file to the asking application.
It's a little bit strange concept, it could be like "Man In The Middle" network concept, but with files instead of network packets.
Thanks for reading.
The best way to do it to cover all cases of opening from any program would be via a file system filter driver. This may be too complex for your needs though.
You can use the trick that Process Explorer uses to replace itself with task manager. Basically create a key like this:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskmgr.exe
Where you replace 'taskmgr.exe' with the name of the process to intercept. Then add a string value called 'Debugger' that has the path to your executable. E.g:
Debugger -> "C:\windows\system32\notepad.exe"
Every a process is run that matches the image name your process will actually be called as a debugger for that process with the path to the actual process as an argument.
You could use code injection and API redirection. You'd start your target process and then inject a DLL which hooks the windows API functions that you want to intercept. You then get called when the target process thinks it's calling OpenFile() or whatever and you can do what you like before passing the call on to the real API.
Google for "IAT hooking".
Windows has an option to encrypt files on the disk (file->properties->advanced->encrypt) and this option is completely transparent to the applications.
Maybe to encrypt decrypt file portions of a disk you should consider softwares like criptainer?
There is this software as well http://www.truecrypt.org/downloads (free and open source) but I haven't tried it.
Developing a custom solution sounds very difficult.