How to Associate a File Extension to the Current Executable in C#

Associate a file extension to an application within C# application

Seems that you haven't enough permissions for writing in the windows registry
Try to add to project app.manifest file with content:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</asmv1:assembly>

or if application have to work without requesting admin rights on each start add ability to self-elevate as shown in this example UAC self-elevation

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);

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!

Associated extension doesn't send file name to application on double click

I actually solved my own problem with the following code:

        RegistryKey command, defaultIcon, extension;
// Create Keys
command = Registry.CurrentUser.CreateSubKey(@"Software\Classes\APP NAME\shell\open\command");
defaultIcon = Registry.CurrentUser.CreateSubKey(@"Software\Classes\APP NAME\DefaultIcon");
extension = Registry.CurrentUser.CreateSubKey(@"Software\Classes\.EXTENSION");

// Create Values
command.SetValue("", "\"" + Application.ExecutablePath + "\" %1", RegistryValueKind.String);
defaultIcon.SetValue("", "ICON PATH", RegistryValueKind.String);
extension.SetValue("", "APP NAME", RegistryValueKind.String);

APP NAME is where I put the name of my application,
EXTENSION is where I put the extension I want to associate with my application, and ICON PATH is the path to the icon file which I want the associated files to have.

The %1 at the end of the ExecutablePath makes the path of the double-clicked associated file to be passed as an argument to Main method of my application.

Allow a custom file to double click and open my application while loading it's data

The answer to your question is no different for a WinForms app and a console app.

The path of the .mmi file that triggered your app will be args[0] in your app's Main method (assuming the signature Main(string[] args)).

So knowing what .mmi file was double-clicked to trigger your app will essentially come for free - after you have told Windows to open .mmi files with your app.

Here is an example - where I just used a text file Test.mmi and a simple console app ConsoleApplication1 for a PoC:

/*
* Program.cs
*/

using System;
using System.IO;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
if (args.Length > 0)
{
// Open and display the text in the double-clicked .mmi file.
Console.WriteLine(File.ReadAllText(args[0]));
}

// Pause for 5 seconds to see the double-clicked file's text.
Thread.Sleep(5000);
}
}
}

After telling Windows to open .mmi files with ConsoleApplication1.exe, ConsoleApplication1.exe displays the text in Test.mmi (Whatever....) when I double-click it:

ConsoleApplication1.exe Output

The only thing that will differ from the PoC I have offered is whatever you need do with the file path that comes in as args[0].

How to get recommended programs associated with file extension in C#

I wrote a small routine:

public IEnumerable<string> RecommendedPrograms(string ext)
{
List<string> progs = new List<string>();

string baseKey = @"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\." + ext;

using (RegistryKey rk = Registry.CurrentUser.OpenSubKey(baseKey + @"\OpenWithList"))
{
if (rk != null)
{
string mruList = (string)rk.GetValue("MRUList");
if (mruList != null)
{
foreach (char c in mruList.ToString())
progs.Add(rk.GetValue(c.ToString()).ToString());
}
}
}

using (RegistryKey rk = Registry.CurrentUser.OpenSubKey(baseKey + @"\OpenWithProgids"))
{
if (rk != null)
{
foreach (string item in rk.GetValueNames())
progs.Add(item);
}
//TO DO: Convert ProgID to ProgramName, etc.
}

return progs;
}

which gets called like so:

foreach (string prog in RecommendedPrograms("vb"))
{
MessageBox.Show(prog);
}

Open custom file with own application

When you open a file with an application, the path to that file is passed as the first command line argument.

In C#, this is args[0] of your Main method.

static void Main(string[] args)
{
if(args.Length == 1) //make sure an argument is passed
{
FileInfo file = new FileInfo(args[0]);
if(file.Exists) //make sure it's actually a file
{
//Do whatever
}
}

//...
}

WPF

In case your project is an WPF application, in your App.xaml add a Startup event handler:

<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
Startup="Application_Startup"> <!--this line added-->
<Application.Resources>

</Application.Resources>
</Application>

Your command line arguments will now be in e.Args of the Application_Startup event handler:

private void Application_Startup(object sender, StartupEventArgs e)
{
if(e.Args.Length == 1) //make sure an argument is passed
{
FileInfo file = new FileInfo(e.Args[0]);
if(file.Exists) //make sure it's actually a file
{
//Do whatever
}
}
}

c#: icon associated with file extension

you need to modify registry entries.
A code snippet how to do with c# can be found here:
http://mel-green.com/2009/04/c-set-file-type-association/



Related Topics



Leave a reply



Submit