1

データベースをインストールするインストーラーがあります。データベースは、いくつかのログインとともに作成されます。ログインを作成するために、SqlString 要素で master データベースを使用しています。master データベースへのアクセスは、SQL サーバーに対して非常に高い権限を持つユーザーにのみ許可されます。多くの場合、権限がないためにマスター データベース用に指定された SQL 文字列を実行できないため、インストールが中止されます。

SqlString 要素を実行できない場合、インストールの SQL 部分がスキップされるように、インストーラーを編集したいと考えています。インストールが行われた後、ユーザーが自分で SQL ステートメントを実行できるようにしたいと考えています。インストーラーが実行するすべての SQL アクションは、SqlString 要素に格納されます。SqlString 要素には、インストール中に置き換えられる多くのプロパティが含まれています。編集したすべての SqlString 要素の内容を、ユーザー ディレクトリに格納されている 1 つの 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

私はかなり奇妙な解決策でこの問題を解決しました。SqlString テーブルから文字列要素を抽出し、書式設定されたフィールドをセッションに格納されている適切なプロパティに置き換える CustomAction を作成しました。セッション変数にアクセスするには、CustomAction を として実行する必要がありますimmediate。プロパティInstallFinalizeへのアクセスを許可する前にスケジュールしました。PersonalFolderこのプロパティを使用すると、SqlScript テーブルのエントリによって生成された Sql スクリプトをユーザーの Documents ディレクトリに保存できます。インストールでさまざまなデータベースを説明するために、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 に答える