2008-09-16 30 views
45

Tôi muốn liên kết phần mở rộng tệp với tệp thi hành hiện tại trong C#. Bằng cách này khi người dùng nhấp vào tệp sau đó trong trình thám hiểm, nó sẽ chạy tệp thi hành của tôi với tệp đã cho làm đối số đầu tiên. Lý tưởng nhất là 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 cho tệp thực thi của tôi. Cảm ơn tất cả.Cách liên kết phần mở rộng tệp với tệp thi hành hiện tại trong C#

+0

này đã được trả lời rõ trong các chủ đề sau: http://stackoverflow.com/questions/2993118/how-to-perform-shell-icon-embedding-in-visual-studio -2010/10415947 # 10415947 –

+0

Điều này đã được trả lời kỹ lưỡng trong [luồng tràn ngăn xếp] sau đây (http://stackoverflow.com/questions/2993118/how-to-perform-shell-icon-embedding-in-visual-studio -2010/10415947 # 10415947). Chúng tôi đã sử dụng triển khai này và nó hoạt động rất tốt. Nó cũng là mã nguồn mở và tích hợp vào MSBuild. –

+2

@BlakeNiemyjski Các liên kết của bạn về cách nhúng biểu tượng vào các hội đồng .NET có liên quan đến câu hỏi này về liên kết tệp mở rộng như thế nào? –

Trả lời

2

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 here rằng tôi có thể dễ dàng chuyển đến C#.

38

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 Đăng ký để đọc và viết các khóa bạn cần.

Bạn cần phải tạo khóa dưới HKEY_CLASSES_ROOT với tên được đặt thành đuôi tệp của bạn (ví dụ: ".txt"). Đặt giá trị mặc định của khóa này thành 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 gọi là "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". Bên dưới khóa "shell", thêm khóa cho mỗi hành động bạn muốn có sẵn thông qua trình đơn ngữ cảnh Explorer, đặt giá trị mặc định cho mỗi khóa thành đường dẫn đến tệp thi hành của bạn theo sau là dấu cách và "% 1" để biểu thị đường dẫn vào tệp đã chọn.

Ví dụ, đây là một tập tin registry mẫu để tạo ra một mối liên hệ giữa các file .txt và EmEditor:

 
Windows Registry Editor Version 5.00 

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

[HKEY_CLASSES_ROOT\emeditor.txt] 
@="Text Document" 

[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\"" 
+0

Có cách nào để chuyển một số đối số cho exe (trong trường hợp này là C: \ Program Files \ EmEditor \ EMEDITOR.EXE)? – Apparao

+0

@Apparao có, hãy xem lệnh In làm ví dụ. Nó chuyển thông số a/p trước tên tệp. –

25

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

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

7

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 bạn, nhưng một gói cài đặt là một nơi tuyệt vời để dễ dàng thực hiện nhiệm vụ cấu hình ứng dụng như đăng ký phần mở rộng tập tin, thêm phím tắt máy tính để bàn, vv

Dưới đây là làm thế nào để tạo sự liên kết mở rộng tập tin bằng cách sử dụng tích hợp trong Visual Studio công cụ cài đặt:

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

  2. Cấu hì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 sự giúp đỡ)

  3. Kích chuột phải vào dự án thiết lập trong Solution Explorer, chọn View ->File Types, và 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 khi tự dọn dẹp sau khi người dùng chạy gỡ cài đặt cho ứng dụng của bạn.

11

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

  • Thuộc tính dự án
  • Publish
  • Tùy chọn
  • file Associatons
  • (thêm bất cứ điều gì bạn cần)

(lưu ý rằng nó phải có đầy đủ tin tưởng, mục tiêu. NET 3.5 và được đặt để sử dụng ngoại tuyến)

Xem thêm MSDN: How to: Create File Associations For a ClickOnce Application

+1

Tôi có VS2008 Professional, SP1 và tôi không thấy tùy chọn này. Chắc chắn là tôi đang thiếu gì đó. – Jerry

5

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

tôi có thể tạo phím dưới HKEY_CURRENT_USER \ Software \ Classes (như Ishmaeel nói)

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

Mẫu mã trông giống như:

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 thấy một bản demo nhanh chóng, rất dễ hiểu. Bạn có thể sửa đổi những giá trị quan trọng đó và mọi thứ đều tốt để đi.

+1

Đừng quên thêm mã cần thiết để thông báo cho trình bao sử dụng biểu tượng. 'SHChangeNotify (0x8000000, 0, 0, 0);' – randomsolutions

8

Dưới đâ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; 
    } 
0

Có hai công cụ cmd đã được khoảng từ Windows 7 mà làm cho nó rất dễ dàng để tạo các hiệp hội tập tin đơn giản. Chúng là assocftype. Đây là một lời giải thích cơ bản của mỗi lệnh.

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

Lưu ý rằng đây là những công cụ cmd chứ không phải tệp thực thi (exe). Điều này có nghĩa là chúng chỉ có thể chạy trong một 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õ "assoc /?" và "ftype /?" tại dấu nhắc cmd.

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

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

Đây là đơn giản hơn nhiều so với rối tung với đăng ký và nó có nhiều khả năng làm việc trong phiên bản cửa sổ trong tương lai.

Bao bì nó lên, đây là một chức năng C# để tạo ra một hiệp hội tập tin:

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

Đoạn code dưới đây là một chức năng nên hoạt động, nó bổ sung thêm các giá trị cần thiết trong cửa sổ đăng ký. Thông thường tôi chạy SelfCreateAssociation (". Abc") trong thực thi của tôi.(Form constructor 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 để 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 registry liên quan, hãy kiểm tra liên kết MSDN này.

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

Để biết thêm thông tin về các khóa registry ClassesRoot chung. Xem bài viết MSDN này.

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); 
    } 
+0

Để lại một khối mã lớn mà không có lời giải thích nào cũng không hữu ích cho người đọc trong tương lai. Vui lòng thử và thêm một số giải thích về mã này. – Nisarg

Các vấn đề liên quan