WiX CLR CustomAction sometime fails to log - wix

In my WiX projects I have two custom actions, in the same DLL. Both are written in C#.
The first one enumerates which IIS-sites are available on the machine. It runs before the Windows Installer dialogs.
The second one runs after a dialog "select which web-site", i.e. in the Dialog-flow as a result of pressing "Next".
The first one logs nicely to the MSI-logfile.
The second one logs nothing at all.
Why cannot my custom action log during the dialog-part? (The rest of the dialog-part is logging as expected.)
Is there something I can do to enable this logging?

Custom actions can't write to the MSI log when they're invoked using a DoAction control event. It's an MSI limitation.

It's a permissions problem.
IIS web site enumeration requires Administrator privileges, so the first custom action runs in an elevated process. Your second custom action runs in a non-elevated process, so it doesn't have enough permissions to write in your log.
If you create the log in a per-user location, for example the current user desktop, the second action will successfully write in the log.
A solution is to use an elevated process for your second custom action. Another solution is to always create the log in a per-user location.

Related

WIX service installer CA write access to RegistryKey components

I have a CA that runs deferred without impersonation in InstallExecuteSequence after PublishProduct.
This CA uses windows impersonation to change context to a local administrative user where the credentials are for queried using a dialog for user input. The elevated requirements are meet, the context is changed and other tasks are performed, however when I try to open a subkey made by the installer for write access in HKLM\SYSTEM\CurrentControlSet\Services\NameOfService\MySubKey, I get an exception related to insufficient access. However I can open for read though?
At this point the service has been installed, the key has been created and other values have been written. The context I am using to modify it is a member of the local Administrators group and the session is elevated as per requirements of the other tasks?
Is this a caveat of the windows installer environment?
For whatever reason, exiting the impersonation back to LocalSystem resolved this. Likely an issue with elevation.

Can wix prompt for a windows service username/password?

I am using Wix to install a windows service. The service will need to run under a non system/service account that is set up by the user.
Is it possible to have it prompt for the username/password for the service login?
The Community MSI Extensions on GitHub contains a ServiceCredDlg dialog for prompting username and password. According to the docs, it can test the credentials are valid and that user has 'logon as a service' rights.
Yes, but it's not built-in. You can setup a GUI in WiX (which is not too intuitive) where you can prompt for any setting you'll need in later steps.
First, check out how to create a GUI that sets custom properties by following these guidelines, ensuring that your GUI fills properties SERVICEACCOUNT and SERVICEPASSWORD. Then use the ServiceInstall element with those properties as shown here.
WiX doesn't (or at least didn't) have anything nice out of the box for what you are looking for. Best option that I am aware of is to roll-your-own.
https://www.geekproject.com/post/wix-service-account-dialog/
You can set PUBLIC PROPERTIES (uppercase) with the credentials on the command line and use these to install the service.
msiexec.exe /I "setup.msi" /QN USER="username" PASS="password"
A custom action can also be used to retrieve these values from the user during an interactive install, but if you do this remember to make the display of the message obey the setups UILevel value. Showing a message box from a custom action in a silent install is considered a serious setup error:
INSTALLUILEVEL_NONE 2 Completely silent installation.
INSTALLUILEVEL_BASIC 3 Simple progress and error handling.
INSTALLUILEVEL_REDUCED 4 Authored UI, wizard dialogs suppressed.
INSTALLUILEVEL_FULL 5 Authored UI with wizards, progress, errors.
Perhaps the best option is to show the dialog in an interactive install, and refuse to install silently if these properties aren't set on the command line. This is a simple custom action to test the values of the USER and PASS properties.
And obviously it is not recommended to use user accounts to run services.

Adding SQL permissions for just created application pool identity in WiX

I have a WiX package that has one component creating an IIS 7 application pool which has the ApplicationPoolIdentity identity (IIS AppPool\AppPoolName). I then have another component to add permissions in a SQL Server database for this identity (I am using the SqlString extension).
When the SQL runs to add permissions I get the following error:
Windows NT user or group 'IIS
AppPool\AppPoolName' not found.
I'm assuming this is happening because the IIS stuff is happening in a transaction and the application pool has not actually been committed quite yet.
Does anyone have a better approach to this problem?
Thanks!
As far as I understand the way WiX IIS extension works, it creates a metabase backup before applying any changes. Then, in deferred sequence, it does all actions you instructed it to do. If an error occurs, rollback action just restores the previous state from backup. Otherwise, if everything is ok, commit actions just drops the backup snapshot.
So, taking this into account, I don't think your guess it correct. It should be possible to do what you want. I suspect the problem is in action sequencing. Make sure IIS actions go first, then SQL stuff, and permissions go last. In such a way the first thing you create an AppPool, then do SQL stuff, and finally apply required permissions. Well, I might be wrong, but you should find the right sequence by try-and-error approach.
And the rule of thumb: always generate a verbose log. It contains everything. Seriously, that's the best thing I like about Windows Installer: whatever has happened, you'll find it in verbose log. Good luck!
Why not create a custom action that configures IIS for you?
You could use a simple custom action that just executes a set of appcmd commands OR
create a managed (C#) custom action that programatically uses the Microsoft.Web.Administration.ServerManager to configure IIS7.

Security Issues Writing to Event Log with My.Application.Log.WriteException

I'm handling the Application.UnhandledException event in a WinForms app and need to log exceptions caught there. My app.config is set up to log exceptions to a FileLog and an EventLog.
The problem is that when running as a non-admin user, the EventLog cannot be written to because of a SecurityException - I get the message "The source was not found, but some or all event logs could not be searched."
I understand why - the user does not have permission to create the EventLog source, but the question is how should this source be created? As I see it, I could either:
1) Create the EventLog source with my installer, as this is running as admin. How to do this?
2) Create from within my app, by somehow elevating permissions? But this would give the UAC prompt on Vista.
What's the best practice for creating a Windows Application EventLog source on a client machine?
thanks
The most common way to do this is your Option 1.
How you do it depends on your installer package, but you need to:
Ensure your installer runs with elevated permission.
Write a single entry to that event log source, OR
Create the registry key for your event source directly
When your installer writes to the event log, the source will be created and will be available for non-administrators.
With WiX, (Windows Installer Xml) you can reference this post for directly creating the event source registry entry.

Logoff script to change user

Using Windows 2003, I'm look for a way to create a "logoff script" that will continue with the current logoff then immediately login another user. So, "UserA" logs off. Script fires to login "UserB".
This is part of an application upgrade for a computer where we have written the 'shell'; similar to a kiosk application. For the upgrade we need to logon as 'Adminstrator' then, when the upgrade has completed, logoff 'Administrator' and logon as 'sample_user'. We would like to accomplish this WITHOUT rebooting.
Note, I do not want a script that will initiate the logoff (i.e. "shutdown"). I'm looking for a script that will run upon the user logging off (set via Group Policies). As above, the script should log a different user on.
Thanks.
Don't think it's possible in the stated way (script at logoff).
You'd have to set the machine to logon automatically as a specified account and then log off (having it log on automatically for you) and then you'd have to disable that feature again afterwards, by placing a temporary logon script... generally sounds messy.
The actual setting can be made using tools like Microsofts Shared Computer Toolkit or similar (not so sure how the "normal" registry auto-login behaves at manual logout but I've had an XP kiosk that would automatically log on instantly, even if you logged out manually - you had to override it using some key like shift+logoff to be able to manually specify the login again, so somehow it can be made).
The "easiest" way might be to replace msgina.dll with someone of your own making...
But why are you doing this? Just use runas and start whatever you need to do as that other user without logging off the console user - it's a multi-user system afterall? The desktop is just fluff ^^
(This will anyhow require that the user credentials are available to your script, which kind of makes it redundant as you compromise the security of that account - defying the purpose of having that second account in the first place, for whatever purpose it exists?)
I would try setting the registry to autologon with the user you want, and then simply logging off the admin user. That should log your kiosk-user right back on.
Not sure how to login another user once the current user logs off (not sure if windows would let you...)
But you can use shutdown to logoff:
shutdown /?
Here's some ideas that probaly fall into the "cheap hack" category:
How about logging in at UserB in the first place, and then using runas /user:userA <cmd> to run the first part of the install process?
If that's unacceptable, I know there's a way to make Windows workstations (those that aren't part of a Domain) automatically log in into a certain user account after a restart. Perhaps if you looked into which Registry changes happen, and duplicated them, a reboot would automatically log in that user. (Of course, as a final stage, after userB logs in, you would have to revert those changes :-)
It also occurs to me to wonder if perhaps there's a way for a service to force an open "login screen" to log in as a certain user. Maybe using some method like the way the Remote Desktop does it remotely... If that's possible, then you could create a service that you install before logoff of userA, that would trigger the login of userB.
You can script it with VNC (there are many free versions, take your pick). Set up a VNC server process on the machine to listen on localhost. When the user logs off, your logoff script will connect to the machine using VNC and send the keystrokes necessary to log on the next user. VNC uses the RFB (remote framebuffer) protocol; there are libraries for most popular languages, so you should be able to get something working quickly. Or there are related tools that might help.
If you were to run something like this as a normal script in a given language, it would most likely not work as when you log out of your account, all processes should be killed along with your running script.
You might be able to create some sort of 'service' that would run on a service account (i.e. always active) that would automatically do this user switching for you.
My bets are on Windows Powershell, although I'm not entirely sure what functionality it has as far as actually creating a service.
A quick search brings up the following (The second link is to a forum but it mentions running Powershell as a service and sending that service a parameter which would be the path to your user switching script)
How to Create a Windows Service using Powershel
Powershell Script as a Windows Service
I don't have a Windows 2003 server or a system with a "Group Policies" setup to test my hunch but you could take a look at SU ("switch user") for Windows. Originally part of the Resource Toolkit this has been extended to a new SUperior SU. Do post the results/script if this works.
You could approach this from the perspective of building a remote control utility (like VNC, etc). The big thing here is that if you want access to the Logon screen (i.e. the CTRL + ALT + DEL / username/password) part, the only kicker is that a Windows Service is the only component that can access this, so you'd have to create one.
The only problem I see with this technique as a whole is that even if you spent a great deal of effort getting it to work (and it would be a pretty big effort), the chances of this working successfully with the whole thing originating from a logoff script (i.e. when stuff is shutting down) are low even due to the number of things that can go wrong when logging back on as Administrator.
Just remember that for anything you need to run as an Administrator, there are easier ways in Windows to make that happen (such as Run As, changing the user permissions on the items that need to update, etc).