it-swarm-id.com

Cara mengaitkan ekstensi file ke executable saat ini di C #

Saya ingin mengaitkan ekstensi file ke executable saat ini di C # . Dengan cara ini ketika pengguna mengklik file setelahnya di Explorer, itu akan menjalankan executable saya dengan file yang diberikan sebagai argumen pertama .Ideally itu juga akan mengatur ikon untuk ekstensi file yang diberikan ke ikon untuk dieksekusi . Terima kasih semua.

51
Chris

Tampaknya tidak ada .Net API untuk mengelola asosiasi file secara langsung tetapi Anda dapat menggunakan kelas Registry untuk membaca dan menulis kunci yang Anda perlukan.

Anda harus membuat kunci di bawah HKEY_CLASSES_ROOT dengan nama yang disetel ke ekstensi file Anda (misalnya: ".txt"). Tetapkan nilai default kunci ini ke nama unik untuk jenis file Anda, seperti "Acme.TextFile". Kemudian buat kunci lain di bawah HKEY_CLASSES_ROOT dengan nama diatur ke "Acme.TextFile". Tambahkan subkunci yang disebut "DefaultIcon" dan setel nilai default kunci ke file yang berisi ikon yang ingin Anda gunakan untuk jenis file ini. Tambahkan saudara lain yang disebut "Shell". Di bawah tombol "Shell", tambahkan kunci untuk setiap tindakan yang Anda inginkan tersedia melalui menu konteks Explorer, atur nilai default untuk setiap kunci ke jalur ke executable Anda diikuti dengan spasi dan "% 1" untuk mewakili jalur ke file yang dipilih.

Misalnya, berikut ini contoh file registri untuk membuat hubungan antara file .txt dan EmEditor:

 Windows Registry Editor Versi 5.00 

 [HKEY_CLASSES_ROOT\.txt] 
 @ = "Emeditor.txt" 

 [HKEY_CLASSES_ROOT\emeditor.txt] 
 @ = "Teks Dokumen "

 [HKEY_CLASSES_ROOT\emeditor.txt\DefaultIcon] 
 @ ="% SystemRoot% \\ SysWow64 \\ imageres.dll, -102 "

 [HKEY_CLASSES_ROOT\emeditor.txt\Shell] 

 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\open] 
.__ [HKEY_CLASSES_ROOT\emeditor.txt\Shell\open\command] 
 @ = "\" C:\\ Program Files \\ EmEditor \\ EMEDITOR.EXE\"\"% 1\"" 

 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\print] 

 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\print\command] 
 @ = "\" C: \\ Program Files \\ EmEditor \\ EMEDITOR.EXE\"/ p \"% 1\"" 
40
X-Cubed

Juga, jika Anda memutuskan untuk menggunakan cara registri, perlu diingat bahwa asosiasi pengguna saat ini berada di bawah HKEY_CURRENT_USER\Software\Classes . Mungkin lebih baik menambahkan aplikasi Anda di sana daripada kelas mesin lokal.

Jika program Anda akan dijalankan oleh pengguna terbatas, Anda tidak akan dapat memodifikasi CLASSES_ROOT.

25
Ishmaeel

Jika Anda menggunakan penyebaran ClickOnce, ini semua ditangani untuk Anda (setidaknya, dalam VS2008 SP1); secara sederhana:

  • Properti Proyek
  • Menerbitkan
  • Pilihan
  • Asosiasi file
  • (tambahkan apa pun yang Anda butuhkan)

(perhatikan bahwa itu harus penuh kepercayaan, target .NET 3.5, dan ditetapkan untuk penggunaan offline)

Lihat juga MSDN: Cara: Membuat Asosiasi File Untuk Aplikasi ClickOnce

11
Marc Gravell

Ini contoh lengkapnya:

public class FileAssociation
{
    public string Extension { get; set; }
    public string ProgId { get; set; }
    public string FileTypeDescription { get; set; }
    public string ExecutableFilePath { get; set; }
}

public class FileAssociations
{
    // needed so that Explorer windows get refreshed after the registry is updated
    [System.Runtime.InteropServices.DllImport("Shell32.dll")]
    private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);

    private const int SHCNE_ASSOCCHANGED = 0x8000000;
    private const int SHCNF_FLUSH = 0x1000;

    public static void EnsureAssociationsSet()
    {
        var filePath = Process.GetCurrentProcess().MainModule.FileName;
        EnsureAssociationsSet(
            new FileAssociation
            {
                Extension = ".binlog",
                ProgId = "MSBuildBinaryLog",
                FileTypeDescription = "MSBuild Binary Log",
                ExecutableFilePath = filePath
            },
            new FileAssociation
            {
                Extension = ".buildlog",
                ProgId = "MSBuildStructuredLog",
                FileTypeDescription = "MSBuild Structured Log",
                ExecutableFilePath = filePath
            });
    }

    public static void EnsureAssociationsSet(params FileAssociation[] associations)
    {
        bool madeChanges = false;
        foreach (var association in associations)
        {
            madeChanges |= SetAssociation(
                association.Extension,
                association.ProgId,
                association.FileTypeDescription,
                association.ExecutableFilePath);
        }

        if (madeChanges)
        {
            SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
        }
    }

    public static bool SetAssociation(string extension, string progId, string fileTypeDescription, string applicationFilePath)
    {
        bool madeChanges = false;
        madeChanges |= SetKeyDefaultValue(@"Software\Classes\" + extension, progId);
        madeChanges |= SetKeyDefaultValue(@"Software\Classes\" + progId, fileTypeDescription);
        madeChanges |= SetKeyDefaultValue([email protected]"Software\Classes\{progId}\Shell\open\command", "\"" + applicationFilePath + "\" \"%1\"");
        return madeChanges;
    }

    private static bool SetKeyDefaultValue(string keyPath, string value)
    {
        using (var key = Registry.CurrentUser.CreateSubKey(keyPath))
        {
            if (key.GetValue(null) as string != value)
            {
                key.SetValue(null, value);
                return true;
            }
        }

        return false;
    }
9
Kirill Osenkov

Mungkin ada alasan khusus mengapa Anda memilih untuk tidak menggunakan paket instal untuk proyek Anda tetapi paket instal adalah tempat yang bagus untuk dengan mudah melakukan tugas konfigurasi aplikasi seperti mendaftarkan ekstensi file, menambahkan pintasan desktop, dll.

Berikut cara membuat asosiasi ekstensi file menggunakan alat Instal Visual Studio bawaan:

  1. Dalam solusi C # Anda yang ada, tambahkan proyek baru dan pilih jenis proyek sebagai Other Project Types -> Setup and Deployment -> Setup Project (atau coba Setup Wizard)

  2. Konfigurasikan penginstal Anda (banyak dokumen yang ada untuk ini jika Anda memerlukan bantuan)

  3. Klik kanan proyek setup di Solution Explorer, pilih View -> File Types, dan kemudian tambahkan ekstensi yang ingin Anda daftarkan bersama dengan program untuk menjalankannya.

Metode ini memiliki manfaat tambahan membersihkan setelah itu sendiri jika pengguna menjalankan uninstall untuk aplikasi Anda.

7
Paul J

Untuk lebih spesifik tentang cara "Windows Registry":

Saya membuat kunci di bawah HKEY_CURRENT_USER\Software\Classes (seperti kata Ishmaeel)

dan ikuti instruksi yang dijawab oleh X-Cubed.

Kode contoh terlihat seperti:

private void Create_abc_FileAssociation()
{
    /***********************************/
    /**** Key1: Create ".abc" entry ****/
    /***********************************/
    Microsoft.Win32.RegistryKey key1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true);

    key1.CreateSubKey("Classes");
    key1 = key1.OpenSubKey("Classes", true);

    key1.CreateSubKey(".abc");
    key1 = key1.OpenSubKey(".abc", true);
    key1.SetValue("", "DemoKeyValue"); // Set default key value

    key1.Close();

    /*******************************************************/
    /**** Key2: Create "DemoKeyValue\DefaultIcon" entry ****/
    /*******************************************************/
    Microsoft.Win32.RegistryKey key2 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true);

    key2.CreateSubKey("Classes");
    key2 = key2.OpenSubKey("Classes", true);

    key2.CreateSubKey("DemoKeyValue");
    key2 = key2.OpenSubKey("DemoKeyValue", true);

    key2.CreateSubKey("DefaultIcon");
    key2 = key2.OpenSubKey("DefaultIcon", true);
    key2.SetValue("", "\"" + "(The icon path you desire)" + "\""); // Set default key value

    key2.Close();

    /**************************************************************/
    /**** Key3: Create "DemoKeyValue\Shell\open\command" entry ****/
    /**************************************************************/
    Microsoft.Win32.RegistryKey key3 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true);

    key3.CreateSubKey("Classes");
    key3 = key3.OpenSubKey("Classes", true);

    key3.CreateSubKey("DemoKeyValue");
    key3 = key3.OpenSubKey("DemoKeyValue", true);

    key3.CreateSubKey("Shell");
    key3 = key3.OpenSubKey("Shell", true);

    key3.CreateSubKey("open");
    key3 = key3.OpenSubKey("open", true);

    key3.CreateSubKey("command");
    key3 = key3.OpenSubKey("command", true);
    key3.SetValue("", "\"" + "(The application path you desire)" + "\"" + " \"%1\""); // Set default key value

    key3.Close();
}

Cukup tunjukkan pada kalian demo cepat, sangat mudah dimengerti. Anda dapat mengubah nilai-nilai kunci tersebut dan semuanya berjalan dengan baik.

5
Strong

Asosiasi file didefinisikan dalam registri di bawah HKEY_CLASSES_ROOT.

Ada contoh VB.NET di sini bahwa saya dapat Anda porting dengan mudah ke C #.

2
Steve Morgan

Kode di bawah ini adalah fungsi yang harusnya berfungsi, ia menambahkan nilai yang diperlukan dalam registri windows. Biasanya saya menjalankan SelfCreateAssociation (". Abc") di executable saya. (form constructor atau onload atau onshown) Ini akan memperbarui entri registy untuk pengguna saat ini, setiap kali dieksekusi dieksekusi. (baik untuk debugging, jika Anda memiliki beberapa perubahan) . Jika Anda memerlukan informasi terperinci tentang kunci registri yang terlibat, periksa tautan MSDN ini.

https://msdn.Microsoft.com/en-us/library/windows/desktop/dd758090(v=vs.85).aspx

Untuk mendapatkan informasi lebih lanjut tentang kunci registri ClassesRoot umum. Lihat artikel MSDN ini.

https://msdn.Microsoft.com/en-us/library/windows/desktop/ms724475(v=vs.85).aspx

public enum KeyHiveSmall
{
    ClassesRoot,
    CurrentUser,
    LocalMachine,
}

/// <summary>
/// Create an associaten for a file extension in the windows registry
/// CreateAssociation(@"vendor.application",".tmf","Tool file",@"C:\Windows\SYSWOW64\notepad.exe",@"%SystemRoot%\SYSWOW64\notepad.exe,0");
/// </summary>
/// <param name="ProgID">e.g. vendor.application</param>
/// <param name="extension">e.g. .tmf</param>
/// <param name="description">e.g. Tool file</param>
/// <param name="application">e.g.  @"C:\Windows\SYSWOW64\notepad.exe"</param>
/// <param name="icon">@"%SystemRoot%\SYSWOW64\notepad.exe,0"</param>
/// <param name="Hive">e.g. The user-specific settings have priority over the computer settings. KeyHive.LocalMachine  need admin rights</param>
public static void CreateAssociation(string ProgID, string extension, string description, string application, string icon, KeyHiveSmall Hive = KeyHiveSmall.CurrentUser)
{
    RegistryKey selectedKey = null;

    switch (Hive)
    {
        case KeyHiveSmall.ClassesRoot:
            Microsoft.Win32.Registry.ClassesRoot.CreateSubKey(extension).SetValue("", ProgID);
            selectedKey = Microsoft.Win32.Registry.ClassesRoot.CreateSubKey(ProgID);
            break;

        case KeyHiveSmall.CurrentUser:
            Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Classes\" + extension).SetValue("", ProgID);
            selectedKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Classes\" + ProgID);
            break;

        case KeyHiveSmall.LocalMachine:
            Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"Software\Classes\" + extension).SetValue("", ProgID);
            selectedKey = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"Software\Classes\" + ProgID);
            break;
    }

    if (selectedKey != null)
    {
        if (description != null)
        {
            selectedKey.SetValue("", description);
        }
        if (icon != null)
        {
            selectedKey.CreateSubKey("DefaultIcon").SetValue("", icon, RegistryValueKind.ExpandString);
            selectedKey.CreateSubKey(@"Shell\Open").SetValue("icon", icon, RegistryValueKind.ExpandString);
        }
        if (application != null)
        {
            selectedKey.CreateSubKey(@"Shell\Open\command").SetValue("", "\"" + application + "\"" + " \"%1\"", RegistryValueKind.ExpandString);
        }
    }
    selectedKey.Flush();
    selectedKey.Close();
}

 /// <summary>
    /// Creates a association for current running executable
    /// </summary>
    /// <param name="extension">e.g. .tmf</param>
    /// <param name="Hive">e.g. KeyHive.LocalMachine need admin rights</param>
    /// <param name="description">e.g. Tool file. Displayed in Explorer</param>
    public static void SelfCreateAssociation(string extension, KeyHiveSmall Hive = KeyHiveSmall.CurrentUser, string description = "")
    {
        string ProgID = System.Reflection.Assembly.GetExecutingAssembly().EntryPoint.DeclaringType.FullName;
        string FileLocation = System.Reflection.Assembly.GetExecutingAssembly().Location;
        CreateAssociation(ProgID, extension, description, FileLocation, FileLocation + ",0", Hive);
    }
2
Carsten R.

Ada dua alat cmd yang telah ada sejak Windows 7 yang membuatnya sangat mudah untuk membuat asosiasi file sederhana. Mereka adalah assoc dan ftype . Berikut adalah penjelasan dasar dari setiap perintah.

  • Assoc - mengaitkan ekstensi file (seperti '.txt') dengan "tipe file."
  • FType - menentukan yang dapat dieksekusi untuk dijalankan ketika pengguna membuka "tipe file" yang diberikan.

Perhatikan bahwa ini adalah alat cmd dan bukan file yang dapat dieksekusi (exe). Ini berarti bahwa mereka hanya dapat dijalankan di jendela cmd, atau dengan menggunakan ShellExecute dengan "cmd/c assoc." Anda dapat mempelajari lebih lanjut tentang mereka di tautan atau dengan mengetik "assoc /?" dan "ftype /?" pada cmd Prompt. 

Jadi untuk menghubungkan aplikasi dengan ekstensi .bob, Anda bisa membuka jendela cmd (WindowKey + R, ketik cmd, tekan enter) dan jalankan yang berikut ini:

assoc .bob=BobFile
ftype BobFile=c:\temp\BobView.exe "%1"

Ini jauh lebih sederhana daripada mengacaukan registri dan lebih mungkin untuk bekerja di versi windows masa depan. 

Membungkusnya, berikut adalah fungsi C # untuk membuat asosiasi file:

public static int setFileAssociation(string[] extensions, string fileType, string openCommandString) {
    int v = execute("cmd", "/c ftype " + fileType + "=" + openCommandString);
    foreach (string ext in extensions) {
        v = execute("cmd", "/c assoc " + ext + "=" + fileType);
        if (v != 0) return v;
    }
    return v;
}
public static int execute(string exeFilename, string arguments) {
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = false;
    startInfo.UseShellExecute = true;
    startInfo.FileName = exeFilename;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.Arguments = arguments;
    try {
        using (Process exeProcess = Process.Start(startInfo)) {
            exeProcess.WaitForExit();
            return exeProcess.ExitCode;
        }
    } catch {
        return 1;
    }
}
0
Mike