cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
jos3ph
Level 2

runtime update of ServiceInstall table

I have an installer (basic MSI) which must allow the user to configure the Windows services to run also under other accounts than default (Local System). Following this overview, I collect the username and password in a dialog in the UI sequence and I want to change that table in a custom action in the execution sequence.

This is my install script code:

hDatabase = MsiGetActiveDatabase(hMSI);

nResult = MsiDatabaseOpenView(hDatabase, "SELECT `Name`, `StartName`, `Password` FROM `ServiceInstall`", hView);
MsiViewExecute(hView, NULL);

while (MsiViewFetch(hView, hRecord) = ERROR_SUCCESS)
MsiRecordSetString(hRecord, 2, svUser);
MsiRecordSetString(hRecord, 3, svPassword);
MsiViewModify(hView, MSIMODIFY_UPDATE, hRecord);
endwhile;

MsiViewClose(hView);


The table stays unchanged and when logging the installation I see also this:
[code]
MSI (s) (A8!CC) [01:42:37:419]: Leaked MSIHANDLE (255) of type 790531 for thread 8140
MSI (s) (A8!CC) [01:42:37:419]: Leaked MSIHANDLE (254) of type 790531 for thread 8140
MSI (s) (A8!CC) [01:42:37:419]: Leaked MSIHANDLE (253) of type 790540 for thread 8140
[/code]

I guess there's something wrong with my code but I can't figure out what. I'd appreciate any suggestion.
Labels (1)
0 Kudos
(1) Reply
MichaelU
Level 12 Flexeran
Level 12 Flexeran

MSDN documents MsiViewModify as only able to update (via MSIMODIFY_UPDATE) when a record is read-write. It looks like you're trying to do this from a custom action; at that point the database is read-only, and thus only accepts changes like MSIMODIFY_INSERT_TEMPORARY.

As for your leaked handles, it looks like you're not calling MsiCloseHandle on hRecord after you finish it with your MsiViewModify call; that should be an easy fix. Unfortunately it's not clear that you'll be able to do what you desire this way.

Instead, the ServiceInstall table uses formatted fields for both the StartName and Password columns. Try populating those with (public) property formats like [SERVICE1_STARTNAME] and [SERVICE1_PASSWORD] (square brackets included), and then set the properties SERVICE1_STARTNAME and SERVICE1_PASSWORD accordingly (perhaps with MsiSetProperty, depending on where and how you get that data).
0 Kudos