用C#創建SHELL擴展

發表于:2007-05-25來源:作者:點擊數: 標簽:shell安徽省民航局創建擴展
安徽省民航局 周毅( longsoft@ah163.com ) 一、前言 .NET平臺是微軟公司推出的作為未來軟件運行和開發的環境,C#是微軟力薦的在.NET平臺下開發應用軟件的首選語言。本文將討論在.NET環境下如何使用C#語言開發 Windows Shell擴展問題。如今Windows家族已發展

 安徽省民航局 周毅(longsoft@ah163.com)

一、前言

     .NET平臺是微軟公司推出的作為未來軟件運行和開發的環境,C#是微軟力薦的在.NET平臺下開發應用軟件的首選語言。本文將討論在.NET環境下如何使用C#語言開發Windows Shell擴展問題。如今Windows家族已發展到XP世代了,想必每個程序員都對Shell Extension不會感到陌生吧,在這里我不想花太多的時間介紹Shell Extension的原理知識,本文中將通過一個實例介紹用C#創建一個Shell Extension,在此過程中也會簡單介紹一些Shell Extension的原理知識(如果想詳細了解Shell擴展原理知識,請參閱MSDN)。

二、開發環境

(1)、Windows2000 專業版。
(2)、Visual Studio.NET Beta 2.0或正式版1.0。

三、原理介紹

     本實例實現一個ShellExecuteEx Win32調用的鉤子操作,Windows Explorer常常會用到這個調用,如打開、編輯、打印等等Shell操作都要用到這個調用。在Windows注冊表HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\ShellExecuteHooks項下安裝了所有實現Shell擴展的組件信息。當Windows Explorer執行Shell操作前,先在注冊中查找到已注冊的Shell擴展組件,并將其實例化,每個Shell擴展組件必須至少實現了IShellExecuteHook接口,此接口提供了一個Execute()函數,Explorer將通過組件實例對象調用Execute()函數,如此函數返回為S_FALSE繼續后面的操作,如返回S_OK則停止后面的所有操作。根據以上原理,本實例要實現Shell擴展就必須要實現一個支持IShellExecuteHook接口的COM組件。

接口聲明

因C#不能像C++那樣用一句#include "shlguid.h"語句就可以完成IShellExecuteHook接口聲明,它必須要求在程序中聲明接口的具體信息,聲明如下:

[ComImpor,InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214FB-0000-0000-C000-000000000046")]
/* Guid("000214FB-0000-0000-C000-000000000046") 相當于shlguid.h中的DEFINE_SHLGUID(IID_IShellExecuteHookW, 0x000214FBL, 0, 0); */
public interface IShellExecuteHook{
[PreserveSig()] /* 允許返回值為COM HRESULT */
int Execute(SHELLEXECUTEINFO sei);
}

結構聲明

在Execute()方法中有一個SHELLEXECUTEINFO結構體參數sei,接下來要聲明結構體:
[StructLayout(LayoutKind.Sequential)]
public class SHELLEXECUTEINFO {
public int cbSize;
public int fMask;
public int hwnd;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpVerb; /* 動作,如edit,open,print... */
[MarshalAs(UnmanagedType.LPWStr)]
public string lpFile; /* 根據lpVerb的值而定,常為文件名 */
[MarshalAs(UnmanagedType.LPWStr)]
public string lpParameters; /* 參數字符串 */
[MarshalAs(UnmanagedType.LPWStr)]
public string lpDirectory; /* 路徑名 */
public int nShow;
public int hInstApp;
public int lpIDList;
public string lpClass;
public int hkeyClass;
public int dwHotKey;
public int hIcon;
public int hProcess;
}

SHELLEXECUTEINFO結構體的元素是不是夠多的,它們的具體說明就不一一介紹了,如果你有空的話可以看看MSDN。

四、實現步驟

     介紹了ISellExecuteHook接口的聲明以及SHELLEXECUTEINFO結構體的聲明后,我們就著手實現這個應用實例,這個實例很簡單,每當Explorer對一個Shell對象執行某動作前將會彈出一個對話框,在其上顯示執行的動作內容、對象名以及參數內容。

  打開VS.NET,按下面步驟工作:
  1.新建一個空項目(項目名:ExtenShell)。
  2.添加一個新類(類名:ExtenShell.cs)。
  3.將下面代碼作為ExtenShell.cs的內容。

   /* ExtenShell.cs */
   using System;
   using System.Reflection;
   using System.Runtime.InteropServices;
   using System.Windows.Forms;

   [assembly: AssemblyKeyFile(@"..\..\ESKey.snk")] /*密鑰文件*/
   namespace ShellExtension
   {
     //接口聲明。
     [ComImport,InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214FB-0000-0000-C000-000000000046")]
        /* Guid("000214FB-0000-0000-C000-000000000046") 相當于shlguid.h中的DEFINE_SHLGUID(IID_IShellExecuteHookW, 0x000214FBL, 0, 0); */
     public interface IShellExecuteHook
     {
         [PreserveSig()] /* 允許返回值為COM HRESULT */
         int Execute(SHELLEXECUTEINFO sei);
     }
    
     //結構聲明。
     [StructLayout(LayoutKind.Sequential)]
     public class SHELLEXECUTEINFO
     {
         public int cbSize;
         public int fMask;
         public int hwnd;
         [MarshalAs(UnmanagedType.LPWStr)]
         public string lpVerb;
         [MarshalAs(UnmanagedType.LPWStr)]
         public string lpFile;
         [MarshalAs(UnmanagedType.LPWStr)]
         public string lpParameters;
         [MarshalAs(UnmanagedType.LPWStr)]
         public string lpDirectory;
         public int nShow;
         public int hInstApp;
         public int lpIDList;
         public string lpClass;
         public int hkeyClass;
         public int dwHotKey;
         public int hIcon;
         public int hProcess;
      }

      [Guid("027F9368-A83E-42clearcase/" target="_blank" >cc-85B2-1DC5E23C4608"), ComVisible(true)]
         /* 用Guid生成工具創建一個新的GUID作為類對象的GUID標識。 */
      public class ExtenShell : IShellExecuteHook
      {
           private int S_OK=0;
           private int S_FALSE=1;
           public int Execute(SHELLEXECUTEINFO sei)
           {
               try
               {
                   MessageBox.Show(null, "[ Verb ]: " + sei.lpVerb + "\n[ File ]: " + sei.lpFile + "\n[ Parameters ]:" + sei.lpParameters + "\n[ Directory ]:" + sei.lpDirectory , "ShellExtensionHook",MessageBoxButtons.OK, MessageBoxIcon.Information);

               }
               catch(Exception e)
               {
                   Console.Error.WriteLine("Unknown exception : " + e.ToString());
               }

               return S_FALSE;
               //如果返回值為S_OK則SHELL將停止對Shell對象的以后的所有動作。
            }
       }
  }

   4. 在命令行上運行:sn -k ESKey.snk ( sn.exe在 C:\Programe Files\Microsoft.NET\FrameworkSDK\Bin下可以找到 ),將ESKey.snk添加到項目中。
  5. 打開<項目> --> <屬性>,將輸出類型改成類庫。
  6. 編譯完成。
  7. 因.NET可控代碼生成的COM組件注冊后要到assembly目錄中尋找實體執行,故應將編譯好的ExtenShell.dll文件拷貝到c:\Winnt\assembly目錄中?!?BR>   8. 注冊組件。在命令行上運行:regasm {項目路徑}\Bin\Debug\ExtenShell.dll。( regasm.exe在c:\Winnt\Microsoft.NET\Framework\v1.0.2914下可以找到)
  9.最后,在HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\ShellExecuteHooks項下新建一個字符串值,其名為{027F9368-A83E-42cc-85B2-1DC5E23C4608},值可以為空也可以加入一串描述性文字。

五、結 束
  這是一個簡單的Shell擴展的例子,雖然不是一個完整的應用,但是作者想通過此實例向讀者介紹Shell擴展和.NET平臺下的COM組件開發技術,希望它能起拋磚引玉的作用。

原文轉自:http://www.anti-gravitydesign.com

評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97