I am trying to open a local html document using Shell Execute(). But, what i need is, Suppose if that particular document is already opened and if ShellExecute is triggered again, then that particular file should not be opened again instead bring the already opened file into foreground. Can you please suggest how can i do this?
void main()
{
ShellExecute(NULL, "open", "C:\\prograomgiles\\help.html",
NULL, NULL, SW_SHOWNORMAL);
}
It's nearly impossible, because it depends on which program processes the html files and how does it work. Suppose, that my OS opens html files by printing them directly on a printer. How would you bring opened file into foreground?
If you want to display HTML content in the way specified by you, write your own browser (It's quite easy, you can - for example - embed IE in C#.NET application) and run it instead of default system browser. You would have then full control on how your files are displayed.
Many web browsers respond to DDE messages, particularly the WWW_OpenURL message. Not sure about other browsers, but IE also responds to WWW_GetWindowInfo and WWW_Activate messages, which you could use to enumerate open windows and their URLs, and then activate a particular window.
Related
I am trying to use ShellExecute to open a .txt file in the default browser.
I am currently using
ShellExecute(0, L"open", L"http://E:/path/to/file.txt", 0, 0, 1);
This correctly creates a new window in the browser but tries to open
E/path/to/file.txt (without the ":")
and then can not find the associated file. The file location is definitely correct as manually adding the ":" back in the browser opens the file as desired.
Option 1
Use AssocQueryString or IQueryAssocations to figure out the default browser, then launch that browser with your text file on the command line.
Option 2
Create a temporary .html file with a <meta> tag that redirects to a file:// URL that loads the text file. Then ShellExecute with your temporary .html file. Since the temp file is of type .html, it should load the user's default browser. The redirect will then cause the browser to load the text file.
The trick is figuring out when to clean up your temporary file. ShellExecute doesn't make it easy to get a handle to the launched process (and, in reality, the process you launch may just launch another process), so you don't have an easy way to know when the browser is done with your temporary file. You might just keep track of the temporary files you create and try to delete them when your application closes.
ShellExecute will open a txt file inside the default text viewer, which isn't a browser I suppose. To open inside a browser, explicitely run the browser and give the file as argument. For example:
ShellExecute(
0,
L"open",
L"C:\\Program Files\\Internet Explorer\\iexplore",
L"E:\\path\\to\\file.txt",
0,
1
);
note: I already looked at the following question but it provided no insight: PDF file does not get open from ShellExecute function in Visual Studio, C++
I have the same problem as the poster in the above question.
Trying to open a PDF file from an MFC Application using ShellExecute. Adobe XI on Win 8 64 bit system.
hReturn = ::ShellExecuteA(NULL,"open",sPath,NULL,NULL,SW_SHOWMAXIMIZED);
sPath is a CString although I've tried alternatives with the same result. I've also tried SW_SHOW, SW_SHOWNORMAL. ShellExecute returns 42 when I cast the HINSTANCE to an int. I understand that means it opens successfully.
In fact, if I watch the task manager when executing the command, Adobe Reader opens in response in Task Manger but the Adobe window never opens.
When I exit my application, Adobe is still open.
If I try to open the target PDF file, the O/S says it can't be opened because it is already open in another application. When I "End Task" on the Adobe Reader in task manager, it frees up the file.
If I then click on the file, it opens fine in Adobe Reader.
So, I'm inferring from this that the ShellExecute is launching Adobe, that it is getting the right file, and that the file is, indeed, readable.
I've also confirmed that ShellExecute is working by directly referencing a txt file. It opens fine in Notepad.
hReturn = ::ShellExecuteA(NULL,"open","d:\\develop\\readme.txt", NULL, NULL, SW_SHOWMAXIMIZED);
Any ideas?
Thanks
try disable "Protected mode"
Adobe Reader - Protected Mode
This seems to be a known problem with opening a PDF file on Win8 via ShellExecuteEx. I had the same issue with an installer that would try to open a PDF at the end of the install process. On Win7 it worked fine. On Win8, it displayed the symptoms you describe. I was able to track it down to a problem with elevated privileges on our install program. I'm not sure why that would adversely affect things, but, it did. As an alternative, we looked at opening the file as an HTML document instead. We are still looking for a better solution.
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.
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.
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.