2013-10-02 2 views
1

У меня есть программа установки, которая устанавливает базу данных. База данных создается рядом с некоторыми входами. Для создания логинов я использую основную базу данных в элементах SqlString. Доступ к основной базе данных предоставляется только тем пользователям, которые имеют очень высокие привилегии на сервере SQL. Зачастую установка прерывается, поскольку строка SQL, предназначенная для основной базы данных, не может быть выполнена из-за отсутствия прав.Можно ли экспортировать результат строк, отредактированных SqlString?

Я хочу отредактировать мой установщик, так что, когда элемент 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"/> 

Пример файла SQL Я хотел бы иметь после того, как SqlStrings потерпели неудачу:

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] 

ответ

0

Я решил эту проблему с довольно нечетным раствором. Я написал CustomAction, который извлекает элементы String из таблицы SqlString и затем заменяет отформатированные поля соответствующими Свойствами, сохраненными в сеансе. Чтобы получить доступ к переменной сеанса, CustomAction должен быть выполнен как immediate. Я запланировал его до InstallFinalize, чтобы получить доступ к объекту PersonalFolder. С помощью этого свойства я могу хранить скрипт Sql, сгенерированный записями в таблице SqlScript в каталоге «Документы пользователей». Чтобы учитывать различные базы данных в установке, я включил поиск в таблицу 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; 
     } 
    } 
}