1. 程式人生 > >[翻譯].NET Shell Extensions - Shell Context Menus---.net 外殼擴展之右鍵菜單

[翻譯].NET Shell Extensions - Shell Context Menus---.net 外殼擴展之右鍵菜單

desc 關於 沒有 sta 函數 sof 外文 shel 選中

我自己的前言說明:

本文原作者為Dave Kerr,原文鏈接為.NET Shell Extensions - Shell Context Menus ,我是在為了完成最新需求的時候查詢資料的時候發現的,因為太久沒有看外文資料了,所以為了鍛煉一下翻譯的,文中有一句未能翻譯出來。

  • Download SharpShell source code - 1.8 MB
  • Download SharpShell Tools - 181.1 KB
  • Download SharpShell core library - 90.9 KB

引言:

一直到.NET 4.0為止,我們都還是不能通過.NET代碼完全實現外殼擴展的功能。但是隨著framework的不斷提高,現在我們已經可以實現這個功能了。在本文中,我將帶領你通過C#類文件快速實現右鍵菜單擴展功能。

技術分享圖片

(圖中是已經實現的功能,“Count Lines”是我自定義的一個右鍵選項,文章將仔細解釋如何實現該功能)

“.NET外殼擴展”索引:

本文只是“.NET外殼擴展”的一部分,本系列還包括:

  1. .NET Shell Extensions - Shell Context Menus
  2. .NET Shell Extensions - Shell Icon Handlers
  3. .NET Shell Extensions - Shell Info Tip Handlers
  4. .NET Shell Extensions - Shell Drop Handlers
  5. .NET Shell Extensions - Shell Preview Handlers
  6. .NET Shell Extensions - Shell Icon Overlay Handlers
  7. .NET Shell Extensions - Shell Thumbnail Handlers
  8. .NET Shell Extensions - Shell Property Sheets
  9. .NET Shell Extensions - Deploying SharpShell Servers

什麽是Shell Context Menus?

Shell Context Menus是在系統中註冊,允許擴展shell對象的Context菜單的COM服務器。這裏說的對象可以明確到具體的文件類型,例如“.txt”文件,驅動,文件或者其他的文件類型。這時的Context菜單可以通過Windows管理器快速訪問到更多的信息。

準備:

實現外殼擴展功能有很多工作需要完成:我們需要實現具體的COM接口,需要提供服務,並通過各種方式更新註冊表。現在我們可以調用我已經寫好的一個叫做“SharpShell”庫來完成這些復雜的功能,這樣我們的任務就變成了只需要創建一個包含已完成延展功能類的輕量級的類庫了。

我們的目標:

下面所示代碼創建了一個shell擴展,允許你通過右鍵並選擇“Count Lines”來計算出任何文本文件中的行數。另外在文章後半部分我將詳細講解如何創建下面所示的庫。我先將代碼顯示出來的意圖是為了強調在調用SharpShell庫的情況下如何直截了當的完成庫的書寫

/// <summary>
/// The CountLinesExtensions is an example shell context menu extension,
/// implemented with SharpShell. It adds the command ‘Count Lines‘ to text
/// files.
/// </summary>
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class CountLinesExtension : SharpContextMenu
{
    /// <summary>
    /// Determines whether this instance can a shell
    /// context show menu, given the specified selected file list.
    /// </summary>
    /// <returns>
    /// <c>true</c> if this instance should show a shell context
    /// menu for the specified file list; otherwise, <c>false</c>.
    /// </returns>
    protected override bool CanShowMenu()
    {
        //  We always show the menu.
        return true;
    }
 
    /// <summary>
    /// Creates the context menu. This can be a single menu item or a tree of them.
    /// </summary>
    /// <returns>
    /// The context menu for the shell context menu.
    /// </returns>
    protected override ContextMenuStrip CreateMenu()
    {
        //  Create the menu strip.
        var menu = new ContextMenuStrip();
 
        //  Create a ‘count lines‘ item.
        var itemCountLines = new ToolStripMenuItem
        {
            Text = "Count Lines...",
            Image = Properties.Resources.CountLines
        };
 
        //  When we click, we‘ll count the lines.
        itemCountLines.Click += (sender, args) => CountLines();
 
        //  Add the item to the context menu.
        menu.Items.Add(itemCountLines);
 
        //  Return the menu.
        return menu;
    }
 
    /// <summary>
    /// Counts the lines in the selected files.
    /// </summary>
    private void CountLines()
    {
        //  Builder for the output.
        var builder = new StringBuilder();
 
        //  Go through each file.
        foreach (var filePath in SelectedItemPaths)
        {
            //  Count the lines.
            builder.AppendLine(string.Format("{0} - {1} Lines", 
              Path.GetFileName(filePath), File.ReadAllLines(filePath).Length));
        }
 
        //  Show the ouput.
        MessageBox.Show(builder.ToString());
    }
}

代碼可以說簡單清晰了,現在就讓我們開始仔細研究具體的實現過程吧。

第一步:新建項目

首先,我們需要開始一個新的C#類庫項目。

提示:你也可以除了C#,還可以使用VB,在本文中雖然所有的代碼都是C#,但是方法原理均同理可得。

在本例中,我們的項目名稱是” CountLinesExtension”.

現在我們需要添加一下的引用:

  • System.Windows.Forms
  • System.Drawing

之所以需要System.Windows.Forms,是因為我們需要通過WinForms ContextMenuStrip來定義context菜單。而需要調用System.Drawing的原因在於我們想要用到Icons。

將‘Class1.cs‘重命名為‘CountLinesExtension.cs‘.那麽目前我們項目的就變成了這樣了:

技術分享圖片

第二步:引用SharpShell

現在我們需要添加對SharpShell的引用。你可以通過以下這些不同的方法:

添加引用:

在文章最開始的地方下載‘SharpShell Library‘壓縮文件,然後直接對SharpShell.dll文件添加引用即可。

提示:文章開始的下載文件是在此文寫的時候的文件,如果你想要獲得最新的版本,請通過Nuget或者從sharpshell.codeplex.com獲取。

Nuget

如果你電腦有Nuget,那麽就只需要簡單檢索SharpShell並安裝即可,或者直接訪問:https://www.nuget.org/packages/SharpShell

技術分享圖片

CodePlex

CodePlex 的裏面專門的SharpShell主頁sharpshell.codeplex.com中你直接可以得到最新的版本。Nuget上雖然也有最新的可靠的版本,但是CodePlex可以還有可用的已寫好的betas,而且那上面的文章裏面的版本基本都是可用的。

第三步:SharpContextMenu

現在開始就開始真正的研究了,註意了哦。我們的CountLinesExtension繼承於SharpContextMenu:

/// <summary>
/// The Count Lines Context Menu Extension
/// </summary>
public class CountLinesExtension : SharpContextMenu
{
}

現在我們既然繼承於SharpContextMenu這個父類,那我們就要來實現這個抽象類。右鍵選擇SharpContextMenu,然後選擇‘Implement Abstract Class‘:

技術分享圖片

這個操作將會自動生成SharpContextMenu的兩個函數-CanShowMenuCreateMenu

/// <summary>
/// The Count Lines Context Menu Extension
/// </summary>
public class CountLinesExtension : SharpContextMenu
{
    protected override bool CanShowMenu()
    {
        throw new NotImplementedException();
    }
 
    protected override ContextMenuStrip CreateMenu()
    {
        throw new NotImplementedException();
    }
}

通過實現這兩個函數沒我們可以實現我們所需的所有功能。兩個函數功能具體介紹:

CanShowMenu (好像有點不對)

這個函數來決定當前的文件是否是我們需要用來顯示擴展菜單的文件。被選中的文件類型是SelectedItemPaths的屬性。我們可以通過檢查來判斷當前的文件類型是不是符合要求的文件類型。如果需要顯示菜單就返回true,否則就返回false。

CreateMenu

這個函數實現主要的功能。我們需要返回WinForms的ContextMenuStrip

下面是具體的實現:

 protected override bool CanShowMenu()
 {
     //  We will always show the menu.
     return true;
 } 
 protected override ContextMenuStrip CreateMenu()
 {
     //  Create the menu strip.
     var menu = new ContextMenuStrip();
 
    //  Create a ‘count lines‘ item.
     var itemCountLines = new ToolStripMenuItem
    {
         Text = "Count Lines"
     }; 
     //  When we click, we‘ll call the ‘CountLines‘ function.
     itemCountLines.Click += (sender, args) => CountLines();  
 
     //  Add the item to the context menu.
     menu.Items.Add(itemCountLines); 
// Return the menu. return menu; } private void CountLines() { // Builder for the output. var builder = new StringBuilder(); // Go through each file. foreach (var filePath in SelectedItemPaths) { // Count the lines. builder.AppendLine(string.Format("{0} - {1} Lines",Path.GetFileName(filePath),File.ReadAllLines(filePath).Length)); } // Show the ouput. MessageBox.Show(builder.ToString()); }

對於CanShowMenu,我們常常直接返回true(很快我們就會明白為什麽我們不需要驗證我們的文本文件了)。對於CreateMenu,我們建立了一個顯示菜單,裏面只有一個選項,也就是‘Count Lines‘,並實現讀出行數的功能。

CountLines這個功能的實現是通過SelectedItemPaths和讀取每個文件的函數,然後總結好了顯示在彈窗裏。

第四步:處理COM註冊

現在所剩的事情不多了。首先我們需要添加COMVisible的引用到我們的類裏面。

[ComVisible(true)]
public class CountLinesExtension : SharpContextMenu

為什麽呢?因為我們的類雖然看起來不像,但是他本質上也是一個COM Server.如果你了解一些基類,那麽你可以看我們剛剛實現的COM接口,例如IShellExtInit, IContextMenu, 和 ISharpShellServer。我們不用了解這裏到底做了什麽,凡是為了保證系統能夠創建我們的擴展,她就必須有這個屬性。

接下來,我們需要給程序集一個強名稱。這裏有很多方法實現這個要求,但是總體來說,這是最好的方法。現在我們單機程序右鍵,然後選擇“屬性”。再選擇“簽名”。選中“為程序集簽名”,再選擇“選擇強名稱秘鑰文件”裏面的“新建”,並輸入新建的密鑰文件名稱。你可以自行選擇是否需要使用密碼保護密鑰文件:

技術分享圖片

最後一步,我們需要關聯我們的擴展到具體的文件類型了。這個的實現可以通過對COMServerAssociation(來源於SharpShell)的引用:

 [ComVisible(true)]
 [COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
 public class CountLinesExtension : SharpContextMenu

在這裏我們做了什麽呢?我們告訴了SharpShell,註冊服務器時,我們想要關聯任何與“.txt”相關的類。這就意味著我們不止是僅限於以.TXT結尾的文件,而是任何同類的文件。更權威的說法是,大多是與txt文件共享同樣圖標的東西。

你可以用COMServerAssociation的屬性來實現更多的功能,例如你還可以與文件夾,驅動,位置的文件來實現特定的擴展,等等。另外,關於COM Server Associations的詳細的文獻資料在SharpShell CodePlex上面。

好了,但目前為止就搞定了!我們已經創建一個可以在作為COM server 在系統中添加自定義菜單的CountLinesExtension程序集項目了。關於註冊COM Server和調試部署的任務,我們我們將在下一節,仔細討論。

調試Shell 擴展

這個Shell擴展功能將被加載到電腦資源管理器時,由於加載.NET COM Server時各種迂回的方式,所以可以說讓調試器進入進程並但不執行托管代碼幾乎可以說是不可能實現的事情。當然,這裏還是有一個方法可以快速實現調試。Sharp Shell有一些工具,讓實現COM Server變得簡單了,其中一個叫做:Server Manager。我們可以用這個工作實現調試。

打開Server Manager工具,然後點擊File,選擇Load Server,再加載已生成的文件(DLL文件)。你也可以直接拖動文件到主界面中。然後被選中的文件的詳細信息就會在旁邊顯示了。

技術分享圖片

這個Server Manager非常好用,它可以告訴你服務是否已經安裝了和其他各種信息。

如果你要加載SharpContextMenu服務,那就選中‘Tools‘,然後你選中再選中‘Test Context Menu‘。

技術分享圖片

當你用到了‘Test Context Menu‘的時候,你會得到一份測試窗口。只是Windows資源管理器應用程序的基本實現。你可以通過右鍵單擊來測試。

提示:不管你的COMServerAssocations已經生成了,測試的窗口都會不斷的重新創建。

將調試器附加到servermanager過程將允許你調試你的上下文菜單和測試它的功能,而無需在Windows登記服務器。下面是運行Count Line上下文擴展菜單時測試shell的樣子

技術分享圖片

安裝和註冊Shell擴展

這裏又很多方法實現安裝和註冊Shell擴展。在接下來的這一節裏我將仔細介紹這些。

regasm

你可以通過regasm這個工具來實現安裝和祖冊shell擴展。當使用regasm的時候shell會被裝進註冊表中(COM服務器的類ID將放在COM服務器類部分,並與實際服務器文件的路徑相關聯),也會創建關聯。

Server Manager

在開發過程中,服務器管理工具是我首選的安裝/卸載和註冊/註銷的方法,因為它可以讓安裝和註冊作為單獨的步驟處理。它也將讓你指定你是安裝/卸載在32位還是64位模式中。

手動註冊表操作

Generally a bad approach, but if you absolutely have to then the MSDN documentation for Shell Extensions describes the changes that must be made to the registry to manually register a COM server, or a Managed COM Server(這句不會翻譯)。這個文獻資料被放在了下一節。

有用的資料

  • 在windows中創建快捷菜單處理程序:這是最重要的資料:關於shell菜單擴展如何在windows裏具體運行的細節介紹。
  • CodePlex上的SharpShell:關於SharpShell項目的專門的主頁:其中包羅了各種文獻資料,大家的討論,以及最新的代碼研究資源和最新的版本。

後記

會逐漸通過SharpShell和.NET的使用來時間實現更多的shell擴展功能,形成一個完整的系列。目前那我正在實現圖標處理程序(正在編寫文檔),關於屬性表處理程序問題已經實現了(還有些bug正在解決)。

[翻譯].NET Shell Extensions - Shell Context Menus---.net 外殼擴展之右鍵菜單