Freigeben über


Anwendungsresilienz: Entsperren der ausgeblendeten Features von Windows Installer

 

Michael Sanford
701 Software

März 2005

Zusammenfassung: Windows Installer verfügt über mehrere Features, die von der Entwicklungscommunity weitgehend unbemerkt geblieben sind. Diese Features ermöglichen es einer Anwendung, sich zur Laufzeit selbst zu reparieren oder optionale Komponenten basierend auf der Interaktion des Benutzers mit der Anwendung zu installieren. (10 gedruckte Seiten)

Laden Sie das MSI-Integrationsbeispiel Code.msiherunter.

Inhalte

Einführung
Resilienz durch Shellintegration
Einführung in die Windows Installer-API
Wichtige Anwendungs-APIs
Herausforderung Nr. 1: Self-Invoked Resilienz
Herausforderung Nr. 2: Bei Bedarf installieren
Schlussbemerkung

Einführung

Als Entwickler neigen wir wirklich dazu, an unsere Anwendungen zu denken, die in idealen Umgebungen, auf idealen Systemen und von idealen Benutzern ausgeführt werden, die die Anwendung nach einer erfolgreichen Installation verwenden. Die Realität ist, dass ihre Lebensdauer für diesen Benutzer erst begonnen hat, nachdem unsere Anwendungen erfolgreich installiert wurden. Die Herausforderungen, mit denen unsere Anwendung konfrontiert ist, stabil und funktionsfähig zu bleiben, sind vielfältig, aber die meisten Anwendungen sind nicht darauf vorbereitet, Änderungen in der Betriebsumgebung zu bewältigen, die dazu führen könnten, dass die Anwendung nicht mehr funktionsfähig ist.

Windows Installer bietet Resilienzfeatures, die erhebliche Fortschritte bei der Stabilität unserer Anwendungen gemacht haben, aber diese Funktion basiert auf bestimmten Aktionen, die der Benutzer während der Interaktion mit der Shell ausführt, um "Einstiegspunkte" bereitzustellen, über die Windows Installer Probleme mit der Konfiguration der Anwendung erkennen und Schritte zur Reparatur der Anwendung ausführen kann.

Im Folgenden finden Sie eine kurze Liste der Einstiegspunkte für Windows Installer:

  • Verknüpfungen. Windows Installer führt eine spezielle Art von Verknüpfung ein, die zwar für den Benutzer transparent ist, aber zusätzliche Metadaten enthält, die Windows Installer über die Shellintegration verwendet, um den Installationsstatus der angegebenen Anwendung vor dem Starten der Anwendung zu überprüfen.
  • Dateizuordnungen. Windows Installer bietet einen Mechanismus zum Abfangen von Aufrufen für die zugeordnete Anwendung eines Dokuments oder einer Datei, sodass Windows Installer die Anwendung überprüfen kann, wenn ein Benutzer ein Dokument oder eine Datei mithilfe der Shell öffnet.
  • COM-Werbung. Windows Installer stellt einen Mechanismus bereit, der in das COM-Subsystem eingebunden ist, sodass jede Anwendung, die eine instance einer com-Komponente erstellt, die von Windows Installer installiert wird (und für die Verwendung dieses Features konfiguriert ist), eine instance dieser Komponente erhält, nachdem Windows Installer den Installationsstatus dieser Komponente überprüft hat.

Unter bestimmten Umständen können die integrierten Resilienzfeatures von Windows Installer möglicherweise nicht alle Probleme mit der Konfiguration unserer Anwendung erkennen, oder unsere Anwendung funktioniert möglicherweise so, dass die erforderlichen Einstiegspunkte nicht aktiviert werden. Glücklicherweise verstanden die intelligenten Leute im Windows Installer-Team diese Herausforderung und stellten uns zusätzliche Resilienzfeatures über die umfassende Windows Installer-API zur Verfügung.

Resilienz durch Shellintegration

Bevor wir mit den erweiterten Resilienzfeatures der Windows Installer-API fortfahren, werfen wir einen Blick auf ein typisches Resilienzszenario, das wir normalerweise kostenlos erhalten, wenn wir unsere Apps mit Windows Installer bereitstellen.

In diesem Szenario stellen wir eine einfache Textbearbeitungsanwendung bereit, die wir SimplePad nennen. Um die Installation zu erstellen, verwenden wir das Open Source WiX Toolkit von Microsoft (weitere Informationen finden Sie unter https://sourceforge.net/projects/wix/.), aber Sie können dasselbe mit jedem Tool Ihrer Wahl erreichen.

<Directory Id="TARGETDIR" Name="SourceDir">
<Component Id="SimplePad" Guid="BDDFA5DC-BD69-4232-998E-5167814C21B9" 
  KeyPath="no">
  <File Id="SimplePadConfig" Name="SP.cfg"
    src="$(var.SrcFilesPath)SimplePad.exe.config"
    LongName="SimplePad.exe.config" Vital="yes" KeyPath="no" DiskId="1" />
  <File Id="SimplePad" Name="Simple~1.exe"
    src="$(var.SrcFilesPath)SimplePad.EXE" LongName="SimplePad.exe" Vital="yes"
    KeyPath="yes" DiskId="1" >
  <Shortcut Id="SC1" Advertise="yes"  Directory="ProgramMenuFolder"
    Name="SimpPad" LongName="Run SimplePad"  />
  </File>
</Component>
<Directory Id="ProgramMenuFolder" Name="ProgMenu"></Directory>
</Directory>

Wie Sie im obigen XML-Fragment sehen können, haben wir eine sehr einfache Installation mit einer Datei (SimplePad.exe) und einer einzelnen Verknüpfung im Startmenü des Benutzers erstellt. Es ist wichtig zu beachten, dass in diesem Beispiel die Verknüpfung, die wir erstellen, der Einstiegspunkt ist, den Windows Installer verwendet, um den Zustand der Anwendung zu erkennen und bei Bedarf zu reparieren.

An diesem Punkt können wir unser Installationsprogramm erstellen, die Anwendung installieren und die neu erstellte Verknüpfung zum Startmenü verwenden, um es auszuführen. Wie erwartet funktioniert die Anwendung genau wie gewünscht. Um die integrierten Resilienzfeatures von Windows Installer zu testen, können wir die SimplePad.exe Datei löschen und versuchen, die Anwendung über die Startmenüverknüpfung auszuführen. Wie erwartet erkennt Windows Installer, dass SimplePad.exe fehlt, und eine Reparatur wird gestartet. Während des Reparaturvorgangs liest Windows Installer die erforderlichen Konfigurationsinformationen aus seiner intern zwischengespeicherten Kopie des Installationspakets und ersetzt schließlich die fehlende Datei, und fordert den Benutzer zur Eingabe des Quellinstallationsmediums auf, wenn es nicht am ursprünglichen Speicherort vorhanden ist, von dem aus es installiert wurde. Nach Abschluss des Reparaturvorgangs wird die Anwendung wie gewohnt gestartet.

Abbildung 1. Reparaturvorgang wird ausgeführt

Die Resilienz von Anwendungen wird auch von Windows Installer über eine Reihe anderer Mechanismen bereitgestellt, die hier erwähnt werden müssen. Die zweithäufigste Methode, um sicherzustellen, dass Anwendungen hochverfügbar bleiben, sind Windows Installer-Dateizuordnungen. Dieser Mechanismus funktioniert sehr ähnlich wie Windows Installer-Verknüpfungen, aber anstatt eine direkte Verknüpfung mit der ausführbaren Datei einer Anwendung herzustellen, wird die Zuordnung durch einen registrierten Dateityp vorgenommen. Wie Sie in Abbildung 2 sehen können, werden Windows Installer-Dateizuordnungen mit demselben Mechanismus definiert, den Standarddateizuordnungen verwenden, mit einer Ausnahme. Beachten Sie in Abbildung 2, dass unter dem typischen Registrierungsschlüssel "shell\Open\command" ein zusätzlicher Wert aufgeführt ist. Mit dem zusätzlichen Wert (auch als "Befehl" bezeichnet) sucht Windows Installer jedes Mal, wenn Sie in der Windows-Shell auf eine Datei doppelklicken. Diese kryptisch anmutende Zeichenfolge, manchmal auch als "Darwin-Deskriptor" bezeichnet, ist eigentlich eine codierte Darstellung eines bestimmten Produkts, einer bestimmten Komponente und eines bestimmten Features. Wenn dieser zusätzliche Wert vorhanden ist, decodiert Windows Installer die Daten und verwendet ihn, um Überprüfungen für dieses Produkt und diese Komponente durchzuführen. Wenn festgestellt wird, dass die Komponente fehlt oder beschädigt ist, startet Windows Installer eine Reparatur, um die fehlende Datei oder Die fehlenden Daten wiederherzustellen, und startet schließlich die Anwendung, auf die verwiesen wird, wie gewohnt, und übergibt die entsprechenden Befehlszeilenoptionen an sie.

Abbildung 2. Anzeigen eines "Darwin-Deskriptors" für eine Dateizuordnung

Der endgültige Resilienzmechanismus, den wir heute besprechen, wird allgemein als COM-Werbung bezeichnet. Bevor wir uns die Mechanismen von COM Advertising ansehen, ist es wichtig, den Anwendungsfall dahinter zu verstehen. Angenommen, Sie waren ein Komponentenanbieter, der eine COM-basierte freigegebene Bibliothek bereitstellt, die Postgebühren in Echtzeit bereitstellt. Da diese Komponente von vielen verschiedenen Produkten verwendet werden kann, wird sie an einem einzigen freigegebenen Speicherort auf dem System des Endbenutzers installiert. Um sicherzustellen, dass die Komponente immer am selben Speicherort installiert wird und die Komponente hochverfügbar bleibt, senden Sie sie an Ihre Kunden in einem Mergemodul, das ordnungsgemäß konfiguriert ist, um COM Advertising zu nutzen. Da Ihre Lösung als einzelne .dll Datei ohne Benutzeroberfläche bereitgestellt wird, reichen die anderen Resilienzmechanismen natürlich nicht aus. In diesem Fall können wir uns auf COM Advertising verlassen, um sicherzustellen, dass unsere Komponente ordnungsgemäß installiert und auf dem System des Benutzers registriert bleibt. Wenn eine Anwendung eine instance dieser Komponente über normale COM-Mechanismen erstellt, "bindet" Windows Installer den Prozess auf die gleiche Weise ein, wie wir es mit Dateizuordnungen gesehen haben. Beachten Sie in Abbildung 3, dass dieses Mal ein "Darwin-Deskriptor" im Registrierungswert InprocServer32 für die COM-Registrierung unserer Komponente gespeichert wird. Auch hier werden diese Informationen decodiert und von Windows Installer verwendet, um sicherzustellen, dass unsere Komponente ordnungsgemäß installiert und konfiguriert ist, wobei ggf. Reparaturen durchgeführt werden, bevor schließlich ein instance Ihrer Komponente an die aufrufende Anwendung zurückgegeben wird.

Es sollte darauf hingewiesen werden, dass dieses einzigartige Feature völlig unabhängig von der Anwendung funktioniert, die die -Komponente verwendet. Anders ausgedrückt: Selbst wenn die Anwendung, die die Komponente verwendet, nicht mit Windows Installer installiert wurde, funktioniert die von der Komponente verwendete COM-Werbung weiterhin ordnungsgemäß, auch wenn die aufrufende Anwendung nur ein VBScript ist.

Abbildung 3. Anzeigen eines "Darwin-Deskriptors" für einen COM-Server

Bisher hat alles, worüber wir gesprochen und gezeigt haben, die Funktionen von Windows Installer genutzt, ohne eine einzige Codezeile schreiben zu müssen, aber jetzt ist es an der Zeit, zu einer umfangreicheren und robusteren Implementierung überzugehen.

Einführung in die Windows Installer-API

Das Standardverhalten von Windows Installer hat uns im vorherigen Szenario gut funktioniert, aber in der Praxis haben wir häufig etwas komplexere Anwendungen. Lassen Sie uns unser Beispielszenario erweitern, um ein anspruchsvolleres Szenario zu behandeln.

Häufig besteht eine Anwendung aus mehreren ausführbaren Dateien. Ein Beispiel ist eine Anwendung, die eine ausführbare Bootstrapper-Datei verwendet, um nach Updates für eine Anwendung zu suchen und zu installieren, wie im Updater-Anwendungsblock zu sehen. In diesem Fall ist die erste ausführbare Datei die, die aufgerufen wird, wenn der Benutzer im Startmenü auf eine Verknüpfung klickt. Daraufhin wird die zweite ausführbare Datei gestartet, die die Standard Benutzeroberfläche Ihrer Anwendung enthält. Je nachdem, wie Ihre Installation konfiguriert wurde, besteht eine gute Chance, dass Probleme mit der ausführbaren Standard Anwendung von der Windows Installer-Engine nicht erkannt werden. Eine Möglichkeit besteht möglicherweise darin, eine Reihe von Code zu schreiben, der beim Start ausgeführt wird, der die Laufzeitumgebung überprüft. Dies funktioniert jedoch einfach nicht, wenn die ausführbare Datei selbst fehlt oder beschädigt ist und darüber hinaus das Problem nicht einfach beheben kann. Eine viel effektivere Lösung besteht darin, das Wissen von Windows Installer über die Konfiguration Ihrer Anwendung zu nutzen, die bereits in Ihrem Bereitstellungspaket definiert ist.

Die Windows Installer-API macht die gleichen Mechanismen zum Überprüfen der Integrität einer Anwendung verfügbar, die sie verwendet, wenn der Benutzer mit der Shell interagiert. Durch die Verwendung dieser API-Aufrufe aus unserer Anwendung können wir sicher sein, dass weiterhin die gleichen Vorteile erzielt werden, ohne dass die zuvor beschriebenen Shell-Einstiegspunkte verwendet werden.

Im Folgenden finden Sie eine Liste der Szenarien, die nicht von den Features der Shellintegrationsresilienz von Windows Installer abgedeckt werden:

  • Apps, die mit dem Betriebssystem beginnen (Registrierungsschlüssel ausführen oder einmal ausführen)
  • Systemdienste
  • Geplante Aufgaben
  • Von anderen Apps ausgeführte Apps
  • Befehlszeilen-Apps

Ich bin sicher, dass es viele weitere Szenarien gibt, die wir der obigen Liste hinzufügen könnten, aber ich denke, Sie haben die Idee. Im folgenden Beispiel veranschaulichen wir, wie wir die Vorteile der Windows Installer-Resilienz nutzen können, ohne die zuvor erläuterten Shell-Integrationsfeatures zu nutzen. Wenn wir fertig sind, können Sie diese Konzepte nutzen und sie problemlos auf jedes Szenario anwenden, in dem ausführbarer Code ausgeführt wird.

Wichtige Anwendungs-APIs

Bevor wir uns mit einigen Beispielszenarien befassen, werfen wir einen Blick auf einige der wichtigsten Windows Installer-APIs, die Sie in Ihren Anwendungen verwenden können. Spezifische Informationen zur Verwendung dieser APIs finden Sie in der Windows Installer-Finction-Referenz im Platform SDK.

Wichtige Windows Installer-Funktionen Beschreibung
MsiProvideComponent Ruft den installierten Speicherort einer Komponente ab und installiert oder repariert nach Bedarf, um sicherzustellen, dass die Komponente verfügbar ist.
MsiQueryFeatureState Gibt den Installationsstatus eines bestimmten Features zurück. Mit dieser Funktion erfahren Sie beispielsweise, ob das Feature installiert, nicht installiert oder angekündigt ist.
MsiQueryProductState Gibt den Installationsstatus eines Produkts zurück. Mit dieser Funktion erfahren Sie beispielsweise, ob das Produkt installiert, angekündigt, für einen anderen Benutzer installiert oder überhaupt nicht installiert ist.
MsiConfigureProduct
MsiConfigureProductEx
Mit diesen beiden Funktionen können Sie eine Anwendung programmgesteuert installieren oder deinstallieren. MsiConfigureProductEx bietet eine bessere Kontrolle, da Sie Optionen angeben können, die denen ähneln, die Sie normalerweise in der Befehlszeile ausführen würden.
MsiConfigureFeature Mit dieser Funktion können Sie ein bestimmtes Feature einer Anwendung installieren, deinstallieren oder ankündigen.
MsiGetUserInfo Diese Funktion gibt den Namen des Benutzers, den organization und die Produktseriennummer zurück, die während der Installationssequenz des Produkts erfasst wurden.
MsiGetComponentPath
MsiLocateComponent
Diese beiden Funktionen unterstützen Sie bei der Bestimmung des physischen Speicherorts einer Komponentendatei oder eines Registrierungsschlüssels im Zielsystem. MsiGetComponentPath gibt den Pfad der von einem bestimmten Produkt installierten instance der Komponente zurück, während MsiLocateComponent den ersten instance einer Komponente zurückgibt, die von JEDEM Produkt installiert wird.

Herausforderung Nr. 1: Self-Invoked Resilienz

Zuvor haben wir über ein sehr einfaches Szenario gesprochen, in dem wir tatsächlich die ausführbare Datei unserer Anwendung aus dem System löschen und eine Verknüpfung verwenden könnten, um Windows Installer dazu zu bringen, das Problem zu erkennen und zu beheben, indem die fehlende Datei neu installiert wird. Obwohl dieses Szenario gut funktioniert hat, um die Shell-Integration zu demonstrieren, die Windows Installer nutzt, werfen wir einen Blick auf ein etwas komplexeres Szenario, um diese Konzepte zu vertiefen.

In diesem Szenario besteht die Anwendung aus einer einzelnen .exe-Datei und mehreren Textdateien, die wichtige Konfigurationsinformationen für die Anwendung bereitstellen.

Der technische Support unseres hypothetischen Softwareunternehmens hat viele Supportanfragen erhalten, die zeigen, dass Probleme mit der Anwendungskonfiguration nicht von Windows Installer gelöst werden, da Benutzer die Anwendung direkt ausführen, indem sie auf die ausführbare Datei in Windows Explorer doppelklicken, anstatt die von unserer Installation erstellte Startmenüverknüpfung zu verwenden.

Nach Rücksprache mit dem Zuständigen für die Bereitstellung des Teams entscheidet unser Technikerteam, dass die Anwendung erheblich davon profitieren würde, indem sie beim Start eine eigene Resilienzprüfung durchführt, um sicherzustellen, dass sie ordnungsgemäß konfiguriert ist. Um dies zu erreichen, fügt das Team einfach einen Aufruf der MsiProvideComponent-API hinzu, um sicherzustellen, dass die im Installationspaket der Anwendung definierten kritischen Komponenten ordnungsgemäß installiert und konfiguriert sind.

<DllImport("msi.dll")> _
Private Shared Function MsiProvideComponent(ByVal szProduct As String, ByVal _
 szFeature As String, ByVal szComponent As String, ByVal dwInstallMode As _
 MSI_REINSTALLMODE, ByVal lpPathBuf As System.Text.StringBuilder, ByRef _
 pcchPathBuf As IntPtr) As Integer
End Function

Public Shared Function ProvideComponent(ByVal productCode As String, ByVal _
 featureName As String, ByVal compID As String) As String
  Dim iRet As Integer
  Dim cbBuffer As Integer = 255
  Dim buffer1 As New System.text.StringBuilder(cbBuffer)
  Dim pSize As New IntPtr(cbBuffer)
  iRet = MsiProvideComponent(productCode, featureName, compID, _
   MSI_INSTALLMODE.INSTALLMODE_DEFAULT, buffer1, pSize)
  Return buffer1.ToString
End Function

Um diesen Code besser zu kapseln, wird dem Projekt eine neue Klasse namens WIHelper hinzugefügt, die Windows Installer-API-Methodendeklarationen und Wrappermethoden beherbergt. Das Aufrufen dieses Codes war eine einfache Angelegenheit, um dem Load-Ereignishandler des Standard Formulars einige Zeilen hinzuzufügen.

Private CONST PRODUCTID As String = "PRODUCT_GUID_HERE"
Private CONST MAIN_FEATUREID As String = "DefaultFeatureKey"
Private CONST COMPID_1 As String = "COMP1_GUID_HERE"
Private CONST COMPID_2 As String = "COMP2_GUID_HERE"
Private Sub MainForm_Load() Handles MyBase.Load
  If WIHelper.IsProductInstalled(PRODUCTID) Then
    WIHelper.ProvideComponent(PRODUCTID, MAIN_FEATUREID, COMPID_1)
    WIHelper.ProvideComponent(PRODUCTID, MAIN_FEATUREID, COMPID_2)
  End If
End Sub
 

Im obigen Beispielcode testen wir zunächst, ob unsere Anwendung tatsächlich über das Installationspaket installiert wurde oder nicht. Dies ist ein wichtiges Konzept, da wir sicherstellen möchten, dass unsere Anwendung auch beim Debuggen in der Entwicklungsumgebung weiterhin ordnungsgemäß funktioniert. Um dies zu erreichen, rufen wir eine -Methode in unserer Hilfsklasse namens IsProductInstalled auf. Diese Methode wiederum ruft einfach MsiQueryProductState auf, um festzustellen, ob das Produkt auf dem System installiert wurde. Wenn der Aufruf von IsProductInstalled zeigt, dass unser Produkt installiert wurde, führen wir eine Reihe von Aufrufen der ProvideComponent-Methode in unserer Hilfsklasse durch. Diese Methode ist wiederum ein einfacher Wrapper um die MsiProvideComponent-API , der den vollständigen Pfad zur angegebenen Komponente zurückgibt und sicherstellt, dass die Komponente ordnungsgemäß installiert und einsatzbereit ist. Abhängig von den Anforderungen Ihrer spezifischen Produkte können Sie die ProvideComponent-Methode beliebig oft aufrufen, um sicherzustellen, dass Ihre Anwendung für den Benutzer vollständig verfügbar ist.

Herausforderung Nr. 2: Bei Bedarf installieren

Die Vertriebsleiter unserer hypothetischen Unternehmen haben viel Feedback von Kunden erhalten, dass sie eine Reihe von Standardvorlagen mit SimplePad erhalten möchten. Während einige Kunden einen starken Wunsch nach diesem Feature geäußert haben, haben andere Bedenken geäußert, dass überflüssige Daten installiert werden, die die meisten ihrer Benutzer möglicherweise nicht benötigen.

Nachdem wir die Techniker darüber gesprochen haben, wie mit dieser neuen Anforderung umgegangen werden soll, springt unser unerschrockener Installationstechniker ein und weist darauf hin, dass Windows Installer dies mit nur einer kleinen Menge zusätzlicher Codierung problemlos bewältigen kann.

Nach einer kurzen Planung entscheidet das Team, dass ein neues Menüelement Vorlagen im Menü Datei der Anwendung implementiert wird. Wenn das Vorlagenfeature lokal auf dem System des Benutzers installiert ist, wird dem Benutzer ein Flyoutmenü mit jeder der verfügbaren Vorlagen und eine Option zum Deinstallieren des Vorlagenfeatures angezeigt. Wenn das Vorlagenfeature nicht installiert wurde, enthält das Flyoutmenü "Vorlagen" einen einzelnen Eintrag, sodass der Benutzer die zusätzlichen Vorlagen installieren kann.

Private Sub mnuFile_Popup(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles mnuFile.Popup
  Dim newItem As MenuItem
  With mnuTemplates.MenuItems
    .Clear()
    If WIHelper.IsFeatureInstalled(PRODUCTID, TEMPLATES_FEATUREID) Then
      Dim dirInfo As New DirectoryInfo(Application.ExecutablePath)
      For Each dirFile As FileInfo In dirInfo.Parent.GetFiles("*.tpl")
        Dim mi As New MenuItem(Path.GetFileNameWithoutExtension(dirFile.Name))
        AddHandler mi.Click, AddressOf OpenTemplate
        .Add(mi)
      Next
      .Add("-")
      newItem = New MenuItem("Uninstall Templates")
      AddHandler newItem.Click, AddressOf UninstallTemplates
      .Add(newItem)
    Else
      newItem = New MenuItem("Install Templates")
      AddHandler newItem.Click, AddressOf InstallTemplates
      .Add(newItem)
    End If
  End With
End Sub

Wie Sie sehen können, überprüfen wir zunächst, ob das Vorlagenfeature installiert ist. Wenn dies der Grund ist, werden die Dateien in unserem Anwendungsordner mit der Erweiterung "tpl" aufgelistet und dem Menü den Namen jeder Vorlage hinzugefügt. Wenn dies nicht der Grund ist, fügen wir einfach eine Option für den Benutzer hinzu, um die Vorlagen zu installieren. Bevor wir uns das ansehen, sehen wir uns zunächst an, wie wir bestimmen, ob das Vorlagenfeature installiert ist.

<DllImport("msi.dll")> _
Private Shared Function MsiQueryFeatureState(ByVal szProduct As String, 
ByVal szFeature As String) As MSI_INSTALLSTATE
End Function    
Public Shared Function IsFeatureInstalled(ByVal pid As String, ByVal fid As String) As Boolean
  Return MsiQueryFeatureState(pid, fid) = MSI_INSTALLSTATE.INSTALLSTATE_LOCAL
End Function

In dieser einfachen Funktion rufen wir einfach die MsiQueryFeatureState-Funktion von Windows Installer auf und übergeben den ProductCode unserer Anwendung und den Namen des Features, nach dem wir gefragt werden. Wenn Windows Installer INSTALLSTATE_LOCAL zurückgibt, geben wir true zurück, da dies bedeutet, dass das Feature lokal installiert ist.

Das Installieren und Deinstallieren unseres Vorlagenfeatures ist genauso einfach.

<DllImport("msi.dll")> _
Private Shared Function MsiConfigureFeature(ByVal szProduct As String, ByVal szFeature As String, ByVal eInstallState As MSI_INSTALLSTATE) As Integer
End Function

Public Shared Function InstallFeature(ByVal pid As String, ByVal fid As String)
  As Boolean
  Return MsiConfigureFeature(pid, fid, MSI_INSTALLSTATE.INSTALLSTATE_LOCAL) = ERROR_SUCCESS
End Function

Public Shared Function UninstallFeature(ByVal pid As String, ByVal fid As String) As Boolean
  Return MsiConfigureFeature(pid, fid, 
MSI_INSTALLSTATE.INSTALLSTATE_ABSENT) = ERROR_SUCCESS
End Function

Wenn der Benutzer auf das Menüelement "Installationsvorlagen" klickt, wird msiConfigureFeature mit dem ProductCode, dem Namen des features, das wir konfigurieren möchten, und einem Enumerationswert aufgerufen, der angibt, dass wir das Feature lokal installieren möchten. Während der Installation des Vorlagenfeatures wird dem Benutzer kurz ein Windows Installer-Statusdialogfeld angezeigt. Wenn das Dialogfeld nicht mehr angezeigt wird, werden die Vorlagen installiert und können verwendet werden. Wenn der Benutzer zurück zum Menü Datei wechselt, wird das Vorlagenuntermenü mit den Namen der Vorlagen aufgefüllt, wie oben beschrieben.

Schlussbemerkung

Die Nutzung der "kostenlosen" Features und der api, die von Windows Installer verfügbar gemacht wird, bietet uns einige coole Funktionen, die einen großen Beitrag zur Senkung der Supportkosten, zur Erhöhung der Anwendungsstabilität und zur Verbesserung der Benutzererfahrung beitragen. Die hier gezeigten Beispiele sind etwas trivial, werden aber hoffentlich einen guten Ausgangspunkt für die Implementierung Ihrer eigenen einzigartigen Lösungen bilden. Wir haben uns einige der verfügbaren APIs angesehen, aber wir haben sie sicherlich nicht alle behandelt. Nehmen Sie sich etwas Zeit, um alle Features der Windows Installer-API zu erkunden, und ich weiß, dass Sie angenehm überrascht sein werden, wie einfach Sie diese relativ unerschlossenen Features von Windows Installer nutzen können.

 

Über den Autor

Michael Sanford ist President und Chief Software Architect für 701 Software (http://www.701software.com). Vor der Gründung von 701 war Michael Präsident und CEO der ActiveInstall Corporation, die von Zero G Software übernommen wurde. ActiveInstall wurde für seine Windows Installer-Erstellungslösungen bekannt. Michael ist Microsoft Certified Solution Developer (MCSD), Microsoft Certified Systems Engineer (MCSE) und Windows Installer MVP. Sie können Michaels Blog unter http://msmvps.com/michaellesen.