Need to write a shell extension - windows-shell

I need to write a shell extension for a small context menu.
unfortunately i reused the code available in open source which uses .net 4.0
now the problem is the requirement is I shud not use .NET 4.0.
Instead is there a way where in I can make an entry in the registry so that the shell extension pops out
My requirement is ....
1. The shell extension context menu should display only on .txt, .csv, .xls files.
2. Upon click of shell extension I need to start a different process, by passing the full name of the file on which we click as parameter to the process.

If you just want to add items to the context menu for certain file types, and in response launch an external application, you don't need to write a shell extension. Registry entries are enough to express this.
As the http://www.jfitz.com/tips/rclick_custom.html article you linked to says, for each file type you want to act on, you need to add a new registry key under the Shell subkey, then create a subkey called command, whose value is the name of the application to launch.
To pass the name of the file you clicked on to this external application, add "%1" to the command. Include the quotes, so that if the file's name contains spaces, it will still be treated as one token by the receiving program.

Related

Opening a file **in** a batch file

I have a batch program that can be used for opening a specific file format I created. The file format is a actually a zip file with the .zip changed to .gcif.
When you run my btch file there is an input field for entering the location of the .gcif file you want to open. The .gcif is then renamed to .zip. The 7z.exe (which is in the same directory as the batch file) then unzips the file and it is processed by my batch file.
But I would like it to also work when the user finds any .gcif file, right clicks it, and selects Open With my batch file. Is there any way for batch file to detect that ithas been tasked to open that specific file?
I figured it out. When a file is opened with a batch file, the file location is passed on to the batch file as a parameter. The parameter can then be accessed using %1.
For example, if I opened the file C:/document.txt in a batch file containing this code:
#ECHO OFF
ECHO %1
The output would display C:/document.txt.
You can register a windows file handler in your system.
You might need admin rights and might need to modify the registry.
Essentially you "connect" your filextension .gcif with your batch file so windows knows that any file of this extension is connected to your batchfile
You can read something about it on the msdn site here: How to Register a File Type for a New Application
If you plan to associate one or more file types with a new
application, you must define a ProgID for each file type that you want
to associate with the application.
To create a ProgID for each unique file type that your application
handles, use these steps.
Instructions
Step 1: Note that some file types have multiple
extensions that point to the same ProgID; for example:
HKEY_CLASSES_ROOT\App.jpeg (your ProgID)
HKEY_CLASSES_ROOT\.jpg = App.jpeg (the file type mappings)
HKEY_CLASSES_ROOT\.jpeg = App.jpeg
Step 2:
Remove the ProgID values when you install and uninstall your
program.
Step 3:
Leave the file type mappings unchanged at uninstall time.
Doing so works because file type mappings are stored per user in
HKEY_CLASSES_ROOT.ext, and the system identifies the case where the
ProgID value is missing and ignores it. Leaving file type mappings
unchanged avoids the need to have conditional code that only removes
the file type mapping if the value still points to your ProgID. It is
important to avoid doing so in cases where it might have been changed
by another application and you thus cannot easily remove the value.
Step 4:
Specify a unique value for the file type description of each
file type ProgID by doing one of the following:
Leave the default value of the ProgID empty, in which case the system
uses the .ext file. Provide a localized value via FriendlyTypeName
and, for compatibility with old applications that read the registry
directly, be sure to provide the default value of the ProgID as the
file type description (that is, use the same value that is referred to
by the FriendlyTypeName in the English resource). Remarks If you plan
to associate the file with an existing application, locate an
application ProgID in the registry.
To accomplish something similar you can open your file once with Explorer and chose "Open with..." - locate your batch file and choose "always open with this application" checkbox.
The first option here is more for when you want to provide 1-click-open experience to customers for your application when they install it on their system.

Trying to 'emulate' a document folder

I am a 3rd party, and I would like to start an 1st party application and virtualize somehow a document folder that I would decide the location.
The first application would not touch the real 'my document' folder but instead save the file in a location I would set.
I don't want to change the registry entries for the personal folders, I want it just for this application.
I did some research but didn't find anything like that. Is that possible without a virtual machine? I would try to work in VB6, I want to test something on xp and win7. It's about a game redesign, and I would like the person to be able to have my program, and the original game installed on the PC without the configuration folders in 'my document' colliding.
I should mention that I cannot pass parameters to it because I am launching the 1st party application through a 2nd party executable already.
Thank you!
Yanick
Of course you can, with a text file (or a program). MS made it easy.
Here is someone quoting my post, who is quoting Raymond Chen directly,
http://www.pcreview.co.uk/threads/re-create-system-folder.522854/
Creating Shell Extensions with Shell Instance Objects
Raymond Chen
Microsoft Corporation
February 2000
Summary: A traditional shell namespace extension requires the implementation
of a COM in-process server. Shell instance objects allow you to create
simple shell extensions without having to write a single line of code. This
article describes how shell instance objects and shell command objects can
be used to easily deploy simple shell extensions. (5 printed pages)
Contents
What Is a Shell Namespace Extension?
What Is a Shell Instance Object?
Shell Objects That Can Be Created as Shell Instance Objects
How About an Example?
Shell Command Objects
Conclusion
What Is a Shell Namespace Extension?
Shell namespace extensions allow you to create "virtual folders" in the
shell. For example, the Recycle Bin icon on the desktop is not an actual
file system directory, but rather represents a collection of items that is
maintained by the Recycle Bin shell extension.
Details on creating shell namespace extensions can be found in the Platform
SDK section of the MSDN Online Library
(http://msdn.microsoft.com/library/psdk/shellcc/shell/shell_adv/namespace.ht
m).
Writing a shell namespace extension can be quite an ordeal. Fortunately, the
shell provides an easy way to create certain types of simple shell namespace
extensions, as this article will show.
What Is a Shell Instance Object?
A shell instance object is a special kind of shell extension provided by the
shdocvw.dll component. Whereas a traditional shell extension requires a DLL
to implement the object, a shell instance object retrieves everything it
needs to know from the registry.
How the shell creates a shell instance object
1.. The shdocvw.dll component is loaded by virtue of being registered as
the InProcServer32 for the shell instance object.
2.. When shdocvw.dll is asked to create an object it does not otherwise
recognize, it checks the registry key for a subkey named Instance. If found,
it reads the CLSID value of that subkey and passes that CLSID to the
CoCreateInstance function. (For lack of a better term, let's call this the
"host" object.)
3.. Next, shdocvw.dll looks for a subkey of Instance named InitPropertyBag
or InitStream. If found, it then creates an IPropertyBag or IStream
(accordingly) based on the contents of the registry key and passes it to the
IPersistPropertyBag::Load or IPersistStream::Load method (accordingly).
4.. Finally, shdocvw.dll returns the now-initialized host object as the
shell instance object.
Shell Objects That Can Be Created as Shell Instance Objects
There are two shell objects that support being the host object of a shell
instance object, namely the Shell link object and the Shell folder shortcut
object.
Both of these objects support the IPersistPropertyBag interface, so you can
use the InitPropertyBag method of initializing them. (It so happens that
both objects also support IPersistStream, but initializing a shortcut from a
registry stream is much more cumbersome.)
The property bag you provide in the registry describes the target of the
shell link or shell folder shortcut object. There are three supported forms
for this property bag.
Targeting a shell special folder
InitPropertyBag
TargetSpecialFolder=REG_SZ:"<special folder number>"
Notice that this is a REG_SZ registry value even though it represents an
integer. Both decimal and hex notation are supported.
Targeting a directory inside a shell special folder
InitPropertyBag
TargetSpecialFolder=REG_SZ:"<special folder number>"
Target=REG_SZ:"<subdirectory name>"
The subdirectory name can contain embedded backslashes.
Targeting a directory by explicit path
InitPropertyBag
Target=REG_SZ:"<full path to target directory>"
How About an Example?
Here's a copy of the registration that creates the Fonts folder icon in
Control Panel:
HKEY_CLASSES_ROOT
CLSID
{D20EA4E1-3957-11D2-A40B-0C5020524152}=REG_SZ:"Fonts"
InfoTip=REG_SZ:"Displays and manages fonts on your computer"
DefaultIcon=REG_EXPAND_SZ:"%SystemRoot%\system32\main.cpl,9"
InProcServer32=REG_EXPAND_SZ:"%SystemRoot%\system32\shdocvw.dll"
ThreadingModel=REG_SZ:"Apartment"
ShellFolder
Attributes=REG_DWORD:0x60000000
WantsFORPARSING=REG_SZ:""
Instance
CLSID=REG_SZ:"{0AFACED1-E828-11D1-9187-B532F1E9575D}"
InitPropertyBag
TargetSpecialFolder=REG_SZ:"0x0024"
Target=REG_SZ:"Fonts"
Because {D20EA4E1-3957-11D2-A40B-0C5020524152} is registered in the Control
Panel namespace, a Fonts folder shortcut is installed in Control Panel.
Let's go through this registry key step by step.
a.. The GUID {D20EA4E1-3957-11D2-A40B-0C5020524152} was generated by
running the uuidgen program found in the Platform SDK. Of course, when you
create your own instance objects, you should run uuidgen and use your own
GUID. The name of the icon as it appears in the namespace is also provided
here.
b.. The optional InfoTip string is displayed when the user hovers over the
icon.
c.. The DefaultIcon string provides the name and icon index for the icon
to display for this item.
d.. The InProcServer32 key must be set to the shdocvw.dll file, and the
threading model must be set to Apartment.
e.. The ShellFolder key sets the Attributes to a collection of SFGAO_
values, which we wish to apply to the folder shortcut. The SFGAO_FOLDER flag
must always be set. Because the target is a file system folder, the
SFGAO_FILESYSTEM flag is also set in the Attributes, and the WantsFORPARSING
value is set to an empty string. (If the target is not a file system folder,
the WantsFORPARSING value should not be created.)
f.. The Instance key sets the CLSID value to the string representation of
CLSID_FolderShortcut. This indicates that the object instance should create
a folder shortcut.
g.. The InitPropertyBag key indicates that the folder shortcut will be
initialized with the IPersistPropertyBag interface. The two values inside
the property bag specify that the target is the subdirectory "Fonts" in the
special folder 0x0024, which is CSIDL_WINDOWS.
Shell Command Objects
Another type of shell extension object is an icon that when double-clicked
runs a command. This, too, can be created without having to write a COM
server. For example, here is a command object that is used by the My Network
Places folder:
HKEY_CLASSES_ROOT
CLSID
{D4480A50-BA28-11d1-8E75-00C04FA31A86}=REG_SZ:"Add Network Place"
InfoTip=REG_SZ:"Connects to shared folders, Web folders, and FTP
sites."
DefaultIcon=REG_EXPAND_SZ:"%SystemRoot%\System32\netplwiz.dll,-107"
ShellFolder
Attributes=REG_DWORD:0x00000000
Shell
Open
Command=REG_EXPAND_SZ:"rundll32 ..."
Most of this registry key should look familiar, so I will only highlight the
differences from shell instance objects:
a.. There is no InProcServer32 key.
b.. The Attributes of the ShellFolder key should omit the SFGAO_FOLDER
flag because this item is not a folder.
c.. Instead of an Instance key, we have a Shell key, which has the same
structure as a progid key. The "Open" verb is the default action for
double-clicking. You can also create other verbs, which will appear on the
context menu. For example, the Internet Explorer icon creates a custom verb
called "Open Home Page."
Details on the structure of the Shell key can be found in the Platform SDK
section of the MSDN Online Library under the topic heading "Extending
Context Menus"
(http://msdn.microsoft.com/library/psdk/shellcc/shell/shell_basics/context.h
tm).
Conclusion
Shell instance objects and shell command objects allow you to deploy simple
shell extensions with a minimum amount of work. For example, you might
create a command object in the Control Panel folder called "Troubleshoot,"
which runs a troubleshoot program. Or you might create a shell instance
object that hosts a folder shortcut to a collection of system administrative
tools on a shared network server. Shell instance objects and shell command
objects allow you to easily deploy these types of shell extensions.
My solution was to search the executable with a hex editor and manually edit it to another folder. Of course I had to choose a folder with less or equal number or character in the path.
Thank you all.

Add a Windows Shell context menu entry for a specific extension (not file type)

To add a Windows shell context menu, let's say for .txt files - if the .txt extension in HKEY_CLASSES_ROOT (or in HKEY_CURRENT_USER\Software\Classes, doesn't really matter) has the default value (file type) txtfile - you add the command to HKEY_CLASSES_ROOT\txtfile\shell\yourcommand (and the command itself in HKEY_CLASSES_ROOT\txtfile\shell\yourcommand\command, of course) and there you go.
However, let's say the .txt extension instead has the default value Notepad++_file. Notepad++_file might be the file type for many other extensions, so if you add the command to HKEY_CLASSES_ROOT\Notepad++_file, then this command will appear for every extension associated with Notepad++.
So, the question is: how can you add a menu entry for ONLY ONE specific EXTENSION, without changing its file type, if possible at all?
P.S.: I don't want to just duplicate the file type, because future changes to the original file type won't affect the duplicated one.
Here you go:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\*\shell\your custom app]
#="Open with your custom app"
"icon"="C:\\Windows\\notepad.exe,0"
"AppliesTo"=".nfo"
[HKEY_CLASSES_ROOT\*\shell\your custom app\command]
#="C:\\Windows\\notepad.exe \"%1\""
The line "AppliesTo"=".nfo" does the trick.
Works perfectly on Windows 10.
It works per file extension, regardless if there is an application associated with that extension or not. Doing this way it less invasive and leaves a very small footprint in the registry.
Compare to Add menu item to windows context menu only for specific filetype
Edit:
If you want to apply that command to more than one extension use:
"AppliesTo"="System.FileName:\"*.nfo\" OR System.FileName:\"*.log\""
Credit: https://superuser.com/questions/183785/windows-7-context-menu-for-folders-if-folder-contains-certain-filetypes

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.

How to set an application as the default program of opening a certain type of file programmatically?

There's an executable file generated from my program in MFC and I want to use it as the default program to open the .jpg files. That is to say, each time I double click a .jpg file, my program will run.
I tried to add some registry entries linking .jpg files with my program, such as HKEY_CLASSES_ROOT\.jpg\shell\open\command (set its value to "myProgram.exe" "%1"), and HKEY_CLASSES_ROOT\myProgram.
The method works just fine except when some other applications register themselves to open the .jpg files. For example, I have installed acdSee on my computer, so each time I doule click a .jpg file, it always start acdSee instead of my own program. But when I register a completely new type of file with my program, it can be open in the program. I don't know how to set my program as the default opening program of an already registered file programmatically. Can anyone help me solve this problem? Thank you very much!
The more typical/standard way for doing this is to set the default value of the ".jpg" key to a name that identifies the file type more clearly, and then setup the various associated actions there. So for jpgs, you might do this:
HKCR\.jpg
#default = MyApp.JpegImage
HKCR\MyApp.JpegImage\shell\open\command
#default = "myApp.exe "%1""
If some other program decides to register the type, they will replace the default value for HKCR.jpg with some other value, like OtherProgram.Jpg. At that point, you could re-register it to your app by setting the value back to MyApp.JpegImage.
Disclaimer: When making this sort of change, please also try to respect the user's preferences. For instance, when installing your application, give the user the option to set this file association or not set it. You can also provide a command from inside your installed application to reset the associations, if the user should wish to do so.
If you instead wanted to add some additional commands to an existing registered type, you would read the default value of the .jpg key to find the name of the file type. Then you could open that key and add an action to the existing set of actions. For instance, you could add the following:
HKCR\ExistingApp.JpegImage\shell\myopen\
#default = "Open with MyApp"
HKCR\ExistingApp.JpegImage\shell\myopen\command\
#default = "myApp.exe "%1""
Note that by writing a key to HKCR, you're actually writing to HKLM\Software\Classes. This will require administrative privileges. However, you can make per-user changes within a user context by writing your keys to HKCU\Classes\Root instead.
Also, user preferences in HKCU will override the system defaults in HKLM, which sounds like what your problem might be.
This is when a program has not registered an extension as a "Default" (Is the program listed in Set Programs and Defaults in the Control Panel?)
Time to start reading documentation!

Resources