SQL 具有 Visual Studio 2017 安装程序项目的服务器命名实例

SQL Server named instance with Visual Studio 2017 Installer project

软件:

  1. SQL 服务器 Express 2016
  2. Visual Studio 2017

我们一直在尝试获取 SQL Server Express 2016 的命名实例作为 VS 安装程序安装项目的一部分进行安装,但没有成功。

我们已尝试按如下方式调用 InstallNamedInstance() 并得到给定结果:

  1. 运行 SQLEXPR_x64_ENU.exe 具有来自管理员 cmd 的相同命令行参数 window:成功
  2. 从控制台应用程序调用 InstallNamedInstance() 并从管理员 cmd 运行 控制台应用程序调用 window:成功
  3. 安装自定义操作(所有人和只有我):失败
  4. BeforeInstall 事件(所有人和只有我):失败

我注意到当 msi 运行s 是 NT AUTHORITY\SYSTEM 时当前用户。每当安装程序项目失败时,它都会失败并显示以下消息:

The account that is running SQL Server Setup does not have one or all of the following rights: the right to back up files and directories, the right to manage auditing and the security log and the right to debug programs. To continue, use an account with both of these rights. For more information, see http://msdn.microsoft.com/en-us/library/ms813696.aspx, http://msdn.microsoft.com/en-us/library/ms813959.aspx and http://msdn.microsoft.com/en-us/library/ms813847.aspx.

这是安装程序项目的限制还是我遗漏了什么?我们使用 AdvancedInstaller 会好运吗?

请注意,安装程序项目的先决条件对我们不起作用,因为我们必须创建 SQL Server Express 的命名实例,而且我们无法看到如何将命令行参数传递给先决条件。

private void InstallNamedInstance()
{
    // NOTE: Change below instance name to get unique instances (or uninstall previous instance)
    var InstanceName = "TFPICDATABASES2";
    var proc = new Process();
    // NOTE:
    //  1. Download "SQLServer2016-SSEI-Expr.exe" web installer from https://www.microsoft.com/en-us/download/details.aspx?id=54284
    //  2. Run the web installer and choose 3rd option "Download Media". This will give "SQLEXPR_x64_ENU.exe"
    proc.StartInfo.FileName = @"c:\temp\sql\SQLEXPR_x64_ENU.exe ";
    proc.StartInfo.Arguments = " /Action=Install";
    proc.StartInfo.Arguments += $" /INSTANCEID={InstanceName}";
    proc.StartInfo.Arguments += $" /InstanceName={InstanceName}";
    proc.StartInfo.Arguments += " /ROLE=AllFeatures_WithDefaults";
    proc.StartInfo.Arguments += " /QS";
    proc.StartInfo.Arguments += " /INDICATEPROGRESS=True";
    proc.StartInfo.Arguments += " /IAcceptSQLServerLicenseTerms=True";
    proc.StartInfo.WorkingDirectory = @"c:\temp\sql";

    WriteLog($"FielName: {proc.StartInfo.FileName}; Arguments: {proc.StartInfo.Arguments}; WorkingDir: {proc.StartInfo.WorkingDirectory}");

    proc.StartInfo.UseShellExecute = false;
    proc.OutputDataReceived += (s, e) => WriteLog($"Info: {e.Data}");
    proc.ErrorDataReceived += (s, e) => WriteLog($"Error: {e.Data}");

    var ok = proc.Start();
    // NOTE: Log files are in C:\Program Files\Microsoft SQL Server0\Setup Bootstrap\Log
    // Summary.txt gives log of latest installer run. It also creates one folder for each installer attempt
    // and gathers more detailed logs in those folders.
    proc.WaitForExit();
    WriteLog($"{proc.StartInfo.FileName} exited with {proc.ExitCode}");
    if (proc.ExitCode != 0)
    {
        throw new Exception($"SQL Server Express installation failed. Check log file for more details");
    }
}

Summary: In essence, the below states: 1) Disable the custom action to run the SQL Server setup.exe in your current MSI. 2) Create a basic WiX Burn Bundle to kick off the SQL Server setup.exe first, and then kick off your Visual Studio Installer Project-generated MSI afterwards. Or better yet, make the whole MSI in WiX as well. Commercial tools such as Advanced Installer and Installshield are viable options - they feature support for this that is built-in (features vary depending on version of prerequisite).

Burn Bundle-Mockup (inspiration, more inspiration):

只是为了展示 WiX Burn 标记的工作原理:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" 
     xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

  <Bundle Name="MyCoolTestApp" Version="1.0.0.0" 
          Manufacturer="Someone" UpgradeCode="PUT-GUID-HERE">

    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />

    <util:FileSearch Path="[WindowsFolder]System32\ucrtbase.dll" Variable="VCDISTINSTALLED"/>

    <Chain>

      <ExePackage SourceFile="vc_redist.x64.exe"
                  DetectCondition="VCDISTINSTALLED"
                  InstallCommand="/q /ACTION=Install"
                  RepairCommand="/q ACTION=Repair /hideconsole" />

      <MsiPackage SourceFile="ShortcutDesktop.msi" />

    </Chain>
  </Bundle>
</Wix>

技术原因:我不是 Visual Studio 安装程序项目的专家 - 不得不说 - 每次都是。然而,正如您所发现的,这些项目有许多限制和怪癖。其中一个怪癖是所有自定义操作 运行 在延迟模式和系统上下文中(运行 宁作为本地系统)没有启动用户的模拟。这可能是所见问题的原因 - 正如您自己所说。

虽然可以 从 VS 安装程序项目中获取,但最好不要使用自定义操作来启动 SQL 服务器安装。更多细节如下。 post 处理将涉及将自定义操作类型从 3078 更改为 1030,以便启用用户模拟 - 这也意味着自定义操作不会 运行 顺便提升 - 因此只有在整个 MSI高架发射。


注意:下面我建议使用 WiX 的刻录功能(开源),或等效的商业工具。 WiX 的刻录功能可用于 Visual Studio 2017 安装程序项目创建的 MSI 文件,或任何其他工具创建的 MSI 文件(也包括 EXE 文件)。您只需将 VS2017 生成的 MSI 插入 WiX 包(或 EXE 文件)。 WiX 显然也可以自己创建 MSI 文件(这就是框架的用途)。 WiX quick start links.


MSI 技术怪癖:从 MSI 自定义操作启动其他安装程序不是好的做法。如果另一个安装程序是另一个 MSI(而不仅仅是非 MSI setup.exe),那么由于技术限制甚至不可能可靠地安装(没有两个 MSI InstallExecuteSequences 可以同时 运行 因为 a mutex that is set during installation)。换句话说:并发 MSI 安装是被禁止的并且在技术上是不可能的。

Burn:输入WiX's Burn feature - downloader / bootstrapper / sequencer 工具,运行s 从它自己的包装器 setup.exe 中按顺序打包安装。它可以安装 MSI 文件、EXE 文件和其他类型的包 - 一个接一个,没有像 MSI 的互斥体那样的技术限制。串行,非并行 运行ning.

SQL Server Install: 您可以通过这样的 Burn 启动 SQL Server EXE 安装程序bundle,您可以将列出的参数指定为命令行参数,而不是在托管代码中这样做(需要 运行 时间要求)。然后你从同一个包开始你的主 MSI。

Burn Crash Course:Burn 有一个学习曲线。它是 "fiddly"(它是代码/标记 - 总是很繁琐),但它非常灵活。我想补充一点 Advanced Installer 似乎对 SQL Server deployment, even if have never had the time to investigate properly in detail. Installshield can install EXE files and MSI files in sequence using its Suite projects 功能有很好的支持(查看链接的屏幕截图)。不确定总体 SQL 服务器支持。

一些刻录示例链接:


部分链接:

我怀疑您的自定义操作在 SYSTEM 帐户下失败是因为这些文章中提到的错误:

在高级安装程序中,安装 SQL 服务器的自定义操作不在系统帐户 运行 下,它 运行 在启动安装的帐户下 (必须有管理员凭据)。自定义操作(由 Advanced Installer 捆绑的专用 exe 启动器)配置为需要管理员提升(我怀疑您无法在 VS 中配置),因此 SQL 服务器的安装过程是 运行ning 使用机器的常规用户帐户提升的,而不是 NT SYSTEM。