Trovare l'applicazione predefinita per l'apertura di un determinato tipo di file su Windows

StackOverflow https://stackoverflow.com/questions/162331

  •  03-07-2019
  •  | 
  •  

Domanda

Sto sviluppando un'applicazione destinata a .NET Framework 2.0 utilizzando C # per il quale devo essere in grado di trovare l'applicazione predefinita utilizzata per aprire un determinato tipo di file.

So che, per esempio, se vuoi solo aprire un file usando quell'applicazione puoi usare qualcosa come:

System.Diagnostics.Process.Start( "C:\...\...\myfile.html" );

per aprire un documento HTML nel browser predefinito o

System.Diagnostics.Process.Start( "C:\...\...\myfile.txt" );

per aprire un file di testo nell'editor di testo predefinito.

Tuttavia, ciò che voglio poter fare è aprire i file che non hanno necessariamente un'estensione .txt (ad esempio), nell'editor di testo predefinito, quindi devo essere in grado di scoprire l'applicazione predefinita per l'apertura dei file .txt , che mi permetterà di invocarlo direttamente.

Suppongo ci sia qualche API Win32 che dovrò fare P / Invoke per fare questo, tuttavia una rapida occhiata con Google e MSDN non ha rivelato nulla di molto interessante; Ho trovato un numero molto elevato di pagine completamente irrilevanti, ma niente di simile a quello che sto cercando.

È stato utile?

Soluzione

Puoi controllare nella sezione del registro HKEY_CLASSES_ROOT per i dettagli dell'estensione e dell'azione. La documentazione per questo è su MSDN . In alternativa, puoi utilizzare l'interfaccia IQueryAssociations .

Altri suggerimenti

Tutte le risposte correnti non sono affidabili. Il registro è un dettaglio di implementazione e in effetti tale codice è rotto sul mio computer Windows 8.1. Il modo corretto per farlo è utilizzare l'API Win32, in particolare 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
}

Documentazione pertinente:

Esempio di utilizzo:

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! Certo.

HKEY_CLASSES_ROOT\.txt

include un riferimento a

HKEY_CLASSES_ROOT\txtfile

che contiene una sottochiave

HKEY_CLASSES_ROOT\txtfile\shell\open\command

che fa riferimento a Blocco note.

Ordinati, molte grazie!

Bart

Ecco un post sul blog con questo topic. Gli esempi di codice sono in VB.net, ma dovrebbe essere facile portarli su C #.

Puoi semplicemente interrogare il registro. Prima ottenere la voce predefinita in HKEY_CLASSES_ROOT \ .ext

Questo ti darà il nome della classe. Ad esempio .txt ha un valore predefinito di txtfile

Quindi apri HKEY_CLASSES_ROOT \ txtfile \ Shell \ Open \ Command

Questo ti darà il comando predefinito usato.

  

Una risposta tardiva, ma esiste un buon pacchetto NUGET che gestisce le associazioni di file: Associazione file

Link NUGET File Association

L'uso è semplice, ad esempio per aggiungere tutte le estensioni di file consentite a un menu di scelta rapida:

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());
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top