it-swarm-vi.tech

Làm cách nào để liên kết một phần mở rộng tệp với tệp thực thi hiện tại trong C #

Tôi muốn liên kết một phần mở rộng tệp với tệp thực thi hiện tại trong C # . Cách này khi người dùng nhấp vào tệp sau Explorer, nó sẽ chạy tệp thực thi của tôi với tệp đã cho làm đối số đầu tiên ..__ Thực sự, nó cũng sẽ đặt biểu tượng cho các phần mở rộng tệp đã cho thành biểu tượng để tôi thực thi . Cảm ơn tất cả.

51
Chris

Dường như không có API .Net để quản lý trực tiếp các liên kết tệp nhưng bạn có thể sử dụng các lớp Registry để đọc và viết các khóa bạn cần.

Bạn sẽ cần tạo một khóa trong HKEY_CLASSES_ROOT với tên được đặt thành phần mở rộng tệp của bạn (ví dụ: ".txt"). Đặt giá trị mặc định của khóa này thành một tên duy nhất cho loại tệp của bạn, chẳng hạn như "Acme.TextFile". Sau đó, tạo một khóa khác trong HKEY_CLASSES_ROOT với tên được đặt thành "Acme.TextFile". Thêm một khóa con có tên "DefaultIcon" và đặt giá trị mặc định của khóa cho tệp chứa biểu tượng bạn muốn sử dụng cho loại tệp này. Thêm một anh chị em khác gọi là "Shell". Trong khóa "Shell", thêm khóa cho từng hành động bạn muốn có sẵn thông qua menu ngữ cảnh Explorer, đặt giá trị mặc định cho mỗi khóa thành đường dẫn đến tệp thực thi của bạn theo sau là khoảng trắng và "% 1" để biểu thị đường dẫn vào tập tin đã chọn.

Chẳng hạn, đây là một tệp đăng ký mẫu để tạo liên kết giữa các tệp .txt và EmEditor:

 Windows Registry Editor Phiên bản 5,00 

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

 [HKEY_CLASSES_ROOT\emeditor.txt] 
 Tài liệu "

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

\Shell] 

 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\open] 

 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\open\lệnh] 
 @ = "\" C:\\ Tệp chương trình\EmEditor \\ EMEDITOR.EXE\"\"% 1\"" 

 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\print] 

 Shell\print\lệnh] 
 @ = "\" C: \\ Tệp chương trình \\ EmEditor \\ EMEDITOR.EXE\"/ p \"% 1\"" 
40
X-Cubed

Ngoài ra, nếu bạn quyết định đi theo cách đăng ký, hãy nhớ rằng các hiệp hội người dùng hiện tại nằm dưới HKEY_CURRENT_USER\Software\Classes . Có thể tốt hơn để thêm ứng dụng của bạn ở đó thay vì các lớp máy cục bộ.

Nếu chương trình của bạn sẽ được điều hành bởi những người dùng hạn chế, bạn sẽ không thể sửa đổi CLASSES_ROOT.

25
Ishmaeel

Nếu bạn sử dụng triển khai ClickOnce, tất cả điều này được xử lý cho bạn (ít nhất, trong VS2008 SP1); đơn giản:

  • Thuộc tính dự án
  • Công bố
  • Tùy chọn
  • Tập tin PGS
  • (thêm bất cứ điều gì bạn cần)

(lưu ý rằng nó phải được tin cậy hoàn toàn, nhắm mục tiêu .NET 3.5 và được đặt cho sử dụng ngoại tuyến)

Xem thêm MSDN: Cách: Tạo liên kết tệp cho ứng dụng ClickOnce

11
Marc Gravell

Đây là một ví dụ hoàn chỉnh:

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

Có thể có lý do cụ thể tại sao bạn chọn không sử dụng gói cài đặt cho dự án của mình nhưng gói cài đặt là nơi tuyệt vời để dễ dàng thực hiện các tác vụ cấu hình ứng dụng như đăng ký tiện ích mở rộng tệp, thêm phím tắt trên màn hình, v.v.

Dưới đây là cách tạo liên kết mở rộng tệp bằng các công cụ Cài đặt Visual Studio tích hợp:

  1. Trong giải pháp C # hiện tại của bạn, thêm dự án mới và chọn loại dự án là Other Project Types -> Setup and Deployment -> Setup Project (hoặc thử Trình hướng dẫn cài đặt)

  2. Định cấu hình trình cài đặt của bạn (nhiều tài liệu hiện có cho việc này nếu bạn cần trợ giúp)

  3. Bấm chuột phải vào dự án thiết lập trong Solution Explorer, chọn View -> File Types, sau đó thêm phần mở rộng mà bạn muốn đăng ký cùng với chương trình để chạy nó.

Phương pháp này có thêm lợi ích là tự dọn dẹp nếu người dùng chạy gỡ cài đặt cho ứng dụng của bạn.

7
Paul J

Để được cụ thể về cách "Windows Registry":

Tôi tạo các khóa bên dưới HKEY_CURRENT_USER\Software\Classes (như Ishmaeel đã nói)

và làm theo hướng dẫn được trả lời bởi X-Cubed.

Mã mẫu trông như sau:

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

Chỉ cần cho các bạn xem bản demo nhanh, rất dễ hiểu. Bạn có thể sửa đổi các giá trị chính đó và mọi thứ đều tốt.

5
Strong

Các liên kết tệp được xác định trong sổ đăng ký theo HKEY_CLASSES_ROOT.

Có một ví dụ VB.NET ở đây mà tôi có thể dễ dàng chuyển sang C #.

2
Steve Morgan

Mã dưới đây là một chức năng nên hoạt động, nó thêm các giá trị cần thiết trong sổ đăng ký windows. Thông thường tôi chạy SelfCreateAssociation (". Abc") trong tệp thực thi của tôi. (hàm tạo mẫu hoặc onload hoặc onshown) Nó sẽ cập nhật mục đăng ký cho người dùng hiện tại, mỗi khi thực thi được thực thi. (tốt cho việc gỡ lỗi, nếu bạn có một số thay đổi) . Nếu bạn cần thông tin chi tiết về các khóa đăng ký liên quan, hãy kiểm tra liên kết MSDN này.

https://msdn.Microsoft.com/en-us/l Library/windows/desktop/dd758090 (v = vs85) .aspx

Để có thêm thông tin về khoá đăng ký ClassesRoot chung. Xem bài viết MSDN này.

https://msdn.Microsoft.com/en-us/l Library/windows/desktop/ms724475 (v = vs85) .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.

Có hai công cụ cmd đã xuất hiện từ Windows 7, giúp tạo các liên kết tệp đơn giản rất dễ dàng. Họ là PGSftype . Đây là một lời giải thích cơ bản của từng lệnh.

  • PGS - liên kết một phần mở rộng tệp (như '.txt') với "loại tệp."
  • FType - định nghĩa một tệp thực thi để chạy khi người dùng mở một "loại tệp" đã cho.

Lưu ý rằng đây là các công cụ cmd và không phải tệp thực thi (exe). Điều này có nghĩa là chúng chỉ có thể được chạy trong cửa sổ cmd hoặc bằng cách sử dụng ShellExecute với "cmd/c assoc." Bạn có thể tìm hiểu thêm về chúng tại các liên kết hoặc bằng cách gõ "PGS /?" và "ftype /?" tại một cmd Nhắc. 

Vì vậy, để liên kết một ứng dụng với phần mở rộng .bob, bạn có thể mở cửa sổ cmd (WindowKey + R, nhập cmd, nhấn enter) và chạy như sau:

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

Điều này đơn giản hơn nhiều so với việc làm rối với registry và nó có nhiều khả năng hoạt động trong phiên bản windows trong tương lai. 

Kết thúc nó, đây là một hàm C # để tạo liên kết tệp:

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