ActiveX,安装不起作用

时间:2014-03-21 13:20:22

标签: .net windows internet-explorer activex cab

我想创建和部署一个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

1 个答案:

答案 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>