2012-08-09 128 views
0

这是一个完全新手的问题,因为我的领域是Java而不是C#,但我得到了构建BHO的任务,并且达到了我需要菜单项的地步(在工具内部菜单)在我的代码中调用一个函数。菜单项被点击...没有反应

我读到我必须声明并实现IOleCommandTarget接口,我这样做了。现在我需要将这个类注册为一个COM对象。

显然要做到这一点,我需要用[ComRegisterFunction]声明几个函数,但即使如此,我也无法在regsvr32中注册它们。而uppon与DLL导出进一步检查查看器的功能似乎并不在那里:(

我在做什么错

预先感谢您

编辑:

好了,所以从我得到的评论我想,我的COM对象被正确注册,但仍然是我的问题依然存在:当我点击新创建的菜单项时,我没有任何反应或方式来调试真正发生的事情

这是我到目前为止的代码:

using System; 
using System.Runtime.InteropServices; 
using System.IO; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using SHDocVw; 
using MSHTML; 
using Microsoft.Win32; 
using System.Windows; 
using System.Windows.Forms; 
using System.Drawing.Imaging; 
using System.Drawing; 
using System.Diagnostics; 
using System.Threading; 


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct OLECMDTEXT { 
    public uint cmdtextf; 
    public uint cwActual; 
    public uint cwBuf; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] 
    public char rgwz; 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct OLECMD { 
    public uint cmdID; 
    public uint cmdf; 
} 

// Interop definition for IOleCommandTarget. 
[ComImport, 
Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), 
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IOleCommandTarget { 
    //IMPORTANT: The order of the methods is critical here. You 
    //perform early binding in most cases, so the order of the methods 
    //here MUST match the order of their vtable layout (which is determined 
    //by their layout in IDL). The interop calls key off the vtable ordering, 
    //not the symbolic names. Therefore, if you switched these method declarations 
    //and tried to call the Exec method on an IOleCommandTarget interface from your 
    //application, it would translate into a call to the QueryStatus method instead. 
    void QueryStatus(ref Guid pguidCmdGroup, UInt32 cCmds, 
     [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] OLECMD[] prgCmds, ref OLECMDTEXT CmdText); 
    void Exec(ref Guid pguidCmdGroup, uint nCmdId, uint nCmdExecOpt, ref object pvaIn, ref object pvaOut); 
} 

namespace ANAISBHO { 

    [ 
    ComVisible(true), 
    Guid("8a194578-81ea-4850-9911-13ba2d71efbd"), 
    ClassInterface(ClassInterfaceType.None) 
    ] 
    public class BHO : IObjectWithSite, IOleCommandTarget { 

     public SHDocVw.WebBrowser webBrowser; 

     public HTMLDocument document; 

     public static string BHOKEYNAME = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects"; 

     private Guid cmdGuid = new Guid("ED016940-BD5B-11CF-BA4E-00C04FD70816"); 

     private static Bitmap bmpScreenshot; 

     private static Graphics gfxScreenshot; 


     public void OnDocumentComplete(object pDisp, ref object URL) { 
      document = (HTMLDocument) webBrowser.Document; 
     } 

     //HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\{GUID}\CLSID 
     private static void RegisterCiteNPLMenuEntry() { 
      Console.WriteLine("Registrying the CiteNPL menu entry"); 
      RegistryKey MicrosoftKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default).OpenSubKey("Software").OpenSubKey("Microsoft"); 
      RegistryKey ExtensionsKey = MicrosoftKey.OpenSubKey("Internet Explorer").OpenSubKey("Extensions", RegistryKeyPermissionCheck.ReadWriteSubTree); 
      String GUID = @"{C3E1CD69-3928-4b69-ABEC-936CA3A3BAAA}"; 

      ExtensionsKey.CreateSubKey(GUID); 
      RegistryKey GUIDKey = ExtensionsKey.OpenSubKey(GUID, RegistryKeyPermissionCheck.ReadWriteSubTree); 
      String CLSID_Shell_ToolbarExtExec = @"{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}"; 
      GUIDKey.SetValue("CLSID", CLSID_Shell_ToolbarExtExec, RegistryValueKind.String); 
      GUIDKey.SetValue("MenuText", "CiteNPL", RegistryValueKind.String); 
      GUIDKey.SetValue("ClsidExtension", "{c4127d56-7114-46da-a853-6ea1b8a199f7}", RegistryValueKind.String); 

      GUIDKey.Close(); 
      ExtensionsKey.Close(); 
      MicrosoftKey.Close(); 
     } 


     public void QueryStatus(ref Guid pguidCmdGroup, UInt32 cCmds, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] OLECMD[] prgCmds, ref OLECMDTEXT CmdText) { 
      MessageBox.Show("query"); 
     } 

     public void Exec(ref Guid pguidCmdGroup, uint nCmdId, uint nCmdExecOpt, ref object pvaIn, ref object pvaOut) { 
      MessageBox.Show("Exec"); 
     } 

     private void TakeScreenshot() { 
      int height = 1024; //webBrowser.Document.Body.ScrollRectangle.Height; 
      int width = 1024; //webBrowser.Document.Body.ScrollRectangle.Width; 
      //int left = 0;  //webBrowser.Document.Body.ScrollRectangle.Left; 
      //int right = 1024; //webBrowser.Document.Body.ScrollRectangle.Right; 
      System.Drawing.Size browserSize = new System.Drawing.Size(width, height); 

      bmpScreenshot = new Bitmap(width, height, PixelFormat.Format32bppArgb); 
      gfxScreenshot = Graphics.FromImage(bmpScreenshot); 
      gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy); 
      bmpScreenshot.Save("c:\\temp.png", ImageFormat.Png); 
     } 

     public int SetSite(object site) { 
      if(site != null) { 
       webBrowser = (SHDocVw.WebBrowser) site; 
       webBrowser.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete); 
      } else { 
       webBrowser.DocumentComplete -= new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete); 
       webBrowser = null; 
      } 

      return 0; 
     } 

     public int GetSite(ref Guid guid, out IntPtr ppvSite) { 
      IntPtr punk = Marshal.GetIUnknownForObject(webBrowser); 
      int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite); 
      Marshal.Release(punk); 

      return hr; 
     } 

     [ComRegisterFunction] 
     public static void RegisterBHO(Type type) { 
      Console.WriteLine("Registering the BHO"); 

      RegisterCiteNPLMenuEntry(); 
      RegisterBHOInWindowsRegistry(type); 
     } 

     [ComUnregisterFunction] 
     public static void UnregisterBHO(Type type) { 
      Console.WriteLine("Unregistering the BHO"); 
      UnRegisterBHOFromWindowsRegistry(type); 
     } 

     private static void UnRegisterBHOFromWindowsRegistry(Type type) { 
      RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME, true); 
      string guid = type.GUID.ToString("B"); 

      if(registryKey != null) { 
       registryKey.DeleteSubKey(guid, false); 
      } 
     } 

     private static void RegisterBHOInWindowsRegistry(Type type) { 
      RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME, true); 

      if(registryKey == null) { 
       registryKey = Registry.LocalMachine.CreateSubKey(BHOKEYNAME); 
      } 

      string guid = type.GUID.ToString("B"); 
      RegistryKey ourKey = registryKey.OpenSubKey(guid); 

      if(ourKey == null) { 
       ourKey = registryKey.CreateSubKey(guid); 
      } 

      ourKey.SetValue("Alright", 1); 
      registryKey.Close(); 
      ourKey.Close(); 
     } 
    } 
} 

回答

1

因为这是一个托管的DLL,您不能使用任何REGSVR32或“DLL导出查看器”。

要注册NET的DLL为COM互操作,使用Regasm

+0

好regasm作品,我真的不知道它做什么,但它说,它说:“成功注册类型”。但是我的Exec函数没有被调用。因为我使用VS express,所以我没有真正的代码调试方式,并找出当我点击该菜单项按钮时会发生什么:( – ricardoespsanto 2012-08-09 09:13:10

+0

@Ricky: - 设置regasm所在的路径..通常在安装目录工具中部分 – perilbrain 2012-08-09 09:15:39

+0

对不起,但我不太明白你的意思...我已经完成了这一步,但也使用了/ codebase:C:\ Documents and Settings \ RE86508 \ My Documents \ Visual Studio 2010 \ Projects \ ANAISBHO \ ANAISBHO \ bin \ Release> c:\ WINDOWS \ Microsoft.NET \ Framework \ v4.0.30319 \ RegAsm.exe ANAISBHO.dll – ricardoespsanto 2012-08-09 09:23:36