I'm currently working on a WIX 3.8 setup project which should deploy a database on installation. If the database already exists, the database should be updated using scripts. The bad thing is that I'm not able to distinguish between these two cases. The following lines present my current stuff:
<Property Id="SQLDATABASEEXISTS" Value="dummy" />
<Binary Id="CustomActions" SourceFile="..\CustomActions\bin\$(var.Configuration)\CustomActions.CA.dll" />
<CustomAction Id="CheckDatabaseExistence" BinaryKey="CustomActions" DllEntry="CheckSqlServerExistence" Return="check" Execute="immediate" />
<InstallExecuteSequence>
<Custom Action="CheckDatabaseExistence" Before="CostFinalize" />
</InstallExecuteSequence>
<util:User Id="SqlUser" Name="username" Password="password" />
<sql:SqlDatabase Id="SqlExistingDatabase" Database="Data_[CUSTOMER_NAME]" Instance="SQLEXPRESS" Server="." User="SqlUser" />
<Binary Id="SqlCreateScript" SourceFile="SqlCreateScript.sql" />
<Binary Id="SqlUpdateScript" SourceFile="SqlUpdateScript.sql" />
<ComponentGroup Id="DatabaseComponents">
<Component Id="DBNewDatabase" Directory="DATA_DIR" Guid="*" KeyPath="yes">
<Condition><![CDATA[NOT SQLDATABASEEXISTS]]></Condition>
<sql:SqlDatabase Id="SqlNewDatabase" Database="Data_[CUSTOMER_NAME]" ConfirmOverwrite="yes" CreateOnInstall="yes" CreateOnReinstall="yes" CreateOnUninstall="no" DropOnInstall="no" DropOnReinstall="no" DropOnUninstall="no" Instance="SQLEXPRESS" Server="." User="SqlUser">
<sql:SqlFileSpec Id="SqlDatabaseDataFile" Name="DB_Data" Filename="C:\DB\[CUSTOMER_NAME]\DB_Data.mdf" />
<sql:SqlLogFileSpec Id="SqlDatabaseLogFile" Name="DB_Log" Filename="C:\DB\[CUSTOMER_NAME]\DB_Data.ldf" />
<sql:SqlScript Id="SqlCreateScript" ExecuteOnInstall="yes" ExecuteOnReinstall="yes" ExecuteOnUninstall="no" BinaryKey="SqlCreateScript" />
</sql:SqlDatabase>
</Component>
<Component Id="DBExistingDatabase" Directory="DATA_DIR" Guid="*" KeyPath="yes">
<Condition><![CDATA[SQLDATABASEEXISTS]]></Condition>
<sql:SqlScript Id="SqlUpdateScript" ExecuteOnInstall="yes" ExecuteOnReinstall="yes" ExecuteOnUninstall="no" BinaryKey="SqlUpdateScript" User="SqlUser" SqlDb="SqlExistingDatabase" />
</Component>
</ComponentGroup>
The CustomAction code is as simple as:
[CustomAction]
public static ActionResult CheckSqlServerExistence(Session session)
{
session.Log("Begin CheckSqlServerExistence");
string connectionString = @"Data Source=.\SQLEXPRESS;Connect Timeout=60;Initial Catalog=Data_" + session["CUSTOMER_NAME"] + @";Persist Security Info=True;User ID=username;Password=password";
try
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
connection.Close();
session["SQLDATABASEEXISTS"] = "true";
}
catch (Exception ex)
{
session.Log("Database connection not possible. Database treated as not existing. Exception: " + ex.Message);
session["SQLDATABASEEXISTS"] = "false";
}
session.Log("Database exists: " + session["SQLDATABASEEXISTS"]);
return ActionResult.Success;
}
The current behavior is that the setup always executes the "update case". So I modified the condition also to
<Condition><![CDATA[SQLDATABASEEXISTS = "false"]]></Condition>
and
<Condition><![CDATA[SQLDATABASEEXISTS = "true"]]></Condition>
but this didn't help either.
What is it that I'm doing wrong?
I found a solution for this one:
<Custom Action="CheckDatabaseExistence" After="CostInitialize" />
and conditions:
<Condition><![CDATA[SQLDATABASEEXISTS = "false"]]></Condition>
<Condition><![CDATA[SQLDATABASEEXISTS = "true"]]></Condition>
It seems like CostFinalize
was too late already to get the property value.