2014-09-01 2 views
2

WIX를 사용하여 데이터베이스를 설치하는 동안 dacpac을 배포해야합니다. 내가WIX를 사용하여 설치 프로그램을 만드는 동안 sqlpackage.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"/> 

을 다음과 같이 이진 태그를 사용하여 그리고

를 다음과 같이 사용자 지정 작업을 사용하여 SqlPackage.exe를 호출 필요한 EXE 및 DLL을 내장 한 있도록 목적을 위해, 나는 필요한 스위치 SQLPackage.exe 명령을 실행하는 것으로 간주 한
<CustomAction Id="DeployMyDb" BinaryKey="SqlPackage" 
       ExeCommand="/a:publish /sf:&quot;MyDacpac.dacpac&quot; /tsn:localhost /tdn:MyDb" 
       Execute="immediate" /> 

사용자 지정 작업은 dacpac가 배포

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

을 다음과 같이 순서가 'InstallFinalize를'후 실행하는 것입니다 (사용자 지정 작업이 실행되는 IE) 임베디드 바이너리 중 하나 인 어셈블리 인 'Microsoft.Data.Tools.Utilities'에 대해 'FileNotFoundException'을 발생시킵니다.

이 exe를 실행하려면 수행해야 할 단계가 없거나 추가 사항에 대해 조언하십시오.

답변

3

해결책을 찾았습니다. 대신 위의 접근 방식의

, 나는 사용자 지정 작업에 대해 별도의 프로젝트를 생성하고 필요한 바이너리에 대한 참조를 추가 바이너리 태그에 형성된 해당 DLL을 추가라는 (내가 이전에 < 진 > 태그에 언급 된 바이너리 즉) 다음과 같이이 <에서 CustomAction >

를 통해 생성 된 솔루션입니다 :

<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> 
+0

당신은 어떻게 위로 SqlPackage.exe를 내장 바람습니까? –

+1

사용자 지정 작업 프로젝트. 관련된 다른 바이너리뿐만 아니라 SqlPackage.exe도 임베드되었습니다. – yash

2

난에서 CustomAction에서 바이너리를 읽고, 바이너리로 dacpac 파일을 추가하고, 마지막으로 '미를 사용하여이를 구현 할 수 있었다 crosoft.SqlServer.Dac '(너겟에서 사용 가능)을 C# 사용자 지정 작업에 사용합니다.

은 내가 DacPac.Load 기능을 사용하기위한 MemoryStream을로 이진 파일 스트림을 작성했다. 이진 스트림은 'RecordStream'의 내부 형식으로,로드 기능으로는 사용할 수 없습니다. 목적에 따라 dacOptions 변수를 수정하여 원하는 결과를 얻을 수도 있습니다.

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] 
    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; 
    }