MFC ActiveX 控件:许可 ActiveX 控件
许可支持是 ActiveX 控件的可选功能,使你可以控制谁能够使用或分发控件。 (有关许可问题的其他讨论,请参阅升级现有 ActiveX 控件中的许可问题。)
重要
ActiveX 是旧技术,不应用于新开发。 有关取代 ActiveX 的新式技术的详细信息,请参阅 ActiveX 控件。
本文讨论以下主题:
实现许可的 ActiveX 控件使你作为控件开发人员,可以确定其他人如何使用 ActiveX 控件。 你向控件购买者提供控件和 .LIC 文件,同意购买者可以随使用控件的应用程序一起分发控件,但不能分发 .LIC 文件。 这可防止该应用程序的用户编写使用控件的新应用程序,而无需首先由你许可控件。
ActiveX 控制许可概述
为了为 ActiveX 控件提供许可支持,COleObjectFactory 类在 IClassFactory2
接口中为多个函数提供实现:IClassFactory2::RequestLicKey
、IClassFactory2::GetLicInfo
和 IClassFactory2::CreateInstanceLic
。 当容器应用程序开发人员发出创建控件实例的请求时,会对 GetLicInfo
进行调用以验证控件 .LIC 文件是否存在。 如果控件已获得许可,则可以创建控件的实例并放置在容器中。 开发人员完成容器应用程序的构造后,会进行另一个函数调用(这次是 RequestLicKey
)。 此函数会将许可证密钥(一个简单字符串)返回给容器应用程序。 返回的密钥随后会嵌入到应用程序中。
下图演示了在容器应用程序开发期间将使用的 ActiveX 控件的许可证验证。 如前所述,容器应用程序开发人员必须在开发计算机上安装正确的 .LIC 文件才能创建控件的实例。
开发期间授权 ActiveX 控件的验证
下图显示的下一个过程会在最终用户运行容器应用程序时发生。
应用程序启动时,通常需要创建控件的实例。 容器通过调用 CreateInstanceLic
并传递嵌入的许可证密钥作为参数来完成此操作。 随后会在嵌入的许可证密钥与控件自己的许可证密钥副本之间进行字符串比较。 如果匹配成功,则会创建控件的实例,应用程序会继续正常执行。 请注意,控件用户的计算机上不需要存在 .LIC 文件。
执行期间授权 ActiveX 控件的验证
控件许可由两个基本组件构成:控制实现 DLL 中的特定代码和许可证文件。 代码由两个(或可能是三个)函数调用和一个字符串(此后称为“许可证字符串,其中包含版权声明”)组成。 这些调用和许可证字符串处于控件实现 (.CPP) 文件中。 ActiveX 控件向导生成的许可证文件是包含版权声明的文本文件。 它使用项目名称及 .LIC 扩展名进行命名,例如 SAMPLE.LIC。 如果需要在设计时使用,则已获许可的控件必须附带许可证文件。
创建已获许可的控件
使用 ActiveX 控件向导创建控件框架时,可以轻松包含许可支持。 指定控件应具有运行时许可证时,ActiveX 控件向导会将代码添加到控件类以支持许可。 代码由使用密钥和许可证文件进行许可证验证的函数组成。 这些函数也可以进行修改,以便自定义控件许可。 有关许可证自定义的详细信息,请参阅本文后面的自定义 ActiveX 控件的许可。
在创建控件项目时使用 ActiveX 控件向导添加许可支持
- 使用创建 MFC ActiveX 控件中的说明。 ActiveX 控件向导的“应用程序设置”页包含用于创建具有运行时许可证的控件的选项。
ActiveX 控件向导现在会生成包含基本许可支持的 ActiveX 控件框架。 有关许可代码的详细说明,请参阅下一个主题。
许可支持
使用 ActiveX 控件向导向 ActiveX 控件添加许可支持时,ActiveX 控件向导会将可声明和实现许可功能的代码添加到控件头文件和实现文件。 此代码由 VerifyUserLicense
成员函数和 GetLicenseKey
成员函数组成,替代了 COleObjectFactory 中的默认实现。 这些函数会检索并验证控件许可证。
注意
第三个成员函数 VerifyLicenseKey
不由 ActiveX 控件向导生成,但可以进行替代以自定义许可证密钥验证行为。
这些成员函数是:
-
通过检查系统中是否存在控件许可证文件来验证控件是否允许设计时使用。 此函数由框架调用(作为处理
IClassFactory2::GetLicInfo
和IClassFactory::CreateInstanceLic
的一部分)。 -
从控件 DLL 请求唯一密钥。 此密钥会嵌入到容器应用程序中,并在以后与
VerifyLicenseKey
结合使用以创建控件的实例。 此函数由框架调用(作为处理IClassFactory2::RequestLicKey
的一部分)。 -
验证嵌入的密钥和控件的唯一密钥是否相同。 这使容器可以创建控件的实例以供其使用。 此函数由框架调用(作为处理
IClassFactory2::CreateInstanceLic
的一部分),可以进行替代以提供许可证密钥的自定义验证。 默认实现会执行字符串比较。 有关详细信息,请参阅本文后面的自定义 ActiveX 控件的许可。
头文件修改
ActiveX 控件向导会将以下代码置于控件头文件中。 在此示例中,声明了 CSampleCtrl
的对象 factory
的两个成员函数,一个用于验证控件 .LIC 文件是否存在,另一个用于检索在包含控件的应用程序中要使用的许可证密钥:
BEGIN_OLEFACTORY(CMyAxUICtrl) // Class factory and guid
virtual BOOL VerifyUserLicense();
virtual BOOL GetLicenseKey(DWORD, BSTR FAR*);
END_OLEFACTORY(CMyAxUICtrl)
实现文件修改
ActiveX 控件向导会将以下两个语句置于控件实现文件中,以声明许可证文件名和许可证字符串:
static const TCHAR BASED_CODE _szLicFileName[] = _T("NVC_MFC_AxUI.lic");
static const WCHAR BASED_CODE _szLicString[] = L"Copyright (c) 2006 ";
注意
如果以任何方式修改 szLicString
,则也必须修改控件 .LIC 文件中的第一行,否则许可无法正常工作。
ActiveX 控件向导会将以下代码置于控件实现文件中,以定义控件类的 VerifyUserLicense
和 GetLicenseKey
函数:
// CMyAxUICtrl::CMyAxUICtrlFactory::VerifyUserLicense -
// Checks for existence of a user license
BOOL CMyAxUICtrl::CMyAxUICtrlFactory::VerifyUserLicense()
{
return AfxVerifyLicFile(AfxGetInstanceHandle(), _szLicFileName, _szLicString);
}
// CMyAxUICtrl::CMyAxUICtrlFactory::GetLicenseKey -
// Returns a runtime licensing key
BOOL CMyAxUICtrl::CMyAxUICtrlFactory::GetLicenseKey(DWORD /*dwReserved*/,
BSTR FAR* pbstrKey)
{
if (pbstrKey == NULL)
return FALSE;
*pbstrKey = SysAllocString(_szLicString);
return (*pbstrKey != NULL);
}
最后,ActiveX 控件向导会修改控件项目 .IDL 文件。 licensed 关键字会添加到控件的 coclass 声明中,如以下示例所示:
[uuid(913E450B-E720-4C71-BCDF-71C96EE98FEB), licensed,
helpstring("MyAxUI Control"), control]
coclass NVC_MFC_AxUI
自定义 ActiveX 控件的许可
由于 VerifyUserLicense
、GetLicenseKey
和 VerifyLicenseKey
声明为控件工厂类的虚拟成员函数,因此可以自定义控件的许可行为。
例如,可以通过替代 VerifyUserLicense
或 VerifyLicenseKey
成员函数,为控件提供多个级别的许可。 在此函数中,可以根据检测到的许可证级别调整向用户公开的属性或方法。
还可以向 VerifyLicenseKey
函数添加代码,以提供用于向用户告知控件创建失败的自定义方法。 例如,在 VerifyLicenseKey
成员函数中,可以显示一个消息框,指出控件未能初始化以及原因。
注意
自定义 ActiveX 控制许可证验证的另一种方法是在注册数据库中检查特定注册表项,而不是调用 AfxVerifyLicFile
。 有关默认实现的示例,请参阅本文的实现文件修改部分。
有关许可问题的其他讨论,请参阅升级现有 ActiveX 控件中的许可问题。