Create Registry Entry to Associate File Extension With Application in C++

Create registry entry to associate file extension with application in C++

Your basic overview of the process is found in this MSDN article. The key parts are at the bottom of the list:

  • Register the ProgID

A ProgID (essentially, the file type registry key) is what contains your important file type properties, such as icon, description, and context menu items including applications used when the file is double clicked. Many extensions may have the same file type. That mapping is done in the next step:

  • Register the file name extension for the file type

Here, you set a registry value for your extension, setting that extension's file type to the ProgID you created in the previous step.

The minimum amount of work required to get a file to open with your application is setting/creating two registry keys. In this example .reg file, I create a file type (blergcorp.blergapp.v1) and associate a file extension (.blerg) with it.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command]
@="c:\path\to\app.exe \"%1\""
[HKEY_CURRENT_USER\Software\Classes\.blerg]
@="blergcorp.blergapp.v1"

Now, you probably want to accomplish this programmatically. To be absolutely kosher, you could check for the existence of these keys, and change your program behavior accordingly, especially if you're assuming control of some common file extension. However, the goal can be accomplished by setting those two keys using the SetValue function.

I'm not positive of the exact C++ syntax, but in C# the syntax looks something like this:

Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command", null, @"c:\path\to\app.exe \"%1\"");
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\.blerg", null, "blergcorp.blergapp.v1");

Of course you could manually open each sub key, manually create the ProgID and extension subkey, and then set the key value, but a nice thing about the SetValue function is that if the keys or values don't exist, they will automatically be created. Very handy.

Now, a quick word about which hive to use. Many file association examples online, including ones on MSDN, show these keys being set in HKEY_CLASSES_ROOT. I don't recommend doing this. That hive is a merged, virtual view of HKEY_LOCAL_MACHINE\Software\Classes (the system defaults) and HKEY_CURRENT_USER\Software\Classes (the per-user settings), and writes to any subkey in the hive are redirected to the same key in HKEY_LOCAL_MACHINE\Software\Classes. Now, there's no direct problem doing this, but you may run into this issue: If you write to HKCR (redirected to HKLM), and the user has specified the same keys with different values in HKCU, the HKCU values will take precedence. Therefore, your writes will succeed but you won't see any change, because HKEY_CURRENT_USER settings take precedence over HKEY_LOCAL_MACHINE settings.

Therefore, you should take this into consideration when designing your application. Now, on the flip side, you can write to only HKEY_CURRENT_USER, as my examples here show. However, that file association setting will only be loaded for the current user, and if your application has been installed for all users, your application won't launch when that other user opens the file in Windows.

That should be a decent primer for what you want to do. For further reading I suggest

  • Best Practices for File Association
  • File Types and File Association, especially
  • How File Associations Work

And see also my similar answer to a similar question:

  • Associating file extensions with a program

How to associate a file extension to a program without making it the default program

Setting the following keys worked for me:

key HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/App Paths/<progname>: "" = <appPath>

key HKCR/Applications/<progname>/SupportedTypes: <fileExt> = ""
key HKCR/<fileExt>: "" = <progID>

key HKCR/<progID>/OpenWithList/<progName>
key HKCR/<fileExt>/OpenWithList/<progName>
key HKCR/SystemFileAssociations/<fileExt>/OpenWithList/<progName>

delete key and subkey at HKCU/SOFTWARE/Microsoft/Windows/CurrentVersion/Explorer/fileExts/<fileExt>

Associate file types with my application C#

Found the answer:
For that I created a faulty file type and associated it to my program.

Then I searched the registry for changes and copied the pathes of those changes.


The code is here and I would like to here if anyone has a better answer.


`
public static void SetAssociation(string Extension, string KeyName, string OpenWith, string FileDescription)
{
RegistryKey OpenMethod;
RegistryKey FileExts;

//HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.avi\UserChoice -->"Progid" "Applications\YEPlayer.exe"
OpenMethod = Registry.CurrentUser.OpenSubKey(@"Software\Classes\Applications\", true);
OpenMethod.CreateSubKey(KeyName + @".exe\shell\open\command").SetValue("",'"'+OpenWith+'"'+ " "+ '"'+"%1"+'"');

FileExts = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\", true);
foreach (string child in FileExts.OpenSubKey(Extension).GetSubKeyNames())
{
FileExts.OpenSubKey(Extension,true).DeleteSubKey(child);
}
FileExts.CreateSubKey(Extension + @"\UserChoice").SetValue("Progid", @"Applications\" + KeyName +".exe");
}

'


Thanks alot!

Create Associativity between file extension & application?

For Windows see the MSDN page "File Type Handlers" for how to register file type handlers.

On many popular Linux desktops, so-called .desktop files are used to define what application to use for opening a file. See the "Desktop Entry Specification" for the structure of those .desktop files. They are quite simple really, changes are you can just take an existing file from any of the popular Linux desktop environments (e.g. KDE) and modify it a bit.

Associate File Extension with Application

The answer was a lot simpler than I expected. Windows Explorer has its own override for the open with application, and I was trying to modify it in the last lines of code. If you just delete the Explorer override, then the file association will work.

I also told explorer that I had changed a file association by calling the unmanaged function SHChangeNotify() using P/Invoke

public static void SetAssociation(string Extension, string KeyName, string OpenWith, string FileDescription)
{
// The stuff that was above here is basically the same

// Delete the key instead of trying to change it
var CurrentUser = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\" + Extension, true);
CurrentUser.DeleteSubKey("UserChoice", false);
CurrentUser.Close();

// Tell explorer the file association has been changed
SHChangeNotify(0x08000000, 0x0000, IntPtr.Zero, IntPtr.Zero);
}

[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);

How can I set a file association from a custom file type to a program

Basically you have to do this -

In registry add these keys

[HKEY_CURRENT_USER\Software\Classes\dekEditor\shell\open\command]<br/>
@="c:\path\to\app.exe \"%1\""<br/>
[HKEY_CURRENT_USER\Software\Classes\.dek]<br/>
@="dekEditor"<br/>

This is a 2 step task.First you associate your extension .dek with dekEditor (2nd entry) and then specify it in Classes(1st entry).

Answer taken from: Create registry entry to associate file extension with application in C++

MSDN Article.

How Open a user-defined extension file in Program?

by Borland C2006 you mean Embarcadero BDS2006 Turbo(explorer) C++?

  1. File associations are stored somewhere in registry

    See Create registry entry to associate file extension with application in C++. So you can create reg file or add registry entries programaticaly by WinAPI.

    I never updated registry in my apps but this is example of how you can read registry (obtaining CPU frequency):

    double getregfcpu()
    {
    DWORD keyhnd;
    HKEY hKey=NULL;
    DWORD dwSize;
    DWORD dwFrequency;
    double f=0.0;
    for(;;)
    {
    keyhnd=RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0",0,KEY_QUERY_VALUE,&hKey);
    if (keyhnd!=ERROR_SUCCESS) break;
    dwSize = sizeof(dwFrequency);
    keyhnd = RegQueryValueEx (hKey,"~MHz",NULL,NULL,(LPBYTE)&dwFrequency,&dwSize );
    if (keyhnd!=ERROR_SUCCESS) break;
    f=dwFrequency; f*=1e6;
    break;
    }
    if (hKey!=NULL) RegCloseKey(hKey);
    return f;
    }

    so experiment/use RegCreateKeyEx instead of RegOpenKeyEx. Strongly recommend to experiment first on some own registry entry not related to windows so you do not mess something up. And only when working as should change the entry name to desired location.

  2. Application side

    Go to your App source file (the one that opens when you open project in IDE). Find there WinMain function and change it like this:

    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdl, int)
    {
    try
    {
    Application->Initialize();
    Application->Tag=(int)cmdl; // *** ADD THIS LINE ***
    Application->CreateForm(__classid(TMain), &Main);
    Application->Run();
    }
    catch (Exception &exception)
    {
    Application->ShowException(&exception);
    }
    catch (...)
    {
    try
    {
    throw Exception("");
    }
    catch (Exception &exception)
    {
    Application->ShowException(&exception);
    }
    }
    return 0;
    }

    The cmdl holds the pointer to the command line with which your application was called. So copy it to your Application->Tag which is intend for any user defined behavior. This way the cmdl is accessible from whole project (in any window/form). Now to extract the file to open you just do in your Form constructor something like this:

    AnsiString cmdl=(LPSTR)Application->Tag;    // access the command line parameters
    if (cmdl.Length()>2) // file is encapsulated with ""
    if (cmdl[1]=='"')
    if (cmdl[cmdl.Length()]=='"')
    {
    AnsiString s="";
    for (int i=2;i<cmdl.Length();i++) s+=cmdl[i]; // cut of the ""
    // here load file: s
    }

    If you want to have more command line options then you need to upgrade this a bit by searching for the "" first and process all the command line switches ... Sometimes it is useful to use Application exe local path. You can get it like this:

    AnsiString exepath=ExtractFilePath(Application->ExeName);

Set registry to control working dir when associating file-type with application

Even if there is a way to have a different working directory for your application specified in the registry - you should really fix this in the application. The reason is that there are multiple ways to open a data file with your application, and you simply can't fix it for all of them. Consider

D:\> c:\Programs\MyApp\MyApp.exe \\public\foo\data.ext

where a program is started with the name of the file (as UNC path) to open as a parameter, executed in a completely different directory. I do stuff like that regularly, and I expect applications to work under these circumstances.

Note that setting the working directory to the application root path first thing after start isn't a good idea either, as then relative paths will be wrong. A proper solution means changing the application in a way that it works correctly from whatever the current working directory happens to be, by using fully qualified paths internally.

Edit:

You comment

But then this means my app is totally dependent on the registry. Which is a pain for development testing, if every time I run my dev build it goes and loads all the files for the installed version

but that isn't necessarily so. You can read the path to the currently running executable, by using the GetModuleFileName() function or its equivalent wrapper in the GUI library (like Application.ExeName in Delphi). Setting the working directory from that path is easy, I just don't think it is a good idea, as changing the working directory breaks relative paths the user may expect to work. It isn't really true that

Windows runs the EXE from the location of the file you double-click. This seems to be the exceptional case, in other cases the EXE always runs from where I expect.

because there can be many ways how the application can be executed with a different working directory than the path to the executable itself. A well-behaved program doesn't make the assumption that these are equal. It makes using the application in scripts or from the command line so much harder.



Related Topics



Leave a reply



Submit