wix习惯UAC dtf

时间:2015-01-20 16:07:36

标签: iis-7 wix uac custom-action

我正在为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 EnumerateIISWebSitesAndAppPools:开始 EnumerateIISWebSitesAndAppPools:尝试在没有管理员权限的情况下运行 CustomAction EnumerateIISWebSitesAndAppPools返回实际的错误代码1603(请注意,如果在沙箱中发生翻译,这可能不是100%准确) 行动结束16:41:23:EnumerateIISWebSitesAndAppPools。返回值3。 MSI(c)(A0:B0)[16:41:23:878]:采取行动:致命错误 行动16:41:23:FatalError。

我试图关注文章 - 我只是理解的是我应该使用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;
    }

private static ActionResult EnumSitesIntoComboBox(Session session,                                                        ServerManager 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);
    }

2 个答案:

答案 0 :(得分:1)

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

或者只是看看WiX IIS扩展程序是否可以执行您想要的操作。或许这个: http://www.codeproject.com/Articles/115036/Creating-WIX-Installer-for-ASP-NET-Web-Application

之前已经做了很多次,不值得重新发明它。

答案 1 :(得分:0)

在UI序列中安排的所有内容都必须立即生效。假冒并不适用于直接的ca。最佳实践是UI不会被提升,因此最佳实践表明CA不应该要求提供私有权限。如果无法解决这个问题,您需要使用引导程序来调用MSI并在调用它之前将其提升。