65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Gadget 中使用 COM 而无需安装

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (8投票s)

2007 年 6 月 5 日

4分钟阅读

viewsIcon

58312

downloadIcon

1515

本文介绍了如何在 Gadgets 中使用 COM 组件,而无需安装或管理员权限。

Screenshot - Workometer.jpg

引言

本文介绍了如何将任何 COM 组件用于 Vista 侧边栏 Gadget,并将其打包到 Gadget 的 ZIP 文件中,以便使用通常的“一键式”部署,而无需任何特殊的 MSI 安装或管理员权限。

要安装 Gadget,请下载 Workometer.zip 文件,将文件扩展名重命名为“.gadget”然后双击它。

背景

为了参加 2007 年瑞士 Gadget 竞赛,我想写一个特殊的 Gadget。我构思了一个类似仪表盘的东西,可以显示你的打字速度以及典型工作日内按键次数的统计信息。为此,我需要使用系统范围的键盘和鼠标挂钩,利用 Windows API 函数 SetWindowsHookEx

我知道我必须编写一个负责统计的 COM 组件,但如果 Gadget 需要先安装和注册 COM 组件才能工作,我该如何发布 Gadget 到 Windows Live 图库呢?卸载又该怎么办?

花了点时间才搞定,但如果你知道方法,其实很简单。我想与大家分享这一点,因为 CodeProject 上的许多人帮助我实现了这一点。

在 JavaScript 中使用 COM 组件

我可以选择用 C++/ATL 或 C#/.NET 编写 COM 组件。两者都相当直接,所以在这篇文章中我不会详细解释。有其他很棒的文章可以参考。无论如何,.NET 中没有 SetWindowsHookEx,所以我需要使用 Interop。我决定用纯粹简单的 C++/ATL 编写组件。全部源代码可从上面的链接下载。

该组件公开了一个名为 IGauge 的接口,其中包含一些方法,如 StartMeasureStopMeasurekeySpeedkeyCount 等。用于访问该组件的 JavaScript 代码如下所示:

var workGauge = new ActiveXObject("Workometer.Gauge"); 
workGauge.StartMeasure();

如果您已在计算机上注册了 COM 组件,那么这就足够了。但是,我们不想注册它。请继续阅读。

使用 JavaScript 和 WScript 临时注册组件

诀窍是在实例化组件之前,编写 COM 组件通常在调用 regsvr32regasm 时写入注册表的注册表项。以下是 Workometer 所需的注册表项。

[HKEY_CURRENT_USER\SOFTWARE\Classes\Workometer.Gauge]
@="Workometer Gauge"

[HKEY_CURRENT_USER\SOFTWARE\Classes\Workometer.Gauge\CLSID]
@="{205BC886-A9AA-4C96-B93C-564CCBA8BD83}"

[HKEY_CURRENT_USER\Software\Classes\CLSID\
{205BC886-A9AA-4C96-B93C-564CCBA8BD83}]
@="Workometer.Gauge"

[HKEY_CURRENT_USER\Software\Classes\CLSID\
{205BC886-A9AA-4C96-B93C-564CCBA8BD83}\InprocServer32]
@="C:\Users\...\Workometer.dll"
ThreadingModel="apartment"

请注意,这些项不在注册表的 HKEY_CLASSES_ROOT 部分。要在此处写入项,您需要以管理员模式运行。令我惊讶的是,可以使用 HKEY_CURRENT_USER,但它确实有效。

要使用 JavaScript 将项写入注册表,请使用 WScript.Shell 对象。WScript 对象存在于所有 Vista 计算机上,并包含 RegWriteRegDelete 函数,您可以使用它们来实现此目的。以下是如何调用它的方法:

var wshShell = new ActiveXObject("WScript.Shell"); 
wshShell.RegWrite ("HKCU\\SOFTWARE\\Classes\\Workometer.Gauge\\", 
    "Workometer Gauge");

还有一件小事。DLL 的完整路径名必须在注册表中。要获取 DLL 的路径,我们使用函数 System.Gadget.path,该函数对所有 Gadget 都是自动可用的。

总结

下面是加载 Workometer COM 组件所需的全部代码。基本上,当 Gadget 加载时,我将所需的项写入注册表,使用 ActiveXObject 创建对象,然后立即删除注册表项,这样就不会留下任何痕迹。这就是全部。

var workGauge;

loadWorkGauge();

function loadWorkGauge()
{
    // dynamic register (write the registry entries into current user
    var wshShell = new ActiveXObject("WScript.Shell"); 
    var rootCls = "HKCU\\Software\\Classes\\CLSID\\
        {205BC886-A9AA-4C96-B93C-564CCBA8BD83}\\";
    var rootPid = "HKCU\\SOFTWARE\\Classes\\Workometer.Gauge\\";
    wshShell.RegWrite (rootPid, "Workometer Gauge");
    wshShell.RegWrite (rootPid+"CLSID\\", "
        {205BC886-A9AA-4C96-B93C-564CCBA8BD83}");
    wshShell.RegWrite (rootCls, "Workometer.Gauge");
    wshShell.RegWrite (rootCls+"InprocServer32\\", 
        System.Gadget.path+"\\Workometer.dll");
    wshShell.RegWrite (rootCls+"InprocServer32\\ThreadingModel", "apartment");

    // create the COM object and store it in global variable
    workGauge = new ActiveXObject("Workometer.Gauge"); 

    // delete all the entries again
    wshShell.RegDelete (rootCls+"InprocServer32\\");
    wshShell.RegDelete (rootCls);
    wshShell.RegDelete (rootPid+"CLSID\\");
    wshShell.RegDelete (rootPid);
}

当您将 Gadget 文件打包成 ZIP 文件(.gadget)进行部署时,上面的代码假定 DLL 位于 ZIP 文件的根目录下,与 gadget.xml 文件在同一个位置。

加载 C#/.NET 组件

虽然我没有尝试过,但我确信您也可以用同样的方式加载公开 COM 对象的 .NET 程序集。对于程序集,需要在注册表中写入另外两三行。要找出需要哪些行,请创建 .NET 程序集并使用 regasm 注册它,然后在注册表中查看相关项。

历史

  • 2007 年 6 月 6 日:初始发布

许可证

本文没有明确的许可证附加,但可能在文章文本或下载文件中包含使用条款。如有疑问,请通过下方的讨论区联系作者。您可以在 此处找到作者可能使用的许可证列表。

© . All rights reserved.