How to change filetype association in the registry?

first time posting in StackOverflow. :D I need my software to add a couple of things in the registry.

My program will use

Process.Start(@"blblabla.smc");

to launch a file, but the problem is that most likely the user will not have a program set as default application for the particular file extension.

How can I add file associations to the WindowsRegistry?


Solution 1:

In addition to the answers already provided, you can accomplish this by calling the command line programs "ASSOC" and "FTYPE". FTYPE associates a file type with a program. ASSOC associates a file extension with the file type specified through FTYPE. For example:

FTYPE SMCFile="C:\some_path\SMCProgram.exe" -some_option %1 %*
ASSOC .smc=SMCFile

This will make the necessary entries in the registry. For more information, type ASSOC /? or FTYPE /? at the command prompt.

Solution 2:

Use the Registry class in Microsoft.Win32.

Specifically, you want the ClassesRoot property of Registry to access the HKEY_CLASSES_ROOT key (cf. Understanding MS Windows File Associations and HKEY_CLASSES_ROOT: Core Services).

using Microsoft.Win32;
Registry
    .ClassesRoot
    .CreateSubKey(".smc")
    .SetValue("", "SMC", RegistryValueKind.String);
Registry
    .ClassesRoot
    .CreateSubKey("SMC\shell\open\command")
    .SetValue("", "SMCProcessor \"%1\"", RegistryValueKind.String);

Replace "SMCProcessor \"%1\"" with the command-line path and argument specification for the program that you wish to associate with files with extension .smc.

But, instead of messing with the registry, why not just say

Process.Start("SMCProcessor blblabla.smc");

Solution 3:

Using Python:

EXT, EXT_TYPE = ".xyz", "XYZ file"
EXE_PATH = r"path\to\my\exe"

# %L is the long (full path) version of path
extCmd = '"%s" "%%L" %%*' % EXE_PATH

# Using assoc and ftype easier than editing registry!
assert os.system('assoc %s=%s' % (EXT, EXT_TYPE))==0
assert os.system('ftype %s=%s' % (EXT_TYPE, extCmd))==0

Associating an icon with the extension type:

import _winreg

try:
    ext = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, EXT_TYPE)
    _winreg.SetValue(ext, "DefaultIcon", _winreg.REG_SZ, ICON_PATH)
    _winreg.CloseKey(ext)
except WindowsError:
    print "Error associating icon"

Register the extension as an executable type (i.e. PATHEXT):

try:
    key = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'

    reg = _winreg.ConnectRegistry( None, _winreg.HKEY_LOCAL_MACHINE )

    # get current value
    ext = _winreg.OpenKey(reg, key)
    pathext = _winreg.QueryValueEx(ext, 'PATHEXT')[0]

    if not EXT in pathext:
        _winreg.CloseKey(ext)

        # modify the current value            
        ext = _winreg.OpenKey(reg, key, 0, _winreg.KEY_ALL_ACCESS)
        pathext += ';' + EXT
        _winreg.SetValueEx(ext, 'PATHEXT', 0, _winreg.REG_SZ, pathext)
        _winreg.CloseKey(ext)

    _winreg.CloseKey(reg)

except WindowsError:
    print "Error adding to PATHEXT"

Additionally, to get PATHEXT recognised without logging in again you can update the environment: (thanks to Enthought for this)

def refreshEnvironment():        
    HWND_BROADCAST      = 0xFFFF
    WM_SETTINGCHANGE    = 0x001A
    SMTO_ABORTIFHUNG    = 0x0002
    sParam              = "Environment"

    import win32gui
    res1, res2          = win32gui.SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, sParam, SMTO_ABORTIFHUNG, 100)

Solution 4:

If you are planning on providing an installer for your application, simply use the file association feature available in whatever installer framework you choose to use - even the Visual Studio setup project knows how to do this.

To alter file type associations directly from your code, I believe you have to look into HKEY_CLASSES_ROOT and find/create a key with the extension you want to bind to (ie ".pdf"). Within this key, the default value is a string containing a reference to another key within HKEY_CLASSES_ROOT. Go follow that pointer, expand/create the shell subkey and add/change your commands here. Look around this area with regedit to get the fealing of how it looks.

I have some C# code in a pet project of mine, which looks up the binding for PDF files and adds an extra option to their context menus. Feel free to have a look.