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

second MsiOpenDatabaseA()


3 replies to this topic

bernard

bernard
  • Full Members
  • 127 posts

Posted 26 April 2011 - 14:55

Habe InstallScript Project (ohne MSI)
Möchte von meinen *.msi Files die GUID nur auslesen und ...

Beim Auslesen von zweitem msi-File bekomme Error 1631: -> ERROR_CREATE_FAILED The database could not be created.
// The Windows Installer service failed to start. Contact your support personnel.

Habe gesucht. Fand ich:
http://us.generation-nt.com/answer/vb-open-two-databases-second-fails-1631-help-52140942.html
October 03rd, 2004 Dennis Bareis
VB to open two databases, second fails with 1631


Wie soll ich meine Scripte ändern?
Brauche Eure Hilfe dringen.

Dazu mein Script:
-- setup.rul --
#include "IsMsiQuery.h"
#include "MsiFuncsConv.h"
// meine function
prototype BOOL dltMsiNew_GUID(STRING, STRING, STRING, BYREF STRING);
prototype number MSI.MsiViewClose(HWND);

if dltMsiNew_GUID(WINSYSDIR, "msi.dll", "xx.msi", svProductGuid) then
// ....
endif;

function BOOL dltMsiNew_GUID(szMsi_Directory,szWindMsiDll,szdltProduct_Msi,szOld_MsiProduct)
// return - szOld_MsiProduct = ProductCode
HWND hdltProd_MSI, hdltProd_Record;
string sz_MsiFile_Control, svProductGuid[128];
number nvOpenMsiDll, nvCount, nvCount_Record;
BOOL bv_Product_Msi;
begin
bv_Product_Msi = TRUE;

sz_MsiFile_Control = szMsi_Directory ^ szWindMsiDll;
nvOpenMsiDll = UseDLL(sz_MsiFile_Control);

nvOpenMsiDll = MsiOpenDatabaseA(szdltProduct_Msi, MSIDBOPEN_READONLY, hdltProd_MSI);
// probiert habe mit: nvOpenMsiDll = MsiOpenDatabase(szdltProduct_Msi, "0", hdltProd_MSI);
switch (nvOpenMsiDll)
case ERROR_CREATE_FAILED:
// MessageBox(" MsiOpenDatabaseA -> ERROR_CREATE_FAILED The database could not be created.",INFORMATION);
bv_Product_Msi = FALSE;
case ERROR_INVALID_PARAMETER:
// MessageBox(" MsiOpenDatabaseA: One of the parameters was invalid.",INFORMATION);
bv_Product_Msi = FALSE;
case ERROR_OPEN_FAILED:
// MessageBox(" MsiOpenDatabaseA: The database could not be opened as requested.",INFORMATION);
bv_Product_Msi = FALSE;
case ERROR_SUCCESS:
// MessageBox(" MsiOpenDatabaseA: The function succeeded.",INFORMATION);
endswitch;

nvCount = 127;
nvOpenMsiDll = MsiDatabaseOpenViewA(hdltProd_MSI, "Select `Value` From Property WHERE `Property` ='ProductCode'", nvCount);
nvOpenMsiDll = MsiViewExecute(nvCount,0);
nvOpenMsiDll = MsiViewFetch(nvCount, hdltProd_Record);
nvCount_Record = 127;
nvOpenMsiDll = MsiRecordGetStringA(hdltProd_Record, 1, svProductGuid, nvCount_Record);
szOld_MsiProduct = svProductGuid;
nvOpenMsiDll = MsiViewClose(nvCount);
nvOpenMsiDll = MsiDatabaseCommit(hdltProd_MSI);
nvOpenMsiDll = MsiCloseHandle(hdltProd_MSI);
if ( UnUseDLL(szWindMsiDll) < 0 ) then
// MessageBox("UnUseDLL: Indicates that the function was unable to unlock or unload the .dll file.\n" + szWindMsiDll,INFORMATION);
endif;

return bv_Product_Msi;
end; // function dltMsiNew_GUID()

Danke im Voraus


bernard

bernard
  • Full Members
  • 127 posts

Posted 28 April 2011 - 06:19

Es wurde ein File mit Namen "0" im SRCDIR immer erstellt.

Die Lösung:
Statt
nvOpenMsiDll = MsiOpenDatabaseA(szdltProduct_Msi, MSIDBOPEN_READONLY, hdltProd_MSI);
habe so eingetragen:

GetEnvVar("TEMP", szTempDirectory);
ParsePath(sv_Temp_Product_Msi, szdltProduct_Msi, FILENAME_ONLY);
sv_Temp_Product_Msi = sv_Temp_Product_Msi + ".xxxx";
sv_Temp_Msi = szTempDirectory ^ sv_Temp_Product_Msi;
nvOpenMsiDll = MsiOpenDatabaseA(szdltProduct_Msi, sv_Temp_Msi, hdltProd_MSI);

Es wird ein neues File pro msi-File im %TEMP%-Verzeichnis erstellt.

Problem
Kann es später nach MsiCloseHandle() und UnUseDLL() nicht löschen.
Habt ihr eine Idee?

Danke im Voraus

Edited by bernard, 28 April 2011 - 06:21.


bernard

bernard
  • Full Members
  • 127 posts

Posted 28 April 2011 - 06:28

QUOTE
Kann es später nach MsiCloseHandle() und UnUseDLL() nicht löschen.

if (DeleteFile(sv_Temp_Msi) = 0) then
MessageBox(" DeleteFile-" + sv_Temp_Msi,INFORMATION);
else
MessageBox(FormatMessage(LAST_RESULT),SEVERE);
endif;

Kommt: Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.


bernard

bernard
  • Full Members
  • 127 posts

Posted 18 July 2011 - 11:35

QUOTE
Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.

Die Lösung:
Es fehlt eine MsiCloseHandle() noch.

Jetzt ist im Script so:
nvOpenMsiDll = MsiOpenDatabaseA(szdltProduct_Msi, sv_Temp_Msi, hdltProd_MSI);
nvOpenMsiDll = MsiDatabaseOpenViewA(hdltProd_MSI, sz_Select_Property, nvCountOpenView);
nvOpenMsiDll = MsiViewExecute(nvCountOpenView,0);
nvOpenMsiDll = MsiViewFetch(nvCountOpenView, hdltProd_Record);
nvCount_Record = 127;
nvOpenMsiDll = MsiRecordGetStringA(hdltProd_Record, 1, svProductGuid, nvCount_Record);
nvOpenMsiDll = MsiViewClose(nvCountOpenView);
nvOpenMsiDll = MsiDatabaseCommit(hdltProd_MSI);
nvOpenMsiDll = MsiCloseHandle(nvCountOpenView);
nvOpenMsiDll = MsiCloseHandle(hdltProd_MSI);

Werden die temporary Files im %TEMP%-Verzeichnis gelöscht.