是否可以导出SqlString编辑的字符串的结果?

时间:2013-10-02 10:45:23

标签: sql wix wix-extension database-installation

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

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

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

示例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]

1 个答案:

答案 0 :(得分:0)

我用一个相当奇怪的解决方案解决了这个问题。我编写了一个CustomAction,它从SqlString表中提取String元素,然后用存储在会话中的相应属性替换格式化的字段。要访问会话变量,必须将CustomAction执行为immediate。我已经在InstallFinalize之前安排了它,可以访问PersonalFolder属性。使用此属性,我可以存储由用户Documents目录中的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;
        }
    }
}