wix customaction UAC dtf

Posted

技术标签:

【中文标题】wix customaction UAC dtf【英文标题】: 【发布时间】:2015-01-20 16:07:35 【问题描述】:

我正在为 IIS 网站创建 Wix 安装程序,可以在 UI 中选择网站、应用程序池并选择虚拟目录。事情是:我成功创建了安装程序,它在 UAC 关闭的情况下工作,但 UAC 设置为最大值。我收到错误 - 来自 MSI 日志:

MSI (c) (A0:C8) [16:41:21:692]:调用远程自定义操作。 DLL:C:\Users\kovac\AppData\Local\Temp\MSI1AEF.tmp,入口点:EnumerateIISWebSitesAndAppPools MSI (c) (A0:CC) [16:41:21:692]:启用隐形。 MSI (c) (A0:CC) [16:41:21:692]:在调用 Install on Server 之前尝试启用所有禁用的权限 MSI (c) (A0:CC) [16:41:21:692]:连接到 CA 接口的服务。 SFXCA:将自定义操作提取到临时目录:C:\Users\kovac\AppData\Local\Temp\MSI1AEF.tmp-\ SFXCA:绑定到 CLR 版本 v4.0.30319 调用自定义操作 WebAppInstallCustomActions!WebAppInstallCustomActions.CustomActions.EnumerateIISWebSitesAndAppPools 枚举 IISWebSitesAndAppPools:开始 EnumerateIISWebSitesAndAppPools:尝试在没有管理员权限的情况下运行 CustomAction EnumerateIISWebSitesAndAppPools 返回实际错误代码 1603(请注意,如果在沙箱内进行翻译,这可能不是 100% 准确) 操作于 16:41:23 结束:枚举 IISWebSitesAndAppPools。返回值 3。 MSI (c) (A0:B0) [16:41:23:878]:执行操作:FatalError 行动 16:41:23:致命错误。

我试图关注文章 - 我只知道我应该使用 Impersonate="no" 运行我的自定义操作,所以我这样做了,但没有成功 附加信息:UAC 没有询问自定义操作是否可以正确运行,它只是结束安装程序...

<CustomAction Id="EnumerateIISWebSitesAndAppPools"
              BinaryKey="WebAppCA"
              DllEntry="EnumerateIISWebSitesAndAppPools"
              Execute="immediate"
              Return="check" Impersonate="no" /> 

另外,我在某处读到需要延迟运行操作 - 但在这种情况下,这是不可能的 - 因为我需要在安装之前为用户列出网站列表。

我的问题是如何以完全权限运行自定义操作 - 启用 UAC,特别是 UAC 与运行 CA 的管理员权限有何关联?感谢任何帮助或任何建议... 由于我不知道重要性和问题域,我宁愿附上用 C# 编写的自定义操作脚本:

/// <summary>
    /// Adds the II7 web sites and the application pool names to the 
    /// ComboBox table in the MSI file.
    /// </summary>
    /// <param name="session">
    /// The installer session.
    /// </param>
    /// <returnenter code heres>
    /// Always returns ActionResult.Success, otherwise rethrows the error
    /// encountered.
    /// </returns>
    /// <exception cref="ArgumentNullException">
    /// Thrown if the <paramref name="session"/> parameter is null.
    /// </exception>
    [CustomAction]
    public static ActionResult EnumerateIISWebSitesAndAppPools(
                                                            Session session)
    

        Debugger.Launch();

        if (null == session)
        
            throw new ArgumentNullException("session");
        

        session.Log("EnumerateIISWebSitesAndAppPools: Begin");

        // Check if running with admin rights and if not, log a message to
        // let them know why it's failing.
        if (false == HasAdminRights())
        
            session.Log("EnumerateIISWebSitesAndAppPools: " +
                        "ATTEMPTING TO RUN WITHOUT ADMIN RIGHTS");
            return ActionResult.Failure;
        

        session.Log("EnumerateIISWebSitesAndAppPools: " +
                                "Getting the IIS 7 management object");
        ActionResult result;
        using (ServerManager iisManager = new ServerManager())
        
            result = EnumSitesIntoComboBox(session, iisManager);
            if (ActionResult.Success == result)
            
                result = EnumAppPoolsIntoComboBox(session, iisManager);
            
        

        session.Log("EnumerateIISWebSitesAndAppPools: End");
        return result;
    

私有静态 ActionResult EnumSitesIntoComboBox(Session session, 服务器管理器 iisManager) 尝试 // Debugger.Break(); session.Log("EnumSites: Begin");

            // Grab the combo box but make sure I'm getting only the one 
            // from WebAppInstallDlg.
            View view = session.Database.OpenView(
           "SELECT * FROM ComboBox WHERE ComboBox.Property='WEBSITE_NAME'");
            view.Execute();

            Int32 index = 1;
            session.Log("EnumSites: Enumerating the sites");
            foreach (Site site in iisManager.Sites)
            
                // Create a record for this web site. All I care about is
                // the name so use it for fields three and four.
                session.Log("EnumSites: Processing site: 0", site.Name);
                Record record = session.Database.CreateRecord(4);
                record.SetString(1, "WEBSITE_NAME");
                record.SetInteger(2, index);
                record.SetString(3, site.Name);
                record.SetString(4, site.Name);

                session.Log("EnumSites: Adding record");
                view.Modify(ViewModifyMode.InsertTemporary, record);
                index++;
            

            view.Close();

            session.Log("EnumSites: End");
        
        catch (Exception ex)
        
            session.Log("EnumSites: exception: 0", ex.Message);
            throw;
        

        return ActionResult.Success;
    

    static bool HasAdminRights()
    
        WindowsIdentity identity = WindowsIdentity.GetCurrent();
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    

【问题讨论】:

【参考方案1】:

您在 UI 模式下使用对话框收集数据,该对话框将设置一堆属性,然后您可以在没有 UI 的延迟自定义操作中使用这些属性。如果您将包 InstallPrivileges 设置为提升,则延迟 CA 会以您需要的权限运行。如果您真的想在您编写的代码中执行所有这些操作,请在安装后使用提升清单运行它以配置网站的内容。

或者只是看看 WiX IIS 扩展是否能满足您的需求。或者也许是这样: http://www.codeproject.com/Articles/115036/Creating-WIX-Installer-for-ASP-NET-Web-Application

这一切都已经做过很多次了,不值得再次重新发明它。

【讨论】:

我忘了特别强调我真正面临的问题 - 我得到了自定义对话框,其中充满了可用网站的名称 + 应用程序池 + 文本字段来选择 IIS 上的虚拟目录,所以我需要在安装之前(知道在哪里复制) - 对于这个任务,我调用上面的自定义操作来枚举到组合框 - 在安装开始之前。我正在使用正确安装的 IIS 扩展,但是 UAC 使得它很难恕我直言 如果自定义对话框是 MSI 早期 UI 序列的一部分,那么 Chris 的回答适用。除非您使用提升的启动器启动 MSI,否则 UI 序列不会提升。这就是为什么许多人事后使用独立的配置程序来执行此操作的原因。此外,作为开发人员,这么多的 UI 选择可能会很有趣,但安装应该继续进行并做一些有效的事情。除非您的客户是专家,否则他们怎么知道要做出哪些选择?应该向客户展示一堆可供选择的信息的想法通常不是一个友好的选择。 感谢您的评论,它启发了我更多地用开箱即用的方式来看待问题【参考方案2】:

在 UI 序列中安排的所有 ca 都必须是即时的。模拟不适用于直接 ca。最佳实践是不提升 UI,因此最佳实践表明 CA 不应要求提升权限。如果没有办法解决这个问题,您需要使用引导程序来调用 MSI 并在调用它之前提升它。

【讨论】:

似乎这对我来说很难事实,因为我需要检索该信息......但我仍然不明白 W7 UAC 是如何修改访问权限的 - 我认为 UAC 应该负责通知用户如果即将进行任何更改,但从这种情况看来,它包括在安装期间应用的访问权限,我没有得到太多...... 现在我遇到了很多问题:我不太确定模拟概念 - 它是如何工作的 - 如果设置为“是”,则安装程序的过程将以当前用户的访问权限执行 - 但是我是使用管理员帐户登录,那么我应该已经拥有完整的权限。如果模拟设置为 NO - 执行什么正确的自定义操作?如果我以完全管理员权限运行 msi,默认情况下,权限是否会在自定义操作上应用相同的权限 - 或者是否有模拟对其执行任何操作?感谢初学者的任何反应或来源 UAC 通过向管理员提供标准用户权限令牌集来工作。当您请求提升时,您会得到全套。模拟设置用于延迟的自定义操作,并控制它是模拟调用用户还是在不模拟的情况下运行并因此调用为 SYSTEM。这是可能的,因为执行序列作为 Windows 服务在服务器端运行,以 SYSTEM 身份运行。 感谢 Christopher,例如,如果 SYSTEM 运行任何东西,它总是 - 在这种情况下,自定义操作具有“完整的特权令牌集”,对吗?但是如果我在没有模拟的情况下运行,那么我仍然应该拥有完整的权限 - 我以具有管理员权限的用户身份登录,那么在这种情况下将模拟设置为 NO 来运行自定义操作有什么意义? 这里有一点很奇怪——我们使用了以前通过 vdproj 生成的安装程序——它允许我们将 IIS 信息加载到 UI 序列,而无需用户设置提升的权限。我不清楚这是如何完成的,他们是否以某种方式提取有关 IIS 站点的信息而不需要特权,或者他们如何避免它或是否存在任何本机支持?

以上是关于wix customaction UAC dtf的主要内容,如果未能解决你的问题,请参考以下文章

以提升用户身份在 wix 中运行 CustomAction

Wix:无法从Wix CustomAction调用DISM

从对话框调用 CustomAction 时出现 WiX 安装错误 2762

具有提升权限的 WiX CustomAction SCHTASKS“拒绝访问”

Wix Toolset CustomAction 用于确定操作系统是 windows 7/xp 家庭版还是入门版,并显示消息不是

WiX-Bootstrapper - 为 UAC 对话框设置产品名称和公司名称