我有一个安装数据库的安装程序。数据库与某些登录一起创建。要创建登录,我在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]
答案 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;
}
}
}