One of the recent Installer/Wix issues that needed to be addressed in our product was to automatically create a Windows group on install. Our installer creates and starts a number of Windows services that are run as a particular user with the appropriate permissions. Currently, whomever is installing the product must create the local group, create the user account to run the services and add the user to the local group before running our installer. In order to count down on the tasks the user must do manually, we added a story to both create the local group and user on install, and I first took to doing a spike solution to create the group.
Doing a spike allowed me to isolate the action needed to just creating the group. Our installer is currently made up of several Wix libraries, approximately a dozen Wix source files, and a number of custom actions. I wasn't confident about finding just the right place to add the group before I even understood how to do it. Also, the spike allowed me to quickly run the install and uninstall without going through all the other actions our current installer does.
My hope was that I could do it fairly simply with Wix or with the Wix Utilities extension. The utilities extension does provide a group element; however, "This element is not capable of creating new groups but can be used to add new or existing users to an existing group." Luckily a Google search indicated that someone had already done the work to create the necessary custom actions to do this. Msiext (http://dblock.github.io/msiext/) contains a UserPrivileges extension along with a number of other Wix extensions which I wish I had known about before. The download includes runnable demos, but there isn't much in the way of documentation. Ergo, I'm writing this blog post rather than simply pointing you to some documentation there.
So I got the latest msiext download. I created a console app as my spike and added a Wix Setup project to the solution. To the setup project I added a reference to the WixUserPrivilegesExtension DLL in the msiext package. This gives access to the LocalGroup element:
Doing a spike allowed me to isolate the action needed to just creating the group. Our installer is currently made up of several Wix libraries, approximately a dozen Wix source files, and a number of custom actions. I wasn't confident about finding just the right place to add the group before I even understood how to do it. Also, the spike allowed me to quickly run the install and uninstall without going through all the other actions our current installer does.
My hope was that I could do it fairly simply with Wix or with the Wix Utilities extension. The utilities extension does provide a group element; however, "This element is not capable of creating new groups but can be used to add new or existing users to an existing group." Luckily a Google search indicated that someone had already done the work to create the necessary custom actions to do this. Msiext (http://dblock.github.io/msiext/) contains a UserPrivileges extension along with a number of other Wix extensions which I wish I had known about before. The download includes runnable demos, but there isn't much in the way of documentation. Ergo, I'm writing this blog post rather than simply pointing you to some documentation there.
So I got the latest msiext download. I created a console app as my spike and added a Wix Setup project to the solution. To the setup project I added a reference to the WixUserPrivilegesExtension DLL in the msiext package. This gives access to the LocalGroup element:
<UserPrivileges:LocalGroup Id="DemoLocalGroup1" Name="DemoLocalGroup1"
Description="Demo local group 1 for a spike." CheckIfExists="yes"
CreateOnInstall="yes" DeleteOnUnInstall="yes"> </UserPrivileges:LocalGroup>
The explanation is pretty straight-forward. the Id is the unique element id, Name is the name of the group and description is what appears in the description when you Manage Groups in Windows. CheckIfExists will prevent it from re-creating the group if the group already exists. CreateOnInstall creates the group on install and DeleteOnUnInstall will delete the group on uninstall. These can be changed if, for example your application creates the groups itself and all you want to do is delete it on uninstall, or if you want to leave the group unchanged even if the user chooses to uninstall. Like I said, pretty straight-forward.
My entire Product.wxs looks like so:
xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:UserPrivileges="http://schemas.appsecinc.com/wix/UserPrivilegesExtension">
<Product Id="*" Name="SetupProject1" Language="1033" Version="1.0.0.0" Manufacturer="PlutoTech" UpgradeCode="5eec8bc9-ee30-451b-b3c2-fd4ce78bf277"> <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" /> <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate /> <Feature Id="ProductFeature" Title="SetupProject1" Level="1"> <ComponentGroupRef Id="ProductComponents" /> </Feature> </Product> <Fragment> <Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject1" />
</Directory>
</Directory>
</Fragment> <Fragment> <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="LocalUserGroupDemo1" Guid="YOUR-GUID-HERE">
<UserPrivileges:LocalGroup Id="DemoLocalGroup1" Name="DemoLocalGroup1" Description="Demo local group 1 for a spike." CheckIfExists="yes" CreateOnInstall="yes" DeleteOnUnInstall="yes">
</UserPrivileges:LocalGroup>
<File Id="File.MyService" KeyPath="yes" Source="$(var.AddLocalGroupSpike.TargetPath)" />
</Component>
</ComponentGroup>
</Fragment> </Wix>
Note that the INSTALLFOLDER cannot be the keypath for the component. In this case it is actually the executable, Id="File.MyService. In our actual installer, the component that creates the necessary groups is separate from any other files, but the component group it belongs to is associated with the TARGETDIR directory.
No comments:
Post a Comment