CustomFileExtension is a control that helps you define a file extension for your custom file types. This component is not visible on a form, but below it.
What is a file association?
File association is a set of Registry keys that determine how your new file type will behave, what icon it is going to have and with what application it is going to be run. This can be done without the
CustomFileExtension control as well, but this way is easier and faster than writing code yourself every time.
It is all about creating the Registry keys in the right place.
Here is some theoretical explanation:
Inside HKEY_CLASSES_ROOT, you need to create a new key with the name of the desired extension. E.g. '.cp' (without the quotes). In the data field of the newly created key, enter MyApplication, which is going to be like a reference to that extension inside the Registry.
Still inside HKEY_CLASSES_ROOT, add a new key with the name of the reference, which is MyApplication. In the data field of this key, you can enter some text which is going to be a description of that file type in Explorer. To have an icon, we need to add a subkey inside our MyApplication key, called DefaultIcon. The data field of the DefaultIcon subkey is going to be the path to the icon you want your file type to have. Enclose the icon path like this: "icon_path". You can also have an icon that is inside the resource of the Exe or DLL file, like this:
where x is the index of the icon inside the resource.
Finally, we need to specify the path to the application so that the application can open your file type.
Inside the MyApplication key, create another subkey called shell. Inside the shell subkey, create another subkey called open. In the data field of the open subkey, enter some text that will be displayed in the context menu when you right click the file with your .cp extension.
And lastly, create another subkey inside the open subkey, called command. In the command subkey, we can set the full path to the application .exe so the file type is connected to the application like so:
%1 acts like an argument variable so if we double click on a file with a .cp extension, we will pass the full path to that clicked file so we can open it inside our application.
The Registry should look something like this:
There is an option to specify an application to open your custom format. For example, you can edit a .html file in Notepad, but in Visual Studio as well. The same functionality you can have for your own application, using this control.
The theory behind this is just adding the OpenWithProgids subkey of the extension key, and inside the OpenWithProgids subkey, start adding string values of handlers to reference different applications.
After that, you need to create a key that matches each handler on the same level as your extension. Each of those keys must have a subkey shell. Then, shell must have a subkey open, and open must have a subkey command. Inside the command subkey, you need to enter the full path to other applications, with %1 at the end.
When you use the
RegisterFileTypes() method, the control will assign the association for the selected extension, and if you have selected applications,
OpenWithProgids will be filled.
Open files in the same application instance
You can also make your program to open files in already running applications instead of running a new instance of the application. Communication is between the processes, and is sent with the
SendMessage Windows API.
No Registry messing around this time.
Two new methods are added:
SendFilePath which has the
args parameter to be passed and checks for the application instances, prepare the file paths, and then sends the file paths to the running application if the application is running. The method returns
true if there is more than one instance of the application.
GetData is another method that is used on the receiving end. Takes a data argument type of
string and returns an array of file paths.
Enough about the theory and the conspiracy theory. Let's see the code.
The source code is pretty simple. We are taking advantage of the
Registry class. So you need to add a
About the code.
Registry.SetValue("HKEY_CLASSES_ROOT\.cp", "", "MyApplication");
Registry.SetValue("HKEY_CLASSES_ROOT\MyApplication", "", "Some description");
"", "Application_Path", "Icon_Position");
Registry.SetValue("HKEY_CLASSES_ROOT\MyApplication\DefaultIcon", "", "Icon_Path");
Registry.SetValue("HKEY_CLASSES_ROOT\MyApplication\shell", "", "");
Registry.SetValue("HKEY_CLASSES_ROOT\MyApplication\shell\open", "", "Open me");
"", "Application_Path" ""%1""");
After executing this code, you need to inform Explorer about the changes. I am not sure if there's an equivalent function in .NET for this, but you can use PInvoke to call the
SHChangeNotify function, that will inform the Explorer about the change. You can call the function with
DllImport, but first, add another
and the required enums which can be found here [^] and here [^].
And after we add the association, all we need is to remove the association.
We have explained this option, but let us see the code for it.
for (int i = 0; i < openWith.Count; i++)
string app = openWith[i].AppPath;
string originalApp = app;
app = app.Substring(app.LastIndexOf("\\") + 1);
app = app.Substring(0, app.LastIndexOf('.'));
string runHandler = "CustomFileExtension." + app + ".Run.Handler";
Registry.ClassesRoot.CreateSubKey(ext + "\\OpenWithProgids");
Registry.SetValue(HKCR + ext + "\\OpenWithProgids", runHandler, "");
Registry.SetValue(HKCR + runHandler, "", "");
Registry.SetValue(HKCR + runHandler + "\\shell", "", "");
Registry.SetValue(HKCR + runHandler + "\\shell\\open", "", "");
Registry.SetValue(HKCR + runHandler + "\\shell\\open\\command", "", "\"" +
originalApp + @""" ""%1""");
This code is in the
RegisterFileType() method. When you register a new extension you have selected, the application will be added to the Open with dialog.
When you call the
RemoveFileType() method, it will delete all the used handlers for the Open with dialog.
Open files in the same application instance
All we have to do in the
SendFilePath method is to combine the file paths, list the current running process, and send the message.
Process proc = Process.GetCurrentProcess();
Process processes = Process.GetProcessesByName(proc.ProcessName);
if (processes.Length == 0)
string message = "";
for (int i = 0; i < args.Length; i++)
message += args[i] + ";";
byte data = Encoding.Default.GetBytes(message);
int dataLen = data.Length;
cds.dwData = (IntPtr)100;
cds.lpData = message;
cds.cbData = dataLen + 1;
if (processes.Length > 1)
foreach (Process p in processes)
if (p.Id != proc.Id)
SendMessage(p.MainWindowHandle, WM_COPYDATA, 0, ref cds);
In your application, you are using this method like this:
CustomFileExtensionControl.CustomFileExtension ctf =
So when the application is already running, we are passing the arguments to the running application. In your application, you also need to add a
WndProc event which will be called when the control sends the message.
protected override void WndProc(ref Message message)
if (message.Msg == WM_COPYDATA)
COPYDATASTRUCT mystr = (COPYDATASTRUCT)message.GetLParam(typeof(COPYDATASTRUCT));
Type mytype = mystr.GetType();
mystr = (COPYDATASTRUCT)message.GetLParam(mytype);
string  args = customFileExtension1.GetData(mystr.lpData);
We can see here the use of the
GetData method which will enable the
OpenFile function to read the files.
Thanks to scosta_FST for asking a question about opening files in running applications.
Setting up this control is pretty straightforward. After you've dragged a component onto a form, select it and set the properties. Here is an explanations of the available properties:
This is the final application file name along with the extension (.exe). E.g. MyApplication.exe must match with the actual application name.
This will be displayed in Explorer when you select the list view on Tiles. It'll show the description, e.g., CP's File.
If set to
true, the icon is used from inside the .exe file in the resource, and then you have to set the
IconPosition as well to select the right icon in the resource.
This is the actual extension of your custom file type which will be used to open that file with your application (
This is used to connect the extension key in the Registry with the corresponding key, to open the extension file name with your application.
IconName is the name of your icon along with the extension (.ico) that you want your file type to have. E.g., MyIcon.ico.
This is the position of your icons inside the Exe's resource file (or .dll). 0 being the first icon, 1 second, and so on.
Set this property to have a custom text when you open a context menu by right clicking your custom file type. It is the default action which is the same as double clicking the file.
This is a collection of file paths to the applications that have to appear in the Open with dialog.
Using this control is pretty straightforward. To add the component to a form, right click on the Toolbar and select Choose items... A dialog will open, click on Browse, and find the .dll file and click OK. Now you can drag and drop the component to the form. Select the control and set the properties, and then you can associate a file type with the
RegisterFileType() function, and use
RemoveFileType() to remove the association. Like so:
And that's all there is to it.
- 26.03.2010 - First initial version.
- 08.04.2010 - Added Open with capabilities.
- 20.04.2010 - Can now open files in a running application instance.
Visual C#/ASP.NET programmer.
Started with Visual Basic 6 around 2001 and since 2003/4 switched to .NET (C#).