Encontrar la aplicación predeterminada para abrir un tipo de archivo particular en Windows
Pregunta
Estoy desarrollando una aplicación dirigida a .NET Framework 2.0 con C # para la cual necesito poder encontrar la aplicación predeterminada que se usa para abrir un tipo de archivo en particular.
Sé que, por ejemplo, si solo desea abrir un archivo con esa aplicación, puede usar algo como:
System.Diagnostics.Process.Start( "C:\...\...\myfile.html" );
para abrir un documento HTML en el navegador predeterminado, o
System.Diagnostics.Process.Start( "C:\...\...\myfile.txt" );
para abrir un archivo de texto en el editor de texto predeterminado.
Sin embargo, lo que quiero poder hacer es abrir archivos que no tienen necesariamente una extensión .txt (por ejemplo), en el editor de texto predeterminado, por lo que debo estar capaz de averiguar la aplicación predeterminada para abrir archivos .txt , lo que me permitirá invocarla directamente.
Supongo que hay algunas API de Win32 que necesitaré P / Invoke para hacer esto, sin embargo, un vistazo rápido tanto de Google como de MSDN no reveló nada de mucho interés; Encontré una gran cantidad de páginas completamente irrelevantes, pero no hay nada como lo que estoy buscando.
Solución
Puede consultar en la sección de registro HKEY_CLASSES_ROOT
para obtener detalles sobre la extensión y la acción. La documentación para esto es en MSDN . Alternativamente, puede usar la interfaz IQueryAssociations .
Otros consejos
Todas las respuestas actuales no son confiables. El registro es un detalle de la implementación y, de hecho, ese código está roto en mi máquina con Windows 8.1. La forma correcta de hacerlo es mediante la API de Win32, específicamente AssocQueryString :
using System.Runtime.InteropServices;
[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern uint AssocQueryString(
AssocF flags,
AssocStr str,
string pszAssoc,
string pszExtra,
[Out] StringBuilder pszOut,
ref uint pcchOut
);
[Flags]
public enum AssocF
{
None = 0,
Init_NoRemapCLSID = 0x1,
Init_ByExeName = 0x2,
Open_ByExeName = 0x2,
Init_DefaultToStar = 0x4,
Init_DefaultToFolder = 0x8,
NoUserSettings = 0x10,
NoTruncate = 0x20,
Verify = 0x40,
RemapRunDll = 0x80,
NoFixUps = 0x100,
IgnoreBaseClass = 0x200,
Init_IgnoreUnknown = 0x400,
Init_Fixed_ProgId = 0x800,
Is_Protocol = 0x1000,
Init_For_File = 0x2000
}
public enum AssocStr
{
Command = 1,
Executable,
FriendlyDocName,
FriendlyAppName,
NoOpen,
ShellNewValue,
DDECommand,
DDEIfExec,
DDEApplication,
DDETopic,
InfoTip,
QuickTip,
TileInfo,
ContentType,
DefaultIcon,
ShellExtension,
DropTarget,
DelegateExecute,
Supported_Uri_Protocols,
ProgID,
AppID,
AppPublisher,
AppIconReference,
Max
}
Documentación relevante:
Uso de muestra:
static string AssocQueryString(AssocStr association, string extension)
{
const int S_OK = 0;
const int S_FALSE = 1;
uint length = 0;
uint ret = AssocQueryString(AssocF.None, association, extension, null, null, ref length);
if (ret != S_FALSE)
{
throw new InvalidOperationException("Could not determine associated string");
}
var sb = new StringBuilder((int)length); // (length-1) will probably work too as the marshaller adds null termination
ret = AssocQueryString(AssocF.None, association, extension, null, sb, ref length);
if (ret != S_OK)
{
throw new InvalidOperationException("Could not determine associated string");
}
return sb.ToString();
}
Doh! Por supuesto.
HKEY_CLASSES_ROOT\.txt
incluye una referencia a
HKEY_CLASSES_ROOT\txtfile
que contiene una subclave
HKEY_CLASSES_ROOT\txtfile\shell\open\command
que hace referencia al Bloc de notas.
¡Ordenados, muchas gracias!
Bart
Aquí hay una publicación de blog con información sobre esto tema. Los ejemplos de código están en VB.net, pero debería ser fácil portarlos a C #.
Puedes consultar el registro. Primero obtenga la entrada predeterminada en HKEY_CLASSES_ROOT \ .ext
Eso te dará el nombre de clase. Por ejemplo .txt tiene un valor predeterminado de txtfile
Luego, abra HKEY_CLASSES_ROOT \ txtfile \ Shell \ Open \ Command
Eso te dará el comando predeterminado utilizado.
Una respuesta tardía, pero hay un buen paquete NUGET que maneja las asociaciones de archivos: Asociación de archivos
Asociación de archivos de enlace NUGET
El uso es simple, por ejemplo, para agregar todas las extensiones de archivo permitidas a un menú contextual:
private void OnMenuSourceFileOpening(object sender, ...)
{ // open a context menu with the associated files + ".txt" files
if (File.Exists(this.SelectedFileName))
{
string fileExt = Path.GetExtension(this.SelectedFileNames);
string[] allowedExtensions = new string[] { fileExt, ".txt" };
var fileAssociations = allowedExtensions
.Select(ext => new FileAssociationInfo(ext));
var progInfos = fileAssociations
.Select(fileAssoc => new ProgramAssociationInfo (fileAssoc.ProgID));
var toolstripItems = myProgInfos
.Select(proginfo => new ToolStripLabel (proginfo.Description) { Tag = proginfo });
// add also the prog info as Tag, for easy access
// when the toolstrip item is selected
// of course this can also be done in one long linq statement
// fill the context menu:
this.contextMenu1.Items.Clear();
this.contextMenuOpenSourceFile.Items.AddRange (toolstripItems.ToArray());
}
}