Drop database from WiX installer - database

The properties [DATABASE_NAME] and [SERVER_NAME] are defined by the user at installation and it seems like unless they are hard coded then doing this fails:
<Component Id="Component.Sql.Database" Guid="*">
<sql:SqlDatabase
Id="Sql.Database"
Database="[DATABASE_NAME]"
Server="[SERVER_NAME]"
CreateOnInstall="yes"
DropOnUninstall="yes"
ContinueOnError="no"
ConfirmOverwrite="yes" />
</Component>
The bit that is supposed to drop the db is DropOnUninstall="yes"
I've found a post on the WiX user group suggesting the following approach to dropping the database on uninstall:
<Component Id="Component.Sql.DropDatabase" Guid="146CD264-1F6D-4E19-BFCC-E544F5BD2D6C">
<sql:SqlString
Id="Sql.DropDatabase"
SqlDb="Sql.Master"
Sequence="1000"
ExecuteOnInstall="no"
ExecuteOnUninstall="yes"
ExecuteOnReinstall="no"
ContinueOnError="no"
SQL="DROP DATABASE [\[][DATABASE_NAME]\[]]"/>
</Component>
<Fragment>
<sql:SqlDatabase Id="Sql.Master" Database="master" Server="[SERVER_NAME]" />
</Fragment>
The idea being that at uninstall the DROP DATABASE ... command is executed on the master database on the server. However this SQL statement never gets executed on the server.
The MSIEXEC log doesn't seem to give any information and I get no errors.
Has anyone successfully achieved this (before I write a custom action to do this)?
I've tried copying the database name and server to the registry to cache them, but this hasn't helped.

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" <!-- Need to import this -->
xmlns:sql="http://schemas.microsoft.com/wix/SqlExtension"><!-- Need to import this -->
<sql:SqlDatabase Id="SqlDatabase"
Database="TestDatabase"
Server="[SQLSERVER]"
DropOnUninstall="yes"
User="SQLUser">
This will definitely work.....

Related

WiX Toolset - How to determine the SQL Server DATA path

I've tried to do this a few ways. Here's my latest attempt, which does not work, but should help illustrate what I'm looking to do.
Note: My assumption for the GetSQLServerInstalledInstance Id is that it will return one instance.
My goal is to find the DATA directory path for an instance of SQL Server installed on the machine that will also be installing my companies product.
<util:RegistrySearch Id='GetSQLServerInstalledInstance'
Variable='SQL_SERVER_INSTALLED_INSTANCE'
Root='HKLM'
Key='SOFTWARE\Microsoft\Microsoft SQL Server'
Value="InstalledInstances"
Format="raw" />
<util:RegistrySearch Id='GetSQLServerInstalledInstanceName'
Variable='SQL_SERVER_INSTALLED_INSTANCE_NAME'
Root='HKLM'
Key='SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL'
Value="[SQL_SERVER_INSTALLED_INSTANCE]"
Format="raw"
After="GetSQLServerInstalledInstance" />
<util:RegistrySearch Id='GetSQLServerInstallPath'
Variable='SQL_SERVER_INSTALL_PATH'
Root='HKLM'
Key='SOFTWARE\Microsoft\Microsoft SQL Server\[SQL_SERVER_INSTALLED_INSTANCE_NAME]\Setup'
Value="SQLPath"
Format="raw"
After="GetSQLServerInstalledInstanceName" />
<SetProperty Id='SQL_SERVER_FILE_PATH' Value="[SQL_SERVER_INSTALL_PATH]\DATA" After="CostFinalize" Sequence="first" />
In the end, I'm looking for the SQL_SERVER_FILE_PATH property to contain this path. (e.g. C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA)
It's also important that the calls are sequenced at that subsequent calls can contain information derived from previous calls.
I'm still fairly new to WiX, but I could imagine how to do this pretty easily if the SetProperty element allowed a RegistrySearch child element to set it's value. Can this be handled by a sequence of CustomActions that would act similar to a SetProperty element that allows a RegistrySearch child element to set it's value?
Thanks
I found a simpler method for determining the SQL Server DATA directory path using WiX. For future reference, this was how I solved this:
<Property Id='SQL_SERVER_INSTALL_PATH'>
<RegistrySearch Id='GetSQLServerInstallPath' Root='HKLM'
Key='SOFTWARE\Microsoft\MSSQLServer\Setup'
Name='SQLPath' Type='directory' Win64="yes" />
</Property>
<SetProperty Id='SQL_SERVER_DATA_PATH' Value="[SQL_SERVER_INSTALL_PATH]DATA" After="CostFinalize" Sequence="first" />
Hope this helps others

WiX: Installing to Multiple DB Targets

I have a set of DB scripts that I need to run during install. I have a UI screen that the user can select the server, provide credentials, and then select the target database. What I need to do is install the bulk of the scripts to the target database the user selected but some scripts need to go to the Master DB. I've tried searching the net for answers but I haven't really found anything that tells me how to do that. If someone has an article or suggestion on how this is accomplished, I would appreciate a little help.
Thanks
You can declare two SqlDatabase nodes, one for each database where the scripts have to be run:
<Binary Id="SqlScriptBinary1" SourceFile="script1.sql" />
<Binary Id="SqlScriptBinary2" SourceFile="script2.sql" />
<Component Id='SqlComponent.Sql1' Guid='YOUR-GUID-HERE' KeyPath='yes'>
<sql:SqlDatabase Id='Database1' Database='[DATABASE_NAME1]' Server='[DATABASE_SERVER]'
CreateOnInstall='no'
DropOnInstall='no' DropOnReinstall='no' DropOnUninstall='no'
ContinueOnError='no'>
<sql:SqlScript Id='SqlScript1' BinaryKey='SqlScriptBinary1' ExecuteOnInstall='yes' />
</sql:SqlDatabase>
</Component>
<Component Id='SqlComponent.Sql2' Guid='YOUR-GUID-HERE' KeyPath='yes'>
<sql:SqlDatabase Id='Database2' Database='[DATABASE_NAME2]' Server='[DATABASE_SERVER]' CreateOnInstall='no'
DropOnUninstall='no' DropOnInstall='no' DropOnReinstall='no' ContinueOnError='no'>
<sql:SqlScript Id='SqlScript2' BinaryKey='SqlScriptBinary2' ExecuteOnInstall='yes' />
</sql:SqlDatabase>
</Component>
Do a quick search and you'll find articles that may help you, such as this one for example.

Can Wix silently not overwrite a database

Wix can obviously prompt/tell the user that a database exists, and give them the choice to overwrite or to cancel the install. Unfortunately the user cannot specify to 'not overwrite' and carry on with the install.
Therefore, can Wix silently not overwrite a database? If the database is present, just ignore and carry onto the next instruction.
If not, is there another way to achieve the fact a reinstall needs to occur and the database is already in place?
Current my Wix fragment looks like this:
<Fragment>
<ComponentGroup Id="COMPG_MyProductDatabase" Directory="TARGETDIR">
<Component Id="COMPG_MyProductDatabase.sql" Guid="{...}">
<File Id="FILE_MyProductDatabase.sql" Source="..\MyProduct.Cache.Database\MyProduct.Deployment.sql" Name="MyProduct.Deployment.sql" KeyPath="yes" Checksum="yes"/>
</Component>
<Component Id='COMP_MyProductDatabase' Guid='{...}'>
<CreateFolder/>
<sql:SqlDatabase Id='DB_MyProductDatabase' Database='MyProduct' Server='[PROP_DATABASESERVERNAME]'
CreateOnInstall='yes' DropOnUninstall='no' ContinueOnError='yes' ConfirmOverwrite='yes'>
<sql:SqlScript Id='SQL_MyProductDatabase' BinaryKey='FILE_MyProductDatabase' ExecuteOnInstall='yes' />
</sql:SqlDatabase>
</Component>
</ComponentGroup>
<Binary Id='FILE_MyProductDatabase' SourceFile='..\MyProduct.Cache.Database\MyProduct.Deployment.sql' />
</Fragment>
Move the database creation into your SQL script then use SQL statements to do the conditional logic. Change the SqlDatabase elemnt to connect to 'master' for this to work.

Wix: Problem creating database with SqlFileSpec and SqlLogFileSpec Filename attribute set under c:\Program Files directory

I have a problem creating database with SqlFileSpec and SqlLogFileSpec Filename attribute set under c:\Program Files directory. I also checked that the folder (C:\Program Files\TestProject) already created. Does anyone know how to solve this?
This is the error:
Error 26201. Error -2147217900: failed to create SQL database: MyDatabase, error detail: CREATE DATABASE failed. Some file names listed could not be created. Check related errors..
<sql:SqlFileSpec Id="Mdf" Name="MyDatabase_Mdf" Filename="['INSTALLLOCATION']\MyDatabase.mdf" Size="3072KB" MaxSize="UNLIMITED" GrowthSize="1024KB"/>
<sql:SqlLogFileSpec Id="Ldf" Name="MyDatabase_log" Filename="['INSTALLLOCATION']\MyDatabase_log.ldf" Size="2048KB" MaxSize="2048GB" GrowthSize="10%"/>
...
<Property Id='INSTALLLOCATION'>C:\Program Files\TestProject</Property>
Thanks in advance.
The quotes around INSTALLLOCATION should be removed - use just [INSTALLLOCATION]. And make sure the mentioned files (mdf/ldf) are there by the time the action runs. Don't forget that the verbose log is your friend here.
Try this
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:sql="http://schemas.microsoft.com/wix/SqlExtension">
<Product Name='SQL app 1.0' Id='DB501C18-86C7-4D14-AEC0-86416A69ABDE' Language='1033' Codepage='1252'
Version='1.0.0' Manufacturer='ABC Ltd.'>
<Package Id='????????-????-????-????-????????????' Keywords='Installer' Description="SQL App 1.0 Installer"
Comments='Comment.' Manufacturer='ABC Ltd.' InstallerVersion='100'
Languages='1033' Compressed='yes' SummaryCodepage='1252' />
<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' />
<User Id="MySQLUser" Name="[SQLUSER]" Password="[SQLUSERPASSWORD]"></User>
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='INSTALLDIR' Name='TestSQL'>
<Component Id="MySqlComponent" Guid="C50999A0-02FD-42d5-9F65-7375318DD328">
<SqlDatabase Id="MySqlDatabase" Database="MyDatabase" Server="[SQLSERVER]" Instance="[SQLINSTANCE]"
CreateOnInstall="yes" DropOnUninstall="yes" User="MySQLUser" ContinueOnError="yes">
<SqlScript Id="CreateDatabase" ExecuteOnInstall="yes" BinaryKey="CreateTablesBin"></SqlScript>
</SqlDatabase>
</Component>
</Directory>
</Directory>
</Directory>
<Binary Id="CreateTablesBin" src="CreateDatabase.sql"></Binary>
<Feature Id='Complete' Level='1' Description="Full" Title="Full Installation">
<ComponentRef Id='MySqlComponent' />
</Feature>
</Product>
</Wix>
CreateDatabase.sql file will contain the script to execute some script, create database, etc.
I've managed to fix my issue by using ".\SQLExpress2012" instead of "[MachineName]\SQLExpress2012" or "[ipAddress]\SQLExpress2012". I can only speculate that by doing the former, you might not be using TCP/IP method of connecting and using named pipes instead.
Also you might want to check your SQL Server Configuration and verify that your server instance support these connection methods.

Component Execution Order In Wix

Is there a way to ensure, either through specifying order or by specifying dependencies, that one component will execute before another in WiX?
Specifically, I'm trying to create a database, then, optionally, run a script on it. My Wix looks similar to this:
<ComponentGroup Id="SQLServerComponentGroup">
<Component Id="SQLServerIstallScriptWA" Guid="" >
<Condition>INSTALLDB</Condition>
<mssql:SqlDatabase Id="dbWA" Server="localhost" Database="[DATABASENAME]" CreateOnInstall="yes" ConfirmOverwrite="yes" DropOnReinstall="no" DropOnUninstall="yes">
<mssql:SqlScript Id="dbWAScript" ContinueOnError="no" ExecuteOnInstall="yes" ExecuteOnReinstall="no" Sequence="1" BinaryKey="MSSQLCreateDBBin" />
</mssql:SqlDatabase>
</Component>
<Component Id="SQLServerCreateUserWA" Guid="">
<Condition>INSTALLDB AND DBCREATEUSER = 1</Condition>
<mssql:SqlDatabase Id="dbWA" Server="localhost" Database="[DATABASENAME]">
<mssql:SqlString Id="dbWACreateUser" ContinueOnError="no" ExecuteOnInstall="yes" ExecuteOnReinstall="no" ExecuteOnUninstall="no" Sequence="1" SQL="" />
</mssql:SqlDatabase>
</Component>
</ComponentGroup>
I want to ensure that the SQLServerInstallScriptWA component is executed before SQLServerCreateUserWA component.
Components are not ordered. However, SqlScript and SqlString have Sequence attributes that can be used to impose order. The SqlScript and SqlString Sequence attributes happen to be ordered together to handle just this scenario.

Resources