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.
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.
An invalid handle and Custom actions
Started by
lokshin
, Mar 06 2002 09:38
7 replies to this topic
Posted 06 March 2002 - 12:18
Sounds weired. Do you generate a new package code each time you rebuild your setup?
Stefan Krüger
InstallSite.org twitter facebook
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.
Stefan Krüger
InstallSite.org twitter facebook
Posted 11 March 2002 - 08:26
Yes, I set this option in the project but it did not help.
Thanks,
Evgeny.
Thanks,
Evgeny.
Posted 12 March 2002 - 02:56
From the Windows Installer documentation, under Custom Actions > About Custom Actions > 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.
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
The geek shall inherit the earth
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;
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;
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.
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
The geek shall inherit the earth