Jump to content


This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.
Photo

An invalid handle and Custom actions


7 replies to this topic

lokshin

lokshin
  • Members
  • 11 posts

Posted 06 March 2002 - 09:38

Hi all,

In my Standard project I created CA with Action Type - 66560 (Type- Run InstallShield Code, Location-<none>, In - Script Execution - deferred execution). It is inserted just before InstallFinalize in sequences/actions view. In this CA I use data from the current msi (read rows from some tables). Each time I rebuild my project with new Product Code I receive an error - ERROR_INVALID_HANDLE (An invalid or inactive handle was supplied) while running the installation first time. If I run the setup next time even after uninstall "unsuccessful installation" it passes smoothly without any errors.

My question is - what could be the reason for the first time failure?

Thanks,
Evgeny.

Stefan Krueger

Stefan Krueger

    InstallSite.org

  • Administrators
  • 13,269 posts

Posted 06 March 2002 - 12:18

Sounds weired. Do you generate a new package code each time you rebuild your setup?

lokshin

lokshin
  • Members
  • 11 posts

Posted 06 March 2002 - 13:37

No, only when I make some major changes.

Thanks,
Evgeny.

Stefan Krueger

Stefan Krueger

    InstallSite.org

  • Administrators
  • 13,269 posts

Posted 06 March 2002 - 13:54

Package code must be changed each time you rebuild your msi, else you'll get weired behaviour. I believe there's an option in the product configuration properties that causes InstallShield to auto-generate the package code for each build.

lokshin

lokshin
  • Members
  • 11 posts

Posted 11 March 2002 - 08:26

Yes, I set this option in the project but it did not help.

Thanks,
Evgeny.

KiwiGeek

KiwiGeek
  • Members
  • 19 posts

Posted 12 March 2002 - 02:56

From the Windows Installer documentation, under Custom Actions > About Custom Actions > Deferred Execution Custom Actions
Quote
Because the installation script can be executed outside of the installation session in which it was written, the session may no longer exist during execution of the installation script. This means that the session handle and property data set during the installation sequence is not available to a deferred execution custom action. A custom action that calls a dynamic-link library (DLL) requires a handle to the installation session. Therefore if this is also a deferred execution custom action, the action must obtain its context information as described in Obtaining Context Information for Deferred Execution Custom Actions.

You may find that your problems are some sort of side-effect of this.  One work-around would be to use an immediate execution custom action to get the data and put it into properties, and then use these properties to populate the CustomActionData property. Your custom action can then use this property to get its information.
Jamie
The geek shall inherit the earth

lokshin

lokshin
  • Members
  • 11 posts

Posted 12 March 2002 - 18:39

One more thing. It happened not only in the CA but in the function that I call in OnMoved Event every time I create a new build (with new Package Code).
Here is a piece of code maybe somebody could help me with this problem:

function DBGetValue (hMsi, szSQLQuery, nField, szColumnType, szPropertyValue, nValue)
NUMBER nResult, nBufSize;
HWND hView, hRecord, hDataBase;
begin

// Obtain a handle to the active database
hDataBase = MsiGetActiveDatabase(hMsi);

if(hDataBase = 0) then
MessageBox("Unable to open active database", SEVERE);
exit;
endif;
// Create a view object as specified by szQuery
nResult = MsiDatabaseOpenView(hDataBase, szSQLQuery, hView);
if(nResult != ERROR_SUCCESS) then
MessageBox("Create View failed", SEVERE);

MsiCloseHandle(hDataBase);
MsiCloseHandle(hView);
return ERROR_INSTALL_FAILURE;
endif;

// Execute the view object and make it
// ready for retrieving records

nResult = MsiViewExecute(hView, NULL);

if(nResult != ERROR_SUCCESS) then

MessageBox("Execute View failed", SEVERE);

MsiCloseHandle(hDataBase);
MsiCloseHandle(hView);
return ERROR_INSTALL_FAILURE;
endif;

nResult = MsiViewFetch(hView, hRecord);

if(nResult != ERROR_SUCCESS) then
MessageBox("Fetch View failed", SEVERE);

MsiCloseHandle(hDataBase);
MsiCloseHandle(hView);
MsiCloseHandle(hRecord);
return ERROR_INSTALL_FAILURE;
endif;


// Explicitly set the value buffer to an empty string
// so we can obtain the required buffer size
switch ( szColumnType )
case "STRING":
// Explicitly set the value buffer to an empty string
// so we can obtain the required buffer size
szPropertyValue = "";
nBufSize = 0;
MsiRecordGetString(hRecord, nField, szPropertyValue,
nBufSize);

// Now that we know the required buffer size set the
// buffer size and get the property value
nBufSize = nBufSize + 1;
Resize(szPropertyValue, nBufSize);
MsiRecordGetString(hRecord, nField, szPropertyValue,
nBufSize);
case "INTEGER":
nValue = MsiRecordGetInteger (hRecord, nField);
default :
MessageBox ("Binary Type", INFORMATION);
MsiCloseHandle(hRecord);
MsiCloseHandle(hDataBase);
MsiCloseHandle(hView);
return ERROR_SUCCESS;
endswitch;

MsiCloseHandle(hRecord);
MsiCloseHandle(hDataBase);
MsiCloseHandle(hView);


return ERROR_SUCCESS;
end;

KiwiGeek

KiwiGeek
  • Members
  • 19 posts

Posted 12 March 2002 - 21:48

Without actually running the code, I would guess that this function fails at MsiGetActiveDatabase. If so, then this is definitely due to the issue I pointed out a couple of postings ago.

One workaround is to use an immediate custom action to populate a series of global InstallScript variables. The values in these variables should then be available during deferred execution. The only possible difficult bit is figuring out which queries to make before the components are moved :)

I know it's messy, but if Microsoft hadn't made Windows Installer so braindead we wouldn't need to do any of this.
Jamie
The geek shall inherit the earth