我想创建和部署一个ActiveX插件,有些很小。我只是想显示一个消息框。
我为它创建了一个库项目并将其编译为DLL。当我在一台机器上通过命令行(regasm
)注册dll时,该插件可以正常工作。
所以我现在需要创建一个安装程序,将它放在一个CAB文件中并签名。
我已安装Visual Studio 2008以使用Setup Project项目(但如果有人可以解释如何操作,我可以使用2010年以上的InstallShield)。我将我的dll添加到应用程序文件夹并将其标记为Register = vsdrpCOM
并构建它,我得到一个.msi和.exe。
我想我只需要msi文件而不是exe文件。我创建了一个带有以下内容的setup.inf文件:
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Setup Hooks]
hook1=hook1
[hook1]
run=msiexec.exe /i "%EXTRACT_DIR%\ActiveInstaller.msi" /qn
要构建.cab文件,我使用命令makecab / f build.ddf。 这是我的.ddf文件:
.Set DiskDirectoryTemplate=;
.Set CabinetNameTemplate=ActiveInstaller.cab
../ActiveInstaller.msi
../setup.inf
这生成了cab文件。现在我需要签名。目前我使用了自己生成并安装在我的电脑上的自签名证书(当我检查登录cab文件时,Windows表示它是安全的)。我使用另一个命令行signtool signwizard
(我也尝试从here手动签名)。然后文件被签名,我上传到我的网站,我启动网站,我被提示安装插件,我安装它。
但是,它不起作用,我不知道为什么。我尝试过很多东西,包括不同的安装程序,不同的选项,不同的inf文件,不同的签名方法等等。
我发现的唯一教程至少有三年了,我不知道自写完以来是否有任何改变。 以下是我使用的主要链接:http://blogs.msdn.com/b/asiatech/archive/2011/12/05/how-to-develop-and-deploy-activex-control-in-c.aspx和另一个http://www.codeproject.com/Articles/24089/Create-ActiveX-in-NET-Step-by-Step
解决方案:
所以,Pepo所说的一切都是真的,所以我把他的答案标记为已被接受。 我还找到了一个完整源代码的人(包括如何创建运行msi的.exe)here。
答案 0 :(得分:4)
问题可能是您尝试运行msiexec.exe并且此exe不在cab文件中。请参阅this question(请务必向下滚动至2009年8月5日Roey发布的极其有用的示例代码)。 尝试创建一个setup.exe,它将运行进程msiexec.exe并安装msi或使用bootstrap setup.exe文件创建一个安装程序,并将它们包含在cab中。
另外,您可能希望了解non-admin activex installations。
您的activex dll必须已签名且您的activeX应实现此接口
/// <summary>
/// Options supported for the IObjectSafety interface
/// </summary>
[Serializable]
[ComVisible(true)]
public enum ObjectSafetyOptions
{
/// <summary>
/// Indicates that the caller of the interface identified by riid might be untrusted.
/// </summary>
INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001,
/// <summary>
/// Indicates that the data passed into the interface identified by riid might be untrusted.
/// </summary>
INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002,
/// <summary>
/// Indicates that the caller of the interface identified by riid knows to use IDispatchEx.
/// </summary>
INTERFACE_USES_DISPEX = 0x00000004,
/// <summary>
/// Indicates that the data passed into the interface identified by riid knows to use IInternetHostSecurityManager.
/// </summary>
INTERFACE_USES_SECURITY_MANAGER = 0x00000008
};
/// <summary>
/// Provides methods to get and set safety options.
/// The IObjectSafety interface should be implemented by objects that have interfaces which support "untrusted" clients, such as scripts.
/// It allows the owner of the object to specify which interfaces must be protected from "untrusted" use.
/// </summary>
[ComImport()]
[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
/// <summary>
/// Gets the safety options supported by an object and the safety options that are currently set for that object.
/// </summary>
/// <param name="iid">An interface identifier for a given object</param>
/// <param name="pdwSupportedOptions">Receives the address of a DWORD representing all the options supported for the interface identified by riid.</param>
/// <param name="pdwEnabledOptions">Receives the address of a DWORD representing all the options currently enabled for the interface identified by riid.</param>
/// <returns>Returns one of the following values:
/// S_OK - the object is safe for loading
/// E_NOINTERFACE - the riid parameter specifies an interface that is unknown to the object</returns>
[PreserveSig]
long GetInterfaceSafetyOptions(ref Guid iid, out int pdwSupportedOptions, out int pdwEnabledOptions);
/// <summary>
/// Returns whether an object is safe for initialization or scripting, as specified.
/// </summary>
/// <param name="iid">An iInterface identifier for the object to be made safe.</param>
/// <param name="dwOptionSetMask">A mask representing the options to be validated.</param>
/// <param name="dwEnabledOptions">A DWORD representing all the options currently enabled for the interface identified by riid. </param>
/// <returns>Returns one of the following values:
/// S_OK - the object is safe for loading
/// E_NOINTERFACE - the riid parameter specifies an interface that is unknown to the object
/// E_FAIL - the dwOptionSetMask parameter specifies an option that is not supported by the object</returns>
[PreserveSig]
long SetInterfaceSafetyOptions(ref Guid iid, int dwOptionSetMask, int dwEnabledOptions);
};
我使用高级安装程序创建msi安装程序,然后设置dll registration。然后,高级安装程序会生成所有必需的注册表项。
在我的测试中,最终的inf文件是
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Deployment]
InstallScope=user|machine
[Setup Hooks]
install=install
[install]
run="""%EXTRACT_DIR%\runmsi.exe""" """%EXTRACT_DIR%\simpleactivex.msi"""
请注意三重引号。它们很重要。
我用过这个ddl
.Set DiskDirectoryTemplate=.
.Set CabinetNameTemplate=simpleactivex.cab
runmsi.exe
simpleactivex.msi
simpleactivex.inf
我使用这个命令构建cab
"c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\signtool.exe" sign /sha1 9A15DC8F51773C557BA2F75CF155F8CBD367A8E1 /tr http://tsa/tsa /d SimpleActiveX /du "http://yourcompany.com" /v runmsi.exe simpleactivex.msi
makecab /V3 /F make.ddl
"c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\signtool.exe" sign /sha1 9A15DC8F51773C557BA2F75CF155F8CBD367A8E1 /tr http://tsa/tsa /d simpleactivex /du "http://yourcompany.com" /v simpleactivex.cab
runmsi.exe是一个使用给定参数运行msiexec的虚拟exe文件。或者,您可以使用exe安装程序或bootstrap exe和msi安装程序。需要注意的重要部分是IE不允许在cab文件之外运行任何东西。因此你必须这样做。
调试时我使用了这个虚拟html页面
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
<head>
<title>WebForm1</title>
</head>
<body style="margin-top: 0px; margin-left: 0px;">
<OBJECT id="SimpleActiveXCtrl" classid="clsid:C0082E22-8A19-4600-8332-D31C4055291A" codebase="SimpleActiveX.CAB"></OBJECT>
<script language="javascript">
// da sa volat z JS metody ActiveXu alebo nastavit property
function OpenActiveX()
{
try
{
alert(document.SimpleActiveXCtrl.HelloWorld("hello"));
}
catch(Err)
{
alert(Err.description);
}
}
</script>
</body>
</html>