简体   繁体   English

使用WIX创建安装程序时执行sqlpackage.exe(具有很少的相关dll)

[英]Execute sqlpackage.exe (which has few dependent dlls) while creating installer using WIX

I need to deploy dacpac while installing database using WIX. 使用WIX安装数据库时,我需要部署dacpac。 For the purpose, I have considered to run SQLPackage.exe command with necessary switches so I have embedded the necessary exe and dlls using binary tags as follows 为此,我考虑过使用必要的开关运行SQLPackage.exe命令,因此我使用二进制标记嵌入了必要的exe和dll,如下所示

<Binary Id="Microsoft.Data.Tools.Schema.Sql.dll" SourceFile="..\DeployDBs\DAC\Microsoft.Data.Tools.Schema.Sql.dll"/>
    <Binary Id="Microsoft.Data.Tools.Schema.Tasks.Sql.11.dll" SourceFile="..\DeployDBs\DAC\Microsoft.Data.Tools.Schema.Tasks.Sql.11.dll"/>
    <Binary Id="Microsoft.Data.Tools.Schema.Utilities.Sql.11.dll" SourceFile="..\DeployDBs\DAC\Microsoft.Data.Tools.Schema.Utilities.Sql.11.dll"/>
    <Binary Id="Microsoft.Data.Tools.Utilities.dll" SourceFile="..\DeployDBs\DAC\Microsoft.Data.Tools.Utilities.dll"/>
    <Binary Id="Microsoft.SqlServer.Dac.dll" SourceFile="..\DeployDBs\DAC\Microsoft.SqlServer.Dac.dll"/>
    <Binary Id="SqlPackage" SourceFile="..\DeployDBs\DAC\SqlPackage.exe"/>
    <Binary Id="SqlPackage.exe.config" SourceFile="..\DeployDBs\DAC\SqlPackage.exe.config"/>

And calling the SqlPackage.exe using the custom action as follows 并使用以下自定义操作调用SqlPackage.exe

 <CustomAction Id="DeployMyDb" BinaryKey="SqlPackage" 
              ExeCommand="/a:publish /sf:&quot;MyDacpac.dacpac&quot; /tsn:localhost /tdn:MyDb" 
              Execute="immediate" />

The custom action is sequences to run after 'InstallFinalize' as follows 自定义操作是在“ InstallFinalize”之后运行的序列,如下所示

<InstallExecuteSequence>
      <Custom Action="DeployMyDb" After="InstallFinalize"/>
    </InstallExecuteSequence>
    </Product>

When the dacpac is deployed (ie the custom action is run), it throws the 'FileNotFoundException' for the assembly 'Microsoft.Data.Tools.Utilities which is one of the embedded binary. 部署dacpac时(即,运行自定义操作),它将为程序集“ Microsoft.Data.Tools.Utilities”抛出“ FileNotFoundException”,该程序集是嵌入式二进制文件之一。

Please advise on the missing steps or additions things needed to be done to run this exe. 请告知缺少的步骤或添加内容,以运行此exe文件需要做的事情。

I found the solution. 我找到了解决方案。

Instead of above approach, I created a separate project for custom action and added the references to the required binaries (ie the Binaries I previously mentioned in <binary> tags) and added the corresponding dll formed in the binary tag and called it via <CustomAction> 代替上述方法,我创建了一个单独的项目来执行自定义操作,并将引用添加到所需的二进制文件(即我先前在<binary>标记中提到的Binaries),并添加了在二进制标记中形成的相应dll,并通过<CustomAction对其进行了调用>

The resultant solution is as follows: 产生的解决方案如下:

<Binary Id="InstallerWix_CustomAction.CA.dll" SourceFile="..\InstallerWix_CustomAction\bin\Debug\InstallerWix_CustomAction.CA.dll" />

<CustomAction Id="DeployDb" BinaryKey="InstallerWix_CustomAction.CA.dll" 
                 DllEntry="CustomAction1"                   
                  Execute="immediate" Return="check" />

<InstallExecuteSequence>
  <Custom Action="DeployDb" After="InstallFinalize"/>
</InstallExecuteSequence>

I was able to implement this by adding the dacpac file as a binary, reading that binary in the CustomAction, and finally using 'Microsoft.SqlServer.Dac' (available on nuget) in my C# custom action. 我可以通过将dacpac文件添加为二进制文件,在CustomAction中读取该二进制文件并最终在C#自定义操作中使用“ Microsoft.SqlServer.Dac”(在nuget上可用)来实现此目的。

I had to write the binary file stream into a MemoryStream for use with the DacPac.Load function. 我必须将二进制文件流写入MemoryStream以便与DacPac.Load函数一起使用。 The binary stream was an internal type of 'RecordStream' that was unusable by the Load function. 二进制流是内部的“ RecordStream”类型,Load函数无法使用它。 For your purposes, you may also want to modify the dacOptions variable to give you the desired result. 为了您的目的,您可能还希望修改dacOptions变量以提供所需的结果。

See my examples below: 请参阅下面的示例:

Project.wxs: Project.wxs:

<Binary Id="Database.dacpac" SourceFile="$(var.ProjectDir)\Database.dacpac" />

<CustomAction Id="DeployDacpac" BinaryKey="CustomAction.dll" DllEntry="DeployDacpac" Execute="immediate" />

<InstallExecuteSequence>
  <Custom Action="DeployDacpac" After="InstallFinalize" />
</InstallExecuteSequence>

CustomAction.cs: CustomAction.cs:

[CustomAction]
    public static ActionResult DeployDacpac(Session session)
    {
        try
        {
            string sql = string.Format("SELECT Data FROM Binary WHERE Name = 'Database.dacpac'");

            View view = session.Database.OpenView(sql);

            view.Execute();
            var dataStream = view.First()["Data"] as Stream;
            byte[] buffer = new byte[dataStream.Length];
            int bytesRead;
            while ((bytesRead = dataStream.Read(buffer, 0, buffer.Length)) > 0) ;
            using (MemoryStream ms = new MemoryStream(buffer))
            {
                var dacOptions = new DacDeployOptions();
                dacOptions.BlockOnPossibleDataLoss = false;
                dacOptions.DropDmlTriggersNotInSource = false;
                dacOptions.DropObjectsNotInSource = false;

                var dacServiceInstance = new DacServices(GenerateConnectionString(session["SQLSERVER"], session["SQLDATABASE"], session["SQLUSER"], session["SQLPASSWORD"]));
                using (DacPackage dacpac = DacPackage.Load(ms))
                {
                    dacServiceInstance.Deploy(dacpac, session["SQLDATABASE"], upgradeExisting: true, options: dacOptions);
                }
            }
        }
        catch (Exception ex)
        {
            session.Log(ex.Message);
            return ActionResult.Failure;
        }
        return ActionResult.Success;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM