How to associate double file extension to application on Windows 10 - windows

I want to associate a file extension .mps.gz to an application on Windows 10.
The .gz extension should not be affected. How can I do this?

You cannot in general because Windows only cares about the text after the last period.
There are of course ways to hack around it. The naive way would be for your application to handle it. If the original registration looks like
HKCR\gzfile\shell\=open
\open\command=c:\otherapp.exe "%1"
you would change it to
HKCR\gzfile\shell\=myapp
\open\command\=c:\otherapp.exe "%1"
\myapp\command\=c:\myapp.exe "%1"
And if myapp.exe is executed with something you don't handle you would call ShellExecuteEx on the file and set lpVerb to open.
A better solution would be to decide inside the shell before anything is executed. For Windows 95 to 10 you could implement IContextMenu and only add your default menu item in QueryContextMenu if you like the file in the data object. The MayChangeDefaultMenu subkey must exist for this to work. On Windows 7, 8 and 10 you could implement IExplorerCommandState instead if you prefer a static verb.
For Windows 11 I suppose you are going to handle IExplorerCommand::GetState but I don't know if this lets you become the default handler.

Related

Why does ShellExecuteEx with verb "print" take LNK file settings of an app into account?

Context
I have a Windows app printing PDF files by forwarding the file paths to ShellExecuteEx and the verb print. Adobe Reader is installed and registered for that verb. Reader by default creates a LNK shortcut file in the start menu:
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Adobe Acrobat DC.lnk
Hide windows
By default, reader shows a GUI window when printing a PDF. Some customer doesn't want that window and simply tried to "hide" it by changing the LNK file content using Windows Explorer properties to at least minimize the windows by default. That customer didn't know if that works or not, one simply tried.
To my surprise this worked, changing the minimize vs. non-minimize/default setting of the LNK file made the reader windows being visible or minimized.
No changes in registry
I've searched the registry for changed settings regarding the print verb, but couldn't find any. The new setting really seemed to be only stored within the LNK file:
The registry contained references to the actual EXE only, not the LNK file. Pretty much like expected, I've never came across any shell verb registration using LNK files at all.
"C:\Program Files\Adobe\Acrobat DC\Acrobat\Acrobat.exe" /p /h "%1"
Though, all invocations of the verb print seemed to recognize that setting, either manually using the context menu of some PDF in Windows Explorer or executing things on the shell:
powershell -Command "Start-Process -Verb print '\\?\C:\[...].pdf'"
Why is that important?
Adobe Reader provides the command line argument /h to minimize itself as well, but using that doesn't fully hide a window at all. Instead, a window is shown for a second or so and afterwards minimized, e.g. like Adobe is doing that itself. OTOH, with the changed LNK file things are different: Either really now window is shown at all or only some artifacts like the window title or alike for less than a second.
It really seems that the difference is between Adobe doing something on it own after it has loaded and stuff vs. Windows itself creating the minimized window already.
Additionally, if possible at all I would like to avoid customers needing to change the LNK file themself. The problem with that change is that it's not tied to the print verb only, but whenever Adobe Reader gets opened. And sometimes customers really need to have a look at PDFs themself instead of automatic printing only.
So, how does that work?
Is Windows itself using the setting of that LNK file or is this something implemented by Adobe Reader?
Using ProcMon, I couldn't find any hint about that Adobe Reader itself reads the LNK file. As well, I couldn't find this behaviour documented in the topics about shell verbs, ShellExecuteEx etc. It's totally unexpected to me, as the LNK file is some arbitrary file in theory, which might not exist at all, can be named as one likes, even multiple of those could exist in theory starting different apps of some package or the same app with different arguments etc.
Thanks for any insights.

How do I set "default App" for a file extension to an ".exe" on Windows 10 after April 2018 update

I have spent a very long time researching this. Most of the solutions were posted PRIOR to April 2018, and involved working your way through the "settings" to get to "Choose default Apps by file type".
Choose default Apps by file type
In previous attempts to assign an app to ".rex" I managed to assign it to Notepad. (At that time, I could not find any way to find an ".exe" on my C: drive.)
So as you can see, if you click on Notepad next to the .rex extension, the only option is to go to the "App store".
And as expected, if you click on App store, nothing is found...
App store - no app's found.
So from what I've read in multiple forums, PRIOR to April 2018, Windows 10 still had a way to "browse your hard drive" to find an ".exe". (Just like in older Windows versions.) After some update in April 2018, that capability no longer exists.
In the POST April 2018, has anyone found a way to assign a file extension to an ".exe" on the hard drive???
I think this question would be more suitable for SuperUser (well, unless you want to do it via a program :) ).
Anyway, here's a way of doing things from console (Cmd). I've tried it 1 or 2 years ago, I just tried it now, so it works regardless of Win (10) version.
Start the process from scratch:
Open a Command Prompt window. Create a new file that the OS doesn't know anything about. I chose the extension .zzz:
e:\Work\Dev\StackOverflow\q052008516>ver
Microsoft Windows [Version 10.0.17134.228]
e:\Work\Dev\StackOverflow\q052008516>dir /b
e:\Work\Dev\StackOverflow\q052008516>:: Create a dummy .zzz file
e:\Work\Dev\StackOverflow\q052008516>echo Some dummy text>file.zzz
e:\Work\Dev\StackOverflow\q052008516>dir /b
file.zzz
Try opening the file (DblClick) from a file browser (it's not relevant, but I use Total Commander), or by typing its name in Cmd. That will yield the dreaded dialog:
Create a new file type and associate our extension with it. [MS.Learn]: assoc utility is used to do the job. First, check if such association doesn't already exist:
e:\Work\Dev\StackOverflow\q052008516>:: No output means no association
e:\Work\Dev\StackOverflow\q052008516>assoc | findstr ".zzz"
e:\Work\Dev\StackOverflow\q052008516>:: Same command for a different extension
e:\Work\Dev\StackOverflow\q052008516>assoc | findstr ".txt"
.dic=txtfile
.exc=txtfile
.log=txtfile
.scp=txtfile
.txt=txtfile
.wtx=txtfile
e:\Work\Dev\StackOverflow\q052008516>:: Create a new FileType (ZZZFile) and associate our extension with it
e:\Work\Dev\StackOverflow\q052008516>assoc .zzz=ZZZFile
.zzz=ZZZFile
e:\Work\Dev\StackOverflow\q052008516>assoc | findstr ".zzz"
.zzz=ZZZFile
No change when trying to open the file.
Associate the file type (ZZZFile, from previous step) with a command. Use the [MS.Learn]: ftype tool for the task. Again, check if the file type is not already associated (this only makes sense if the file type existed before previous step):
e:\Work\Dev\StackOverflow\q052008516>:: As usual, no output means no association
e:\Work\Dev\StackOverflow\q052008516>ftype | findstr ZZZFile
e:\Work\Dev\StackOverflow\q052008516>:: Same thing for txtfile
e:\Work\Dev\StackOverflow\q052008516>ftype | findstr txtfile
txtfile=%SystemRoot%\system32\NOTEPAD.EXE %1
e:\Work\Dev\StackOverflow\q052008516>:: Associate ZZZFile with notepad
e:\Work\Dev\StackOverflow\q052008516>ftype ZZZFile=%SystemRoot%\system32\notepad.exe %1
ZZZFile=C:\WINDOWS\system32\notepad.exe %1
e:\Work\Dev\StackOverflow\q052008516>ftype | findstr ZZZFile
ZZZFile=C:\WINDOWS\system32\notepad.exe %1
Try opening the file again (from Cmd), and voilà:
Summary:
In order to open with Notepad files having .zzz extension, there are only 2 commands that need to be remembered from this whole (and pretty long) answer:
assoc .zzz=ZZZFile
ftype ZZZFile=%SystemRoot%\system32\notepad.exe %1
Notes:
My user has (super) administrative privileges, but I guess they shouldn't impact differently depending where the action is performed from (Cmd or UI (if possible)), in other words users that don't have the required privileges, won't be able to do it, no matter what they would try
Apparently, there is a (pretty dark) nebula on this topic, that my knowledge wasn't yet able to "decipher". In my example, I constantly compare the .zzz results to .txt. Yet a big surprise: Notepad++ and not Notepad is used to open txtfile (.txt only), in spite of the above output
Update #0
I did a little more digging on the .txt mystery. Facts:
FType shows Notepad as opening program
It is actually opened by Notepad++ (in Cmd and PS)
In Choose default apps by file type, Notepad++ is shown
So apparently, it's more than meets the eye (over the years, I got used to MS's way of doing things which in some cases seems to be (but maybe it's me who didn't have all the pieces) illogical).
I've also found out many resources like:
[MS.Technet.Blogs]: Windows 10 – How to configure file associations for IT Pros? which mentions the command:
dism /online /export-defaultappassociations:"file.txt"
[XDADevelopers]: Programatically set default file associations which mentions the reg keys:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\${EXT}
HKCR\${EXT}
I couldn't find anywhere a clear algorithm of how an executable is chosen to run a file with a certain extension. I can think that the 2 keys above are queried, but I'm 100% sure there's more. Not to mention that I've ran into an even stranger problem (for a regular user on my Win 10), for .py files:
FType (and Assoc) reported everything as above
In Choose default apps by file type, Python was shown (just like in my Super Admin user's case)
Attempting to run the file from Cmd, yielded the dialog at the beginning
It worked from PS
Sadly, I selected Python from the dialog, before taking a look at the registry keys (and now it works), so I can't do any more debugging (and also, switching users is annoying).
Might be related:
[SuperUser]: Windows 10 won't let me set default apps for file extensions
[SuperUser]: Can't change Windows 10 default file type association
[SuperUser]: SSMS wont give up file associations

FTYPE/ASSOC priority and adding to OpenWithList from the command line

(Not sure if this belongs on superusers, but it seems there is a cmd.exe tag here, so here goes...)
As background, I'm working on a Firefox add-on (This question does not require knowledge of Firefox, btw, as Firefox add-ons can call the command line.) The add-on aims to build different kinds of shortcuts to cmd.exe (especially for the sake of my project https://github.com/brettz9/webappfind which allows files to be opened directly from the desktop into web apps).
Anyways, I'd like to give users the option to associate these shortcuts:
As the default handler for specific file extensions or file types.
To show up within the Open With list of applications (even if the user opts not to make the apps as default handlers)
As far as the default handling, I have found the ftype and assoc (and associate) commands, but I have read that user selections will override their behavior. Is there some way to ensure that I can get priority from the command line in associating file extensions to types and specific executables (until the user changes it again), or if it is not possible, then at least through C++ or the like?
As far as the Open With list:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<file extension>\OpenWithList
...in my testing (with an exe), this command:
reg add HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.svg\OpenWithList /v d /d D:\wamp\www\webappfind\cplusplus\WebAppFinder-view-mode-Firefox.exe
...did cause the exe file to show up in:
reg query HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.svg\OpenWithList
...but it did not show up when I subsequently right-clicked a file with the ".svg" extension.
I would really appreciate any help with these two points.
REGEDIT4
[HKEY_CURRENT_USER\Software\Classes\Applications\MYFOO.exe\shell\open\command]
#="\"C:\\MYFOO.exe\" \"%1\""
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.myfoo]
"Application"="MYFOO.EXE"
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.myfoo\OpenWithList]
"a"="MYFOO.EXE"
"MRUList"="a"
So I got to an investigation what makes those file associations. It appears that you have to create a mapping from the bare EXE name to the full path as shown in the first two long-ish lines. Then you must only use the EXE name in the .extension branch. Setting the .extension's Application value will give you your default app instantly. Remember, only use APP.EXE, its full path must be defined as above. This was your main error. The "%1" part allows you to customize the parameters of your program so that it doesn't have to be just the opened document in quotes, as shown here. The backslashes are just escape characters for Regedit, you may discard them as you see fit.
The OpenWithList is tricky in the sense that there are letters for entries and just a blind write may overwrite some of the user's favorite apps. One approach would be to call your item "z" to lower the probability of overwriting. The right way would be enumerating the key and giving your app the first free letter. The MRUList is not essential, although it should have each used letter once and yours bumped to the start.
Note about user friendliness: Explorer will cache these values until next reboot. Make sure you update the registry and place exe first and create your file later. Although the caching only fully influences the display of the file and when it is run, the registry is read again and it will execute as you want.
TIP: If you decide to use Regedit instead of reg, the /s parameter skips the confirmation message and applies the values right away. Make sure you use double backslashes in the full path as shown. When preparing your temporary .reg file, make sure you append two CRLF's to the end or a glitch may cause your last line of code to be ignored. This sample starts with REGEDIT4 which signifies an ANSI file. If you need support for Unicode in your app path, you'll have to start the file with Windows Registry Editor Version 5.00 and store it in UTF16. This is already a superior solution to calling reg because there's no way you could get CMD.EXE to process special UTF stuff through the command line without mangling.

Passing arguments while launching program from browser

I am trying to launch an application (.exe) from my browser.
The specific app needs 4 arguments/parameters when launching, which are: firstname, lastname, id, info
Is there a way to add these arguments on the Internet Explorer address bar when i launch my program?
I mean something like this:
"myapp:// -firstname -lastname -id -info"
(I only managed to add those arguments straight to the windows registry, it worked that way. But thats no help... i need them to be inputted when launching the app )
I have added this to my windows registry:
[HKEY_CLASSES_ROOT\myapp]
#="URL:myprogram Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\myapp\DefaultIcon]
#="\"C:\\myapp.exe\""
[HKEY_CLASSES_ROOT\myapp\shell]
[HKEY_CLASSES_ROOT\myapp\shell\open]
[HKEY_CLASSES_ROOT\vsa\shell\open\command]
#="\"C:\\myapp\" "%1"
Thanks for help already! I hope someone knows how to fix this... :)
ps. Im using windows 7 64 bit and Internet Explorer 10.
You cannot simply pass multiple command line arguments to your application (unless they're listed explicitly in the registry as you've shown).
Instead, you must code your application's executable so that it is able to process the Application Protocol URL string. So your code is invoked by the browser like so:
C:\apps\myapp.exe "myapp:myParam?myParam2&myParam3&myParam4"
The executable must be able to process this string and handle it appropriately. You must take care to avoid security holes in the parsing of this string, as ANY webpage could exploit a hole here to escape the browser sandbox and attack the user's system.
There's more information on Application Protocols in this post: http://blogs.msdn.com/b/ieinternals/archive/2011/07/14/url-protocols-application-protocols-and-asynchronous-pluggable-protocols-oh-my.aspx

How to pass multiple associated files to a program?

I have written a Windows software and I have associated a file extension with this program. When I double click a data file then my program starts up and opens the file. So far it works. But when I select multiple files and then click "Open" in the context menu then multiple instances of my program are started, one instance for one file. I want Windows to open ALL files with a single instance of my program. Is this possible without implementing a one-instance-handler in my program?
Currently the MyFileType/shell/open/command in the registry looks like this:
"C:\Program Files\MyApp\MyApp.exe" "%1"
Maybe there is some special Token/Variable I have to use instead of the "%1" to get it working? On Linux I have to use %f for a single file and %F for a list of files. Is there something similar on Windows?
The simplest way is to associate your app with the default shell verb (e.g. “open,” or “play,”) for the file type, and implements a drop target that uses SHCreateShellItemArrayFromDataObject to get the selected files. Suggested reading: How the Shell Invokes Verbs
If you don't like to take over the default verb, you can add your verb to the file association's open with list.
Another method is to make your app a singleton and send the document's path to the first instance via inter-process communication methods such as DDE or RPC. This requires you to keep your main window responsive (for example, won't work if you are showing a dialog)
%* might be what you're looking for.

Resources