1

我有一个安装数据库的安装程序。该数据库是与一些登录名一起创建的。为了创建登录,我在 SqlString 元素中使用主数据库。只有在 SQL 服务器上具有非常高权限的用户才能访问 master 数据库。由于缺少权限而无法执行为 master 数据库指定的 SQL 字符串,因此安装通常会中止。

我想编辑我的安装程序,以便当无法执行 SqlString 元素时,将跳过安装的 SQL 部分。安装完成后,我希望用户能够自己执行 SQL 语句。我的安装程序执行的每个 SQL 操作都存储在 SqlString 元素中。SqlString 元素包含许多在安装过程中被替换的属性。我想将所有已编辑的 SqlString 元素的内容提取到一个存储在用户目录中的 sql 文件中。

我想我必须编写一个在 sqlextension 替换属性之后发生的 customaction。然后我将不得不访问这些更改的字符串。有什么办法可以做到这一点吗?

示例 SqlString 元素:

    <sql:SqlDatabase Id="MasterDB" Server="[SQLSERVER_SERVER]" Instance="[SQLSERVER_INSTANCENAME]" Database="master" />

<sql:SqlString
      SqlDb="MasterDB"
      Id="CreateNetworkServiceAccount"
      ExecuteOnInstall="yes"
      ContinueOnError="no"
      SQL="IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'{[WIX_ACCOUNT_NETWORKSERVICE]}')
        CREATE LOGIN [\[]{[WIX_ACCOUNT_NETWORKSERVICE]}[\]] FROM WINDOWS WITH DEFAULT_DATABASE=[\[]master[\]]"
      Sequence="101"/>

SqlStrings 失败后我想要的 sql 文件示例:

USE master;
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'NT AUTHORITY\Network Service')
CREATE LOGIN [NT AUTHORITY\Network Service] FROM WINDOWS WITH DEFAULT_DATABASE=[master]
4

1 回答 1

0

我用一个相当奇怪的解决方案解决了这个问题。我编写了一个 CustomAction,它从 SqlString 表中提取字符串元素,然后用存储在会话中的适当属性替换格式化的字段。要访问会话变量,CustomAction 必须以immediate. 我之前已经安排它InstallFinalize可以访问该PersonalFolder物业。使用此属性,我可以将由用户文档目录中的 SqlScript 表中的条目生成的 Sql 脚本存储起来。为了说明安装中的不同数据库,我在 SqlDatabase 表中包含了一个查找。

这是 CustomAction 的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Deployment.WindowsInstaller;
using System.IO;
using System.Text.RegularExpressions;

namespace SaveSqlStrings
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult SaveSqlStrings(Session session)
        {
            StringBuilder sqlStrings = new StringBuilder();
            Database db = session.Database;
            View view = db.OpenView("SELECT * FROM `SqlString`");
            IList<string> SqlStringElements = db.ExecuteStringQuery("SELECT `String` FROM `SqlString`");
            Regex bracketedProperties = new Regex(@"\[(\b[A-Z_]*\b)\]");
            Regex formattedProperties = new Regex(@"{\[(\b[A-Z_]*\b)\]}");
            Regex openeningSquareBrackets = new Regex(@"\[\\\[\]");
            Regex closingSquareBrackets = new Regex(@"\[\\\]\]");
            string sqlDb_ = "";
            string sqlString = "";
            string Database = "";
            foreach (string dbString in SqlStringElements)
            {
                sqlDb_ = (string)db.ExecuteScalar("SELECT `SqlDb_` FROM `SqlString` WHERE `String` ='{0}'",dbString);
                sqlString = (string)db.ExecuteScalar("SELECT `SQL` FROM `SqlString` WHERE `String` ='{0}'",dbString);
                view.Close();
                view = db.OpenView("SELECT * FROM `SqlDatabase`");
                Database = (string)db.ExecuteScalar("SELECT `Database` from `SqlDatabase` WHERE `SqlDb`='{0}'", sqlDb_);
                if(bracketedProperties.IsMatch(Database))
                {
                    Database = bracketedProperties.Match(Database).Groups[1].Value;
                    Database = session[Database];
                }
                if (openeningSquareBrackets.IsMatch(sqlString))
                    sqlString = openeningSquareBrackets.Replace(sqlString, "[");
                if (closingSquareBrackets.IsMatch(sqlString))
                    sqlString = closingSquareBrackets.Replace(sqlString, "]");
                if(formattedProperties.IsMatch(sqlString))
                {
                    string propertyName = formattedProperties.Match(sqlString).Groups[1].Value;
                    string propertyValue = session[propertyName];
                    sqlString = formattedProperties.Replace(sqlString, propertyValue);
                }
                sqlStrings.AppendLine(String.Format("use {0}",Database));
                sqlStrings.AppendLine(sqlString);
            }
            string home = session["PersonalFolder"];
            string sqlPath = string.Concat(home, @"Script.sql");
            try
            {
                File.WriteAllText(sqlPath, sqlStrings.ToString());
            }
            catch (Exception ex)
            {
                session["FailedTowrite"] = sqlPath;
            }
            view.Close();
            db.Close();
            return ActionResult.Success;
        }
    }
}
于 2013-10-11T14:28:14.233 回答