Question

I'm trying to use <util:User Id="UpdateServiceAccountLogonAsService" UpdateIfExists="yes" CreateUser="no" Name="[SERVICEACCOUNTFULL]" LogonAsService="yes"/> to grant logonAsService to a UI-specified user. This property value IS UPDATED prior to this util:User getting processed at runtime.

I know this because I can give the SERVICEACCOUNTFULL property a default value of "localhost\defaultUserValue" and set CreateUser="yes" and it will generate a runtime messagebox error about that showing the original value after my custom action has set the property values. Not sure why that fails to create the user, but it shows the right timing. If I hard-code the property default values to what I would be setting them to dynamically (with CreateUser="no") it works.

The <ServiceInstall /> tag I have as part of the same component correctly uses the updated values of the property, but <util:User /> won't.

Remember that I am verifying that the createUser step happens after the custom action program that sets the Property values. But now I'll mention that strangely, the createUser action execution is in the log just above the custom action that gets the property values and whose Before="InstallFiles".

Help? Thanks!

===========

Hi Rob,

Not exactly sure what you need to see but I think these are relevant:

<Component Id="Service" Guid='*'>
  <File Source='$(var.root)My Service.exe' />
  <ServiceInstall Id="ServiceInstall"
    Name="MyServer"
    DisplayName="My Server"
    Type="ownProcess"
    Start="auto"
    ErrorControl="normal"
    Description="My Server Windows Service"
    Interactive="no"
    Account="[SERVICEACCOUNTFULL]"
    Password="[SERVICEACCOUNTPASSWORD]" />
  <ServiceControl Id="StopMyServer" Name="MyServer" Stop="both" Wait="yes" Remove="uninstall" />
  <util:User Id="UpdateServiceAccountLogonAsService" UpdateIfExists="yes" 
    CreateUser="no" Name="[SERVICEACCOUNTFULL]" LogonAsService="yes"/>
</Component>

...

<Binary Id="ConfigBinary" SourceFile="$(var.....TargetDir)$(var.Configuration.TargetName).CA.exe" />

<Property Id="Net">net.exe</Property>
<CustomAction Id="NetStart" Property="Net" ExeCommand="START MyServer" Return="check" />

<Property Id="PerformNetStart" Value="0" />
<CustomAction Id='SetPerformNetStart' Property='PerformNetStart' Value='1' />
<CustomAction Id="RunConfiguration" BinaryKey="ConfigBinary" DllEntry="RunConfiguration" Execute="immediate" Return="check" />
<CustomAction Id='IsPrivileged' Error='You must be an admin to install this feature' />

<InstallExecuteSequence>
    <Custom Action='IsPrivileged' Before='RunConfiguration'>
    <![CDATA[Not Privileged AND &FeatureServer > 2 ]]>
    </Custom>
    <Custom Action="RunConfiguration" Before="InstallFiles">
    <![CDATA[&FeatureServer > 2 AND Not Installed ]]>
    </Custom>
    <Custom Action="SetPerformNetStart" Before="InstallFiles">
    <![CDATA[&FeatureServer > 2 AND Not Installed ]]>
    </Custom>
    <Custom Action="NetStart" After="InstallFinalize">
    PerformNetStart = 1
    </Custom>
</InstallExecuteSequence>

Then in C#:

public static ActionResult RunConfiguration(Session session)
{
    session["SERVICEACCOUNTFULL"] = "MyDomain\svcAccount";
    session["SERVICEACCOUNTPASSWORD"] = "secret;

    return ActionResult.Success;
}

Here are the logs of a hard-coded valid value run:

MSI (s) (F0:F8) [18:29:29:191]: Created Custom Action Server with PID 4796 (0x12BC).
MSI (s) (F0:CC) [18:29:29:211]: Running as a service.
MSI (s) (F0:CC) [18:29:29:213]: Hello, I'm your 32bit Impersonated custom action server.
MSI (s) (F0!48) [18:29:29:240]: PROPERTY CHANGE: Adding CreateUserRollback property. Its value is '**********'.
MSI (s) (F0!48) [18:29:29:243]: Doing action: CreateUserRollback
Action 18:29:29: CreateUserRollback. 
Action start 18:29:29: CreateUserRollback.
CreateUserRollback: 
Action ended 18:29:29: CreateUserRollback. Return value 1.
MSI (s) (F0!48) [18:29:29:247]: PROPERTY CHANGE: Adding CreateUser property. Its value is '**********'.
MSI (s) (F0!48) [18:29:29:247]: Doing action: CreateUser
Action 18:29:29: CreateUser. 
Action start 18:29:29: CreateUser.
CreateUser: 
Action ended 18:29:29: CreateUser. Return value 1.
Action ended 18:29:29: ConfigureUsers. Return value 1.
MSI (s) (F0:F0) [18:29:29:252]: Skipping action: IsPrivileged (condition is false)
MSI (s) (F0:F0) [18:29:29:252]: Doing action: RunConfiguration
Action 18:29:29: RunConfiguration. 
Action start 18:29:29: RunConfiguration.
MSI (s) (F0:E0) [18:29:29:286]: Invoking remote custom action. DLL: C:\Windows\Installer\MSIC008.tmp, Entrypoint: RunConfiguration
SFXCA: Extracting custom action to temporary directory: C:\Users\Jason\AppData\Local\Temp\MSIC008.tmp-\
SFXCA: Binding to CLR version v4.0.30319
Calling custom action ...Configuration!...RunConfiguration
Begin RunConfiguration
Setting MSI values from RunConfiguration
MSI (s) (F0!48) [18:29:47:629]: PROPERTY CHANGE: Modifying RUNTIMECONNECTIONSTRING property. Its current value is 'DEFAULT'. Its new value: 'Data Source=.;Initial Catalog=DB;Integrated Security=True'.
MSI (s) (F0!48) [18:29:47:629]: PROPERTY CHANGE: Modifying SERVICEACCOUNTFULL property. Its current value is 'MyDomain\DEFAULTVALUE'. Its new value: 'MyDomain\svcAccount'.
...
Returning from RunConfiguration

It's logged in this backwards order which would explain the problem except that when I make CreateUser action error out on CreateUser="yes" it clearly happens several beats after the Configuration custom action returns. But perhaps it's queued up some weird way and really the order of execution IS the problem -- in that case I still don't know how to control that order.

Is this good information for you to diagnose?

Was it helpful?

Solution

The issue is that your custom action RunConfiguration that sets the property to be used by the User element is running too late. Instead of scheduling the RunConfiguration before InstallFiles instead schedule the action before ConfigureUsers. Something like:

<Custom Action="RunConfiguration" Before="ConfigureUsers">
<![CDATA[&FeatureServer > 2 AND Not Installed ]]>
</Custom>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top