Executing wix msi custom actions as system - wix

I am using WIX to build a an MSI that will be executed as a regular user but with system privileges (AlwaysInstallElevated=1). I have defined two Custom Actions that execute net.exe.
The net.exe commands are not getting executed as a regular user. I have also tested executing this msi as an Administrator and the net.exe commands are getting executed.
I have logged the msi output and I see error codes that lead me to believe that the net.exe commands are not being executed elevated. I'm reaching out to the community to see if
What I'm trying to do is possible
Do I need to instead use an exe as a custom action in order for the exe to install elevated.
Thanks in advance for the feedback.
<CustomAction Directory="TARGETDIR" ExeCommand="[SystemFolder]net.exe user TestUser /add" Return="ignore" Execute="deferred" HideTarget="no" Impersonate="no" Id="Command1">Command1</CustomAction>
<CustomAction Directory="TARGETDIR" ExeCommand="[SystemFolder]net.exe localgroup Administrators TestUser /add" Return="ignore" Execute="deferred" HideTarget="no" Impersonate="no" Id="Command2">Command2</CustomAction>
<InstallExecuteSequence>
<Custom Action="Command1" After="PublishProduct">NOT Installed</Custom>
<Custom Action="Command2" After="Command1">NOT Installed</Custom>
</InstallExecuteSequence>
Machine Policy and User policy allows for msis to be executed as system.
MSI (c) (DC:F8) [09:17:39:438]: Machine policy value 'AlwaysInstallElevated' is 1
MSI (c) (DC:F8) [09:17:39:438]: User policy value 'AlwaysInstallElevated' is 1
MSI (c) (DC:F8) [09:17:39:438]: Running product '{34ED8E61-40EA-47CE-95E7-8EE3CDBCB1E8}' with elevated privileges: All apps run elevated.
Errors
MSI (s) (8C:8C) [20:39:18:989]: Executing op: ActionStart(Name=Command1,,)
MSI (s) (8C:8C) [20:39:18:989]: Executing op: CustomActionSchedule(Action=Command1,ActionType=3170,Source=C:\,Target=C:\WINDOWS\SysWOW64\net.exe user TestUser /add,)
CustomAction Command1 returned actual error code 2 but will be translated to success due to continue marking
MSI (s) (8C:8C) [20:39:19:535]: Executing op: ActionStart(Name=Command2,,)
MSI (s) (8C:8C) [20:39:19:535]: Executing op: CustomActionSchedule(Action=Command2,ActionType=3170,Source=C:\,Target=C:\WINDOWS\SysWOW64\net.exe localgroup Administrators TestUser /add,)
CustomAction Command2 returned actual error code 1 but will be translated to success due to continue marking

Even in an install started by an administrator the impersonated custom actions run without elevation. So the answer is your number 2. start the install from an elevated process with a CreateProcess-type of initiation. Having said that, it's not clear to me why you can't run the CA deferred with no impersonation because there seems to be nothing that requires the user to be an actual user as opposed to the system account. So the failure might not be elevation, and that's the issue with passing the task off to a program that isn't going to give you good error messages. So....
I've seen boilerplate code to do this kind of thing, and I believe WiX has it anyway, the Util User element, that may be the way to go.

Like Phil says, don't use net.exe to create users. Use WiX's built in features to do so (I should have found a better sample but don't have time right now):
http://wixtoolset.org/documentation/manual/v3/xsd/util/user.html
https://www.firegiant.com/wix/tutorial/com-expression-syntax-miscellanea/new-user-on-the-block/
My first instinct would be that the AlwaysInstallElevated policy would be misconfigured, but judging from the log file it is set correctly. I am rusty, but the impersonation looks like it is correctly set to "no" Phil? And the scheduling is deferred and seemingly placed right before InstallFinalize - seems OK off the top of my head.
Could it be that net.exe cannot be run properly as LocalSystem? Why then would it work when the installation is kicked off as Administrator? One would think LocalSystem had all required privileges. Isn't the current user's access token attached to the msiexec.exe process somehow? (for logging purposes or something). Or could it be a privilege that the Administrator account has that LocalSystem does not? How would that privilege apply if there is no impersonation? Did you try to manually launch net.exe as a regular user? What errors do you get when attempting to create a user when running as a regular user?
In either case I wouldn't waste my time running EXE custom actions if there is an alternative. I don't remember the last time I did. I normally use VBScript, C++ and earlier I used Installscript - with all its archaic syntax. Just switch to the built-in WiX constructs and you should be fine.

Related

Wix elevated AND impersonating Custom Action

I have a custom action that needs to modify registry settings:
it is marked as deferred in order to support a rollback
it must be run with elevated priviliges in order to modify the Registry
it must be run within the security context of a particular user (impersonated)
<CustomAction Id="EncryptRegistrySettings"
BinaryKey="DLServiceCA"
DllEntry="EncryptRegistrySettings"
Execute="deferred"
Impersonate="yes"
Return="check"/>
I have some other ugly options to workaround this problem (Execute="immediate" or impersonate="yes" with elevated subprocess) which I don't want to resort to.
The problem is: with Impersonate="no" subprocess msiexec is run by SYSTEM. With yes it is run by User, but not elevated.
So the question is:
Is it possible to run a Custom Action both as Impersonated AND elevated?
No, they are mutually exclusive capabilities in Windows Installer.

Run ExeCommand in customAction as Administrator mode in Wix Installer

I am new to wix installer. I have developed a set-up using wix installer for my application and I need to execute a Custom Action to run a command in cmd.exe. In XP it works fine. But in Windows 8 & 7 the cmd prompt needs to be run as administrator.
I have googled and found the keywords Elevated Privileges and impersonate might help me.
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated"></Package>
As you can see above, I used the InstallScope attribute set to perMachine, and I have used Impersonate="No" in the CustomAction element:
<CustomAction Id='comReg' Directory='INSTALLLOCATION' Impersonate='no'
ExeCommand='"[NETFRAMEWORK40CLIENTINSTALLROOTDIR]regasm.exe" "[INSTALLLOCATION]myProduct.dll" /codebase' Return='check' />
But I didn't get any changes while installating. I need the command prompt to open and run the above command in Administrator Mode.
And can anyone please tell me about these keywords "Elevated Privileges & impersonate"
<InstallExecuteSequence>
<Custom Action='comReg' After='InstallFinalize'>NOT REMOVE</Custom>
<Custom Action='comUnreg' Before='RemoveFiles'>REMOVE</Custom>
</InstallExecuteSequence>
How to do it?
The wix documentation here explains the Impersonate attribute:
This attribute specifies whether the Windows Installer, which executes as LocalSystem, should impersonate the user context of the installing user when executing this custom action. Typically the value should be 'yes', except when the custom action needs elevated privileges to apply changes to the machine.
You also need to understand the difference between deferred and immediate custom actions. See the Execute attribute on the same help page:
This attribute indicates the scheduling of the custom action. This attribute's value must be one of the following:
deferred
Indicates that the custom action runs in-script (possibly with elevated privileges).
immediate
Indicates that the custom action will run during normal processing time with user privileges. This is the default.
At present your custom action is immediate, which means it is running with user privileges. See this blog post for lots of details, but particularly:
Any immediate custom actions impersonate the invoking user. Before Windows Vista this wasn't a problem since at this point the installing administrative user had a privileged token. With the introduction of UAC in Windows Vista the default administrative token with UAC enabled is a filtered token and does not hold all privileges. Since immediate custom actions are not supposed to modify machine state - only to gather state data and schedule custom actions to run deferred - this still shouldn't be a problem. After all, at this point the generation of the installation and rollback scripts is all that should be going on.
You should never modify machine state with an immediate custom action. Use a deferred one, and keep impersonate to no, and it should work:
<CustomAction Id='comReg' Directory='INSTALLLOCATION' Execute='deferred' Impersonate='no' ExeCommand='"[NETFRAMEWORK40CLIENTINSTALLROOTDIR]regasm.exe" "[INSTALLLOCATION]EAWordImporter.dll" /codebase' Return='check' />
EDIT: Schedule the custom action using the InstallExecuteSequence element:
<InstallExecuteSequence>
<Custom Action='comReg' Before='InstallFinalize'/>
</InstallExecuteSequence>

Kill my application during uninstall

I have run into challenging problem trying to accomplish the following:
my application installs a service (watchdog.exe) and an exe file (app.exe).
After the installation is done the service starts and creates process "app.exe".
during uninstall I want to kill the process "app.exe" (which is running under local system account, so I must be running as admin).
problem 1:
The installs says that it requires a reboot since it sees that file "app.exe" is being held (running) during the CostFinalize phase (please correct me if I'm wrong about the phase that checks if a reboot will be required). It would be much better to kill the process when the uninstallation begins. I have verified that if the process is not running during the uninstall then the install does not complain about a reboot required.
problem 2:
using a custom action to kill the process is problematic. the action must run elevated, but on the other hand it must run before the costFinalize (otherwise - it's back to problem 1).
I would appreciate any suggestion. Also, any alternative solutions (is there another way to close the process maybe during install that will not require a reboot?)
The custom action code I have now (not good since it both unnecessarily asks for a reboot and fails to kill the process due to lack of permissions):
<InstallExecuteSequence>
<!--<ScheduleReboot After="InstallFinalize" />-->
<Custom Action="MyProcess.TaskKill" Before="InstallValidate"></Custom>
</InstallExecuteSequence>
<!--<Property Id="Net">Net.exe</Property>-->
<Property Id="QtExecCmdLine" Value='"[%SYSTEMROOT]\System32\taskkill.exe" /F /IM App.exe' />
<CustomAction Id="MyProcess.TaskKill"
BinaryKey="WixCA"
DllEntry="CAQuietExec"
Execute="immediate"
Return="ignore" />
Here is the log for the failure:
CAQuietExec: Error 0x80070001: Command line returned an error.
CAQuietExec: Error 0x80070001: CAQuietExec Failed
CustomAction MyProcess.TaskKill returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 18:15:54: MyProcess.TaskKill. Return value 1603.
There are few ideas that I have, namely:
Use EventWaitHandles, which allow processes to communicate between each other, and delegate your wish to app.exe. Your app.exe can then terminate, as needed. This is clean solution and should be prefered.
If for whatever reason you decide to kill the application like you don't care about anything at all in the world, then you can:
I saw today a project that can run MSI completely elevated, in all stages. It was Visual Stdio template, however I can't find it right now, but know that it exists there.
You can also use this, maybe it works: How do I get WiX installer to request administrative privileges?
Basically there are so many hackery tricks you can do, to kill the application. Such as using WiX Burn and requiring administration rights, then doing your thing. I would go with solution#1(create your own mechanisms)
By the way, if you use ServiceControl element in WiX, it will STOP the service before REINSTALLING/UNISTALLING. You can hook to OnStop() method in Service and kill your App.exe there. If you have set Service as App.exe parent, then there should be flag that any child processes die with parent.

PerUser install with Custom Action - UAC disabled

I'm using WiX to generate an MSI that installs a browser plugin on a perUser basis. I have a custom action to install a driver using DPInst (which needs elevated privileges).
The install works fine when UAC is enabled; Windows shows the prompt to elevate. However, if I have UAC disabled and try to install on a regular user account, dpinst.exe will get spawned until the computer freezes. (About a thousand times at last count).
In the <InstallExecuteSequence> I have:
<Custom Action="Install_Drivers" After="InstallFiles">NOT Installed</Custom>
My custom action is:
<CustomAction Id='Install_Drivers' Execute='deferred' Directory='DRIVERS' ExeCommand='"[DRIVERS]DPinst.exe" /SW /SA' Return='ignore' Impersonate='no'/>
I have Return='ignore' because, from what I understand so far, dpinst.exe always returns a non-0 code.
How can I ensure that the custom action fails correctly when UAC is disabled? On a related note, can I show a custom message to the user when the driver installation fails?
Further Information: I'm developing on Windows 7 currently, but targeting WinXP and up.
Edit Taking a look at the log for the installation these seem to be the relevant lines:
Executing op: CacheSizeFlush(,)
Executing op: ActionStart(Name=Install_Drivers,,)
Executing op: CustomActionSchedule(Action=Install_Drivers,ActionType=3170,Source=C:\long_redacted\Drivers\,Target="C:\long_redacted_path\Drivers\DPinst.exe" /SW /SA,)
Disallowing shutdown. Shutdown counter: 0
CustomAction Install_Drivers returned actual error code 1073807364 but will be translated to success due to continue marking
The bit about the shutdown is, I believe, when I logged off stop the installation. (Canceling doesn't seem to have any effect).
Try setting the 'Impersonate=no' attribute on the 'CustomAction' element, like this:
<CustomAction Id='Install_Drivers' Execute='deferred' Directory='DRIVERS' ExeCommand='[DRIVERS]DPinst.exe" /SW /SA' Return='ignore' Impersonate="no" />
Also note: you have a stray double-quote in your ExeCommand
Installing a driver is an inherently per-machine operation. A limited user can't do it. So with UAC disabled, it's not going to work. DPInst apparently doesn't get the hint that it doesn't have permissions and can't get them. Sounds like a bug in DPInst. You should change your installer to be per-machine and add a launch condition on the Privileged property to prevent the installer from starting for limited users without UAC.

Why doesn't this silent launch work in WIX?

I have the following command running at the end of my package install for an application.
<Property Id="WixShellExecTarget" Value="[INSTALLDIR]RCR.VDS.exe" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA"
DllEntry="WixShellExec" Impersonate="no" />
I can't use [#myApplication] because I run heat on my output folder on my build server so I don't know the auto generated id of my application. Any ideas on how to silently run my application after the install?
The log file shows this for the command line section
******* CommandLine: **********
MSI (c) (30:74) [09:47:14:156]: Note: 1: 2203 2: VDSInstall.msi 3: -2147287038
MSI (c) (30:74) [09:47:14:156]: MainEngineThread is returning 2
Please see: How To: Run the Installed Application After Setup
If you want the custom action called during a silent install add:
<InstallExecuteSequence>
<Custom Action="LaunchApplication" After="InstallFinalize">SOMECONDITION</Custom>
</InstallExecuteSequence>
Note SOMECONDITION should be an expression that checks the EXE is installed and the user wants the program to be launched.
The are a copy things you can consider:
The identifier from heat.exe will be stable. So you can use the ugly identifer in your [#UglyFileId1234abcef45612345asdf] custom action.
a. You could also apply a XSLT to transform the heat output for the executable file's Id to something nicer than the ugly identifier. Depends how readable you want the launch custom action to be.
If you want the executable launched silently then you'll probably want the Quite Execution custom action instead of the Shell execute custom action that "LaunchApplication" uses.