C#开发BHO插件UrlTrack
最近忽然突发奇想,想统计一下我最经常上的网站是哪些,并且在这些网站上都停留了多久。为此决定写一个BHO插件来做这件事。
BHO(Browser Help Objects)是实现了特定接口(IObjectWithSite)的COM组件。开发好的BHO插件除了要在注册表中注册为COM Server外,还必须将它的CLSID在HKLMSOFTWARE...Browser Helper Objects下注册为子键。每当浏览器[1]启动时,首先会在上述注册表位置查看是否有注册的BHO CLSID,如果有则分别创建一个实例,并对BHO实例进行初始化。BHO实例运行在浏览器的地址空间内,能对可访问的对象(如窗口、模块等等)执行任何操作,且因为它依附于浏览器的主窗口,所以其生命周期与浏览器实例的生命周期一致。下图演示了BHO的创建过程:
下面就来介绍一下如何开发BHO插件。首先创建一个C#项目,类型为Class Library。然后将Class1.cs改名为IObjectWithSite.cs,还要给IObjectWithSite添加两个功能:GetSite和SetSite。
Public Interface Iobjectwithsite
{
[Preservesig]
Int Setsite([Marshalas(Unmanagedtype.Iunknown)]Object Site);
[Preservesig]
Int Getsite(Ref Guid Guid, Out Intptr Ppvsite);
}
添加一个cs文件UrlTrack.cs,并且实现IObjectWithSite接口。使用BHO还需要添加两个引用SHDocVw.dll和MSHTML.dll,可以在WindowsSystem32目录下找到。
在IObjectWithSite.cs中,还需要为我们的程序指出IE的GUID,使得它可以挂接(attach)到IE上
[
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")
]
另外,还需要给BHO程序分配一个GUID,这个可以通过System.Guid.NewGuid()方法得到
[
ComVisible(true),
Guid("e90da13b-117a-4178-8111-0f712da09ff9"),
ClassInterface(ClassInterfaceType.None)
]
在UrlTrack.cs中,我们还需要写两个方法用来DLL注册和移除注册
public static string BHOKEYNAME = @"SOFTWARE...Browser Helper Objects";
[ComRegisterFunction]
public static void RegisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_KEY_NAME, true);
if (registryKey == null)
{
registryKey = Registry.LocalMachine.CreateSubKey(BHO_KEY_NAME);
}
string guid = type.GUID.ToString("B");
RegistryKey bhoKey = registryKey.OpenSubKey(guid, true);
if (bhoKey == null)
{
bhoKey = registryKey.CreateSubKey(guid);
}
// NoExplorer: dword = 1 prevents the BHO to be loaded by Explorer.exe
bhoKey.SetValue("NoExplorer", 1);
bhoKey.Close();
registryKey.Close();
}
[ComUnregisterFunction]
public static void UnregisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHO_KEY_NAME, true);
string guid = type.GUID.ToString("B");
if (registryKey != null)
registryKey.DeleteSubKey(guid, false);
}
接下来就是实现具体的统计功能了。考虑一下,当输入网址后,我们需要记录下网址以及当前的时间;当在同一浏览窗口中切换网址时,不仅需要记录下网址和当前时间,还要设置前一个浏览记录的结束时间;并且在关闭浏览器时,也要记下结束时间。所以在SetSite中需要挂载NavigateComplete2和OnQuit事件。
private void NavigateComplete2(object pDisp, ref object URL)
{
string url = URL as string;
if (url.IndexOf("about:blank") >= 0)
{
return;
}
if (visitHists.Count > 0)
{
VisitHist currentHist = visitHists[visitHists.Count - 1];
if (currentHist.VisitUrl != url)
{
currentHist.EndTime = System.DateTime.Now;
}
else
{
return;
}
}
VisitHist newHist = new VisitHist();
newHist.StartTime = System.DateTime.Now;
newHist.VisitUrl = url;
visitHists.Add(newHist);
}
private void OnQuit()
{
if (visitHists.Count > 0)
{
VisitHist currentHist = visitHists[visitHists.Count - 1];
currentHist.EndTime = System.DateTime.Now;
}
// 输出统计记录
...
}
开始编译,然后就可以在bin目录下找到项目的dll文件了。在Console中使用regasm /codebase "UrlTrack.dll"注册dll。打开注册表,在HKLMSOFTWARE...Browser Helper Object可以看到多出了一个子项{E90DA13B-117A-4178-8111-0F712DA09FF9}。
需要注意的是,需要将AssemblyInfo.cs文件中的ComVisible属性设为true,否则在注册BHO时会得到这样的信息:
RegAsm : warning RA0000 : No types were registered.
更多的BHO资料可以看这里:Browser Extensions
[1] 在Windows操作系统上有两种浏览器:资源浏览器(explorer.exe,应用于文件系统)和Internet浏览器(IEXPLORE.EXE,应用于互联网资源)。
Related Posts
People who read this, also read...
使用SAPI 5.1和C#构建TTS程序(续)
在《使用SAPI 5.1和C#构建TTS程序》一文中我们实现了一个简单的TTS程序,不过它还只能够朗读英文。下面我们就来给它添加朗读中文的功能。要想实现中文发音,必需要安装SAPI 5.1 Language Pack。Language Pack可以在这里下载:http://www.microsoft.com/speech/speech2007/downloads.mspx。安装好以后,就可以开始进行中文发音的开发了。
SpVoiceClass类有个属性Voice可以用来控制TTS的语种,因此在中文发音时需要将Voice属性设置为中文语种的编码,另外还要在控制面板的语音中进行一些设置:

Voice支持所有的语种列表可以通过SpVoiceClass的GetVoices方法得到,其中0表示汉语,1/2/3/4表示英语,只是口音有所不同。
private void SetChineseVoice()
{
voice.Voice = voice.GetVoices(string.Empty, string.Empty).Item(0);
}
private void SpeakChinese(string text)
{
SetChineseVoice();
voice.Speak(text, SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
private void SetEnglishVoice()
{
voice.Voice = voice.GetVoices(string.Empty, string.Empty).Item(1);
}
private void SpeakEnglish(string text)
{
SetEnglishVoice();
voice.Speak(text, SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
现在,程序已经能够单独的朗读中文或者英文了,接下来我们还要实现中英文混合朗读。对于中英文混合文字的朗读,可以通过划分文字中的中英文,分别调用相应的方法来实现。如果是中文就调用SpeakChinese方法,是英文则调用SpeakEnglish方法。
private void Speak(string text)
{
int begin = 0;
int length = 0;
bool isChinese = false;
Regex regex = new Regex("[\u4e00-\u9f5a]", RegexOptions.Compiled);
for (int current = 0; current < text.Length; current++)
{
if (regex.IsMatch(text[current].ToString()))
{
if (!isChinese)
{
length = current - begin;
SpeakEnglish(text.Substring(begin, length));
begin = current;
isChinese = true;
}
}
else
{
if (isChinese)
{
length = current - begin;
SpeakChinese(text.Substring(begin, length));
begin = current;
isChinese = false;
}
}
}
length = text.Length - begin;
if (isChinese)
{
SpeakChinese(text.Substring(begin, length));
}
else
{
SpeakEnglish(text.Substring(begin, length));
}
}
Related Posts
People who read this, also read...
- 使用USB在ThinkPad X60上安装Ubuntu 8.04
- [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property...
使用SAPI 5.1和C#构建TTS程序
SAPI SDK是微软公司免费提供的语音应用开发工具包,这个SDK中包含了语音应用设计接口(SAPI)、微软的连续语音识别引擎(MCSR)以及微软的语音合成(TTS)引擎等等。目前的5.1版本一共可以支持3种语言的识别(英语,汉语和日语)以及2种语言的合成(英语和汉语)。
SDK下载地址:http://www.microsoft.com/speech/speech2007/downloads.mspx
新建一个C#的Windows Application工程SimpleTTS,右键点击References,选择Add Reference,点击弹出的Add Reference窗体中的COM属性页,选择"Microsoft Speech Object Library"语音引擎组件,确定后SpeechLib就被添加到了References中。

程序范例:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SpeechLib;
namespace SimpleTTS
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void btnSpeak_Click(object sender, EventArgs e)
{
SpVoice voice = new SpVoice();
voice.Voice = voice.GetVoices(string.Empty, string.Empty).Item(1);
voice.Speak(this.mtbSpeechText.Text, SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Dispose();
}
}
partial class MainForm
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.mtbSpeechText = new System.Windows.Forms.TextBox();
this.btnSpeak = new System.Windows.Forms.Button();
this.btnExit = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// mtbSpeechText
//
this.mtbSpeechText.Location = new System.Drawing.Point(8, 8);
this.mtbSpeechText.Multiline = true;
this.mtbSpeechText.Name = "mtbSpeechText";
this.mtbSpeechText.Size = new System.Drawing.Size(284, 60);
this.mtbSpeechText.TabIndex = 0;
this.mtbSpeechText.Text = "This is Simple TTS application.";
//
// btnSpeak
//
this.btnSpeak.Location = new System.Drawing.Point(110, 80);
this.btnSpeak.Name = "btnSpeak";
this.btnSpeak.Size = new System.Drawing.Size(80, 24);
this.btnSpeak.TabIndex = 1;
this.btnSpeak.Text = "&Speak";
this.btnSpeak.Click += new System.EventHandler(this.btnSpeak_Click);
//
// btnExit
//
this.btnExit.Location = new System.Drawing.Point(200, 80);
this.btnExit.Name = "btnExit";
this.btnExit.Size = new System.Drawing.Size(80, 24);
this.btnExit.TabIndex = 2;
this.btnExit.Text = "&Exit";
this.btnExit.Click += new System.EventHandler(this.btnExit_Click);
//
// MainForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(299, 120);
this.Controls.Add(this.btnExit);
this.Controls.Add(this.btnSpeak);
this.Controls.Add(this.mtbSpeechText);
this.MaximizeBox = false;
this.Name = "MainForm";
this.Text = "SimpleTTS";
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.TextBox mtbSpeechText;
private System.Windows.Forms.Button btnSpeak;
private System.Windows.Forms.Button btnExit;
}
}
BTW:TTS是text-to-speech的缩写,英文也称Speech Synthesis即语音合成。


