2009-04-27 5 views
1

Je suis en train de maintenir quelques scripts de construction qui utilisent des bases de données MSI à partir de fichiers Javascript (.js). Le code est essentiellement:Javascript MSI automation - fermeture de la base de données

{ 
    var oTargetDB = g_oInstaller.openDatabase("mymsi.msi", msiOpenDatabaseModeReadOnly); 
    var oView = oTargetDB.openView(...); 
    oView.execute(); 
    oView.close(); 
} 
// Later... 
{ 
    var oTargetDB = g_oInstaller.openDatabase("mymsi.msi", msiOpenDatabaseModeTransact); 
} 

La deuxième OpenDatabase échoue avec les 0x80004005 toujours utiles (FAIL), que je suppose est parce que le premier n'est pas fermée. Toutefois, l'objet Database n'a pas de méthode close. J'ai essayé oTargetDB = null - n'a rien changé.

Que puis-je faire pour fermer la base de données, afin de pouvoir l'ouvrir à nouveau?

Edit:

  • Je vois la poignée ouverte en utilisant Handle.exe de Sysinternals, il est donc sans aucun doute le problème
  • retard n'a pas aidé (j'ai essayé d'attendre pour un temps très long, et il didn « aide t)
  • script de courte durée n'est pas une option en raison de la structure de script existant
  • Uber-hacking est au-delà de la portée de ce correctif
  • Je vais devoir enlaidir mon code et aller avec le (pseudo-singleton) s solution. Blergh.

Répondre

0

La définition du handle sur null fonctionne avec VB Script, donc je ne sais pas pourquoi cela ne serait pas le cas avec JS. Ma meilleure estimation serait peut-être que vous avez découvert un bug dans l'implémentation JS - surtout si vous l'ouvrez en lecture seule la première fois, il n'est pas nécessaire d'appeler la méthode Commit pour vider les modifications.

Le documentation semble indiquer que la simple fermeture de la poignée est tout ce qui est nécessaire pour fermer la base de données. Donc, je devine même après avoir défini oTargetDB = null Javascript ne libère pas le handle au moment où vous allez l'ouvrir à nouveau. Vous pouvez essayer d'insérer un délai après avoir relâché la poignée pour voir si c'est le cas.

0

Dans ce cas, MS a oublié d'implémenter une méthode de fermeture. Vraiment. Lame hein? En général, la définition de obj = null n'effectue pas de nettoyage tel que les opérations de fermeture.

Lorsque j'ai rencontré ce problème spécifique, il appelait les objets MSIDatabase à partir de C#. La base de données doit être fermée (voir MsiOpenDatabase et MsiCloseHandle). Malheureusement, comme vous l'avez observé, MS a oublié d'implémenter Database.Close dans l'objet COM que vous voyez. De C#, j'ai été en mesure d'appeler Marshal.FinalReleaseComObject pour déverrouiller le fichier.

Nous avons même abandonné l'objet COM comme non fiable et sommes passés à p/invoke.

Si jscript est votre seule option, vous pouvez garder les scripts de courte durée - quand ils meurent, ils libèrent leurs poignées. Ou, vous créez un singleton pour représenter l'objet. Potentiellement, certains uberhacker sauront comment appeler MsiCloseHandle à partir de jScript, et identifieront le descripteur utilisé par cet objet COM.

Questions connexes