Wix Toolset can't grant permission to user in install directory - wix

My app writes log using log4net in the appinstalldirectory\log directory but the app is not able to create log directory and create file. It was because on security tab current login user which is local admin in windows 10 was not added as list of user who has full access to that folder.
Thus in wix installer I have created a component as below
<CreateFolder>
<util:PermissionEx
GenericAll="yes"
CreateFile="yes"
User="[UserSID]"
Domain="[%USERDOMAIN]"/>
<!--<Permission
GenericAll="yes"
CreateFile="yes"
User="[UserSID]"
Domain="[%USERDOMAIN]"/>-->
</CreateFolder>
With PermissionEx the installer doesn't complete and show message as below
https://i.stack.imgur.com/SiCbk.png
But when is used I get error as below
https://i.stack.imgur.com/AXNpO.png
When I check the usersid in command I can see that usersid
https://i.stack.imgur.com/KDVpC.png
Could some one please point me what is wrong or what should I do? I don't want to keep modifying every system and grant current user full access so that my app can write log.

Use the username, not the SID
<CreateFolder>
<util:PermissionEx
GenericAll="yes"
CreateFile="yes"
User="[LogonUser]"
Domain="[%USERDOMAIN]"/>
</CreateFolder>

Related

Wix installer - Issues installing to a mapped network drive

I have an issue while trying to install to a mapped network drive. I have permissions to create, edit, delete files/folders at this location. It is always for this particular file abc.xslt
This is the what the wix log tell me:
MSI (s) (48:9C) [14:48:11:524]: Source for file 'NSf100' is compressed
InstallFiles: File: abc.xslt, Directory: M:\abc\def\, Size: 17819
MSI (s) (48:9C) [14:48:11:525]: Re-applying security from existing file.
Error 1315. Unable to write to the specified folder: M:\abc\def\.
MSI (s) (48:9C) [14:50:33:621]: Product: ABC -- Error 1315. Unable to write to the specified folder: M:\abc\def\.
Then, I tried to do a RemoveFile before installing the new one as follows:
<RemoveFile Id="NSfr100" Name="abc.xslt" On="install"/>
Again, I see this error:
RemoveFiles: File: abc.xslt, Directory: M:\abc\def\
Error 1315. Unable to write to the specified folder: M:\abc\def\.
MSI (s) (9C:3C) [16:54:29:389]: Product: ABC -- Error 1315. Unable to write to the specified folder: M:\abc\def\.
Action ended 16:54:29: InstallFinalize. Return value 3
So, I tried setting permissions on that file as follows but that did not help either,
<util:PermissionEx User="Everyone" Domain="domain name" GenericRead="yes" Delete="yes" Read="yes" GenericAll="yes" GenericWrite="yes" GenericExecute="yes" WriteAttributes="yes" WriteExtendedAttributes="yes" ReadAttributes="yes" ReadExtendedAttributes="yes" ReadPermission="yes" Synchronize="no" />
The same installer works without issues when installing locally. Could someone please help me understand why this fails while installing to a mapped network drive?
Thanks much
This isn't a supported scenario for Windows Installer. The mapped drive only exists in the users logged in context. The windows installer service running as SYSTEM cannot see it.

Custom action of Wix failed to call vb script

I have one VB script in the package itself. I need to call it using CMD, the default way of calling the script taking too much time, so I am trying to call it with CMD and CSCRIPT but the installer raises the error while installation.
I am using the following code which is not working as expected. I searched a lot but didn't find the solution.
<Binary Id="ServiceInstall" SourceFile="..\..\..\AddVirDir.vbs" />
<CustomAction Id="InstallService" BinaryKey ="ServiceInstall"
ExeCommand="CMD /C "[#ServiceInstall]""
Execute="immediate" Return="check" HideTarget="no" Impersonate="no"/>
WiX IIS Elements: If this is all IIS, I would avoid scripting and custom actions whenever possible and use WiX's built-in IIS elements. Here is a Web-installer sample from Rainer Stropek available on github.com.
Look for <iis:WebVirtualDir ... /> et al. Find the WiX Documentation here. I believe you should be able to accomplish what you need without too many custom actions.
DISM.exe: Stropek himself uses custom actions in another sample source to set up IIS using DISM.exe. Not sure I would do it like this (no other suggestions though), but it is a sample of custom actions and IIS.
Need-For-Speed: As to your installation performance issues. Maybe you need to suppress the creation of a restore point and limit file costing? The Windows Installer engine allows this - see link below. I doubt it will be very effective though. I think there must be something else wrong in your installer. Some timeout issue? It could relate to other custom actions, slow network, or some other issue. Can you elaborate on your deployment scenario?
In any case, here is some documentation on speeding up MSI installations in general. Essentially the MSIFASTINSTALL property is the only one I would recommend. DISABLEROLLBACK can cause genuine problems.
Logging: I normally recommend that setup developers enable default verbose MSI logging - as described in the "Globally for all setups on a machine" section, to always have a log file ready when you need one. It is created with a random name for every MSI operation in the TEMP folder and you sort by modify to get the latest one. The log file might give clues as to why the installation is slow - just determine what is really going on. Apologies if this is just obvious trifles and you have this set up already.
Manual log file creation:
msiexec.exe /i C:\Path\Your.msi /L*v C:\Your.log
Interpreting an MSI log: interpreting a log file can be challenging sometimes. Here is an answer with some links to help with this.
Service Installation & Control: You should not install services with scripts. There are built-in mechanisms in MSI that are vastly superior. You simply use the ServiceInstall and ServiceControl WiX XML Elements and "declare" how the service should be registered and when and how the service should be started and stopped:
<Component>
<File Source="$(var.SourceDir)\WindowsService.exe" />
<ServiceInstall Name="MyService" ErrorControl="normal" Start="auto" Type="ownProcess" />
<ServiceControl Id="MyService" Name="MyService" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
</Component>
Look! No custom actions! :-) - Just MSI auto-magic. There is no need to use any custom actions for this. MSI is full-featured and reliable provided your service executable behaves as it is supposed to.
Let me link to a similar sample on github in case the above is not clear. It is more complete and elaborate.
VBScript: I wrote this before I saw you dealt with services. I'll just throw it in: to call a script that doesn't have a function you can try something like this:
<!-- The VBScript file -->
<Binary Id='Sample.vbs' SourceFile='Sample.vbs' />
<!-- The Custom Action -->
<CustomAction Id='Sample.vbs' VBScriptCall='' BinaryKey='Sample.vbs'
Execute='immediate' Return='ignore'/>
<!-- And Insert Into Installation Sequence -->
<InstallExecuteSequence>
<Custom Action='Sample.vbs' After='AppSearch'/>
</InstallExecuteSequence>
That should work for a script like this (Sample.vbs - no funtions, just an implicit main function):
MsgBox(Session.Property("ProductName"))
There is an answer on the topic of VBScript custom actions here: WIX installer execute vbscript from CustomAction.

WIX MSI Installed from Windows Service

I am working on self installing software. There is a windows service that is running and can be notified that there is a software update. At that time, it will download my burn exe and do a process.start to silently install it. The installer works as expected except for one issue - the services it installs won't start due to a logon failure. If I change the service password in services, the service will start, so I am confident the issue resolves around the service account password. Here's the rub - if I run the exact same installer on the exact same machine from the interactive desktop (logged on user), it works!
Here is one of the services I install:
<ServiceInstall
Id="DataAcquisitionInstaller"
Type="ownProcess"
Name="DataAcquisitionService"
DisplayName="Data Acquisition Service"
Description="Handles all data acquisitions"
Start="demand"
Account="[SERVICEACCOUNTUSERID]"
Password="[SERVICEACCOUNTPASSWORD]"
ErrorControl="normal"
>
<util:PermissionEx
User="[SERVICEACCOUNTUSERID]"
GenericAll="yes"
ServiceChangeConfig="yes"
ServiceEnumerateDependents="yes"
ChangePermission="yes"
ServiceInterrogate="yes"
ServicePauseContinue="yes"
ServiceQueryConfig="yes"
ServiceQueryStatus="yes"
ServiceStart="yes"
ServiceStop="yes" />
<ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnReinstall="yes"/>
</ServiceInstall>
I have verified in the log that SERVICEACCOUNTUSERID and SERVICEACCOUNTPASSWORD are correct. The only difference I can see in the log is this:
When installing from service:
MSI (s) (30:80) [10:05:28:905]: Executing op:
ServiceInstall(Name=DataAcquisitionService,DisplayName=Data
Acquisition Service,ImagePath="C:\Program Files
(x86)\xxx\xxx\Services\DataAcquisitionService.exe",ServiceType=16,StartType=3,ErrorControl=1,,Dependencies=[~][~],TagId=0,StartName=.\test,Password=**********,Description=Handles
all data acquisitions,SecurityDescriptor=BinaryData,)
When installing from the interactive desktop as the logged in user
MSI (s) (44:E8) [09:45:57:518]: Executing op:
ServiceInstall(Name=DataAcquisitionService,DisplayName=Data
Acquisition Service,ImagePath="C:\Program Files
(x86)\xxx\xxx\Services\DataAcquisitionService.exe",ServiceType=16,StartType=3,ErrorControl=1,,Dependencies=[~],,StartName=.\test,Password=**********,Description=Handles
all data acquisitions,,)
What does this mean --> "SecurityDescriptor=BinaryData"? Is that what is causing my issue and if so, how can I fix it?
Thanks.

WiX Service Install with user credentials or LocalSystem depending on UI input

Below is a section of my .wxs installer file which installed my service. I have a WiX UI dialog where the user can either choose to install the service to run under the LocalSystem account or input the credentials of the account they want. The UI has two text boxes (one bound to the ACCOUNT property and one to the PASSWORD property) and a checkbox that is bound to a property called USELOCALSYSTEMACCOUNT.
Individually, these service installers work fine, you can see both ServiceInstall sections below. However I want the installer to install the service with the user input credentials if USELOCALSYSTEMACCOUNT is not set to 1, or to use the LocalSystem account if USELOCALSYSTEMACCOUNT is set to 1, but I am unsure how to do this. the Condition tag doesn't work within a ServiceInstall tag so I'm a bit lost on how to achieve this.
WiX component section below:
<Component Id='MainExe' Guid='*'>
<File Id='MainService'
Name='MyService.exe'
Source='$(var.ServiceRoot2)\SA.MyService.exe'/>
<ServiceInstall Id='MyService'
Type='ownProcess'
Vital='yes' Name='MyService'
Name='$(var.HumanProductName)'
Description='$(var.ProductDescription)'
Start='demand'
Account='[ACCOUNT]'
Password='[PASSWORD]'
ErrorControl='ignore'
Interactive='no'/>
<ServiceInstall Id='MyService'
Type='ownProcess'
Vital='yes'
Name='$(var.HumanProductName)'
Description='$(var.ProductDescription)'
Start='demand'
Account='LocalSystem'
ErrorControl='ignore'
Interactive='no'/>
<ServiceControl Id='MyServiceServiceControl'
Stop='both'
Remove='both'
Name='$(var.HumanProductName)'
Wait='yes'/>
</Component>
You should be able to put the condition around the entire component and just have the LocalSystem version and the User specified version. Wix is smart enough to not package the Myservice.exe twice in the installer. Just make sure your condition has "OR Installed" appended to it because I've had issues in the past with conditional components/features not uninstalling because the property they depended on was not set during uninstall. If it is a state of the machine (VersionNT/VersionVT64 which remain constant) then omitting "OR Installed" should be fine.

WiX: conditionally register application to start when Windows launches

I want to register my application to start as windows launches based on a check box in the exit dialog.
I followed this but it seem that the writing to the registry is done before the end dialog (and the relevant check box) even appear.
My code is:
in product.wxs:
<Property Id="APP_AUTOMATIC_START_UP">1</Property>
....
<Component Id="AppAutoStartUp" Guid="{MyGuid}">
<RegistryValue Id="App.rst" Root="HKCU" Action="write" Key="Software\Microsoft\Windows\CurrentVersion\Run" Name="App" Value="[#MyApp.exe]" Type="string" />
<Condition><![CDATA[Installed OR APP_AUTOMATIC_START_UP]]></Condition>
in MyExitDialog.wxs:
<Control Id="AutomaticStartup" Type="CheckBox" Height="18" Width="295" X="135" Y="190" Text="Run App upon windows startUp" Property="APP_AUTOMATIC_START_UP" CheckBoxValue="1">
<Condition Action="hide" >Installed</Condition>
<Condition Action="show" >NOT Installed</Condition>
EDIT:
I tried adding the key to the registry and in case the user un-check the check box delete it using a custom action. my code:
[CustomAction]
public static ActionResult NotRunOnStartUp(Session session)
{
session.Log("Begin NotRunOnStartUp");
RegistryKey rk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
rk.DeleteValue("MyApp");
return ActionResult.Success;
}
<Binary Id="NotRunOnStartUpBinary" src="..\CustomActions\NotRunOnStartUp\bin\$(var.Configuration)\NotRunOnStartUp.CA.dll" />
...
<CustomAction Id="NotRunOnStartUpCA"
Return="check"
Execute="immediate"
BinaryKey="NotRunOnStartUpBinary"
DllEntry="NotRunOnStartUp" />
...
<Publish Dialog="MyExitDialog" Control="Finish" Event="DoAction" Value="NotRunOnStartUpCA">APP_AUTOMATIC_START_UP= 0 and NOT Installed</Publish>
The result is, during instalation I write the key to the registry, but when I uncheck the check box and press finish, the key in not removed from the registry.
Any Ideas why?
The other choice is to write a custom action that runs at the end of the install based on the value of the checkbox, and again you'd need to remove that registry entry at uninstall.
As suggested, it is better to make it a configuration of the app and not the install. If the user changes his mind, what's he supposed to do? Fiddle in the registry (if he can figure out where it is)? Uninstall and re-install to change the setting?
By the way, the program does not start "as windows launches". It will start when the user logs on, and that's not the same thing. If you want it to launch when the user logs on I would describe it to your users as "when you logon". If you want it launch when Windows starts it would need to be a service.
Sounds like you have a conditional feature. Remove the check box and instead make a sub-feature.
Another take...
User choices like that are not an installation issue; They are a configuration issue. There is a fine and wavy line between the two. The application's programs should manage its own configuration.
After the installation is complete and your user has made a configuration choice, your installer can launch a configuration program with command-line arguments to add or modify the Run key.
The installer could remove the registry entry upon uninstallation since it would be better to clean up the Run key than to preserve user's choice for when they install your application again.