AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Treiberinstallation
Tutorial durchsuchen
Ansicht
Themen-Optionen

Treiberinstallation

Ein Tutorial von Nuclear-Ping · begonnen am 14. Sep 2007
Antwort Antwort
Nuclear-Ping
Hallo,

Ziel dieses kleinen Tutorials soll es sein, dem Anwender eine Möglichkeit zu zeigen, wie er eine automatische Installation von Treibern, die über eine .inf-Datei verfügen, realisiert.

Hintergrund ist, dass ich im Rahmen eines aktuellen Projekts mit diesem Problem konfrontiert wurde und nach längerem Suchen im Netz nur spärlich fündig wurde. Entweder haben die Lösungen nicht funktioniert (z.B. per ShellExecute + rundll32) oder es lagen keine Beispiele vor, wie man mit mit diesen konkreten Funktionen und den Parametern, die sie erwarten, umgeht (z.B. die SetupAPI von Jedi) und wo das rumexperimentieren kein Resultat brachte.

Dann bin ich auf eine Lösung gestoßen, die wirklich sehr simpel ist - wie die meisten Dinge, wenn man erstmal weiß, wie's geht. Und diese möchte ich euch nicht vorenthalten, damit der nächste Sucher sich die Zeit und Nerven sparen kann, die ich mit Suchen und Puzzlen verbracht hab.

Das was ich gefunden habe und für mich gut funktioniert hat war die "Driver Install Frameworks API" oder kurz "DIFxAPI" von Microsoft.

Hierbei möchte ich auch nur auf die beiden Funktionen zur Installation und Deinstallation von Treibern eingehen.

Was benötigt ihr?
- Das DIFxAPI Kit Version 2.01: http://download.microsoft.com/downlo...ationTools.msi
- Einen Win32 C Compiler. Ich habe den Borland C++ 5.5 Compiler genommen, den es kostenlos auf der Borland Seite zum Download gibt (Warum C? Dazu gleich mehr)
- Ein paar C-Grundlagenkenntnisse

Warum C?
Anfangs hab ich die DIFxAPI.h nach Delphi übersetzt. Das lief auch, allerdings erhielt ich nach ein paar Läufen in der IDE immer wieder sporadisch eine Zugriffsverletzung (nicht die rote, sondern die mit dem "i"-Symbol), die ich nicht wegbekommen hab.
Runterladen kann man sich den Header unter http://www.108bits.de/private/files/sources/difxapi.zip - Wer motiviert ist, kann sich das Ganze ja mal angucken. Vielleicht sieht er einen Fehler, der das auslöst.
Der Delphi-Code dafür sah so aus:
Delphi-Quellcode:
const
  lqrInfFile: String = '.\drivers\NT_2K_XP\lqr\lqr_usb.inf';
var
  NR: Boolean;
  Res: DWORD;
// Info: PCINSTALLERINFO_A;
begin
{  GetMem (Info, 128);
  Info.pApplicationId := 'AppGUID';
  Info.pDisplayName := 'ApplicationDisplayName';
  Info.pProductName := 'YourProductName';
  Info.pMfgName := 'ManufacturerName';}

  Res := DriverPackageInstall (PChar (lqrInfFile1), DRIVER_PACKAGE_FORCE or DRIVER_PACKAGE_LEGACY_MODE, nil, NR);
  if (Res <> 0) then
    // Fehler

  {...}
// FreeMem (Info);
end;
Also hab ich kurzerhand die paar Funktionsaufrufe in C umgesetzt - und da lief es auch, bis heute ohne Zugriffsverletzungen. ^^
Wer früher etwas C gemacht oder sich mit PHP / Java / JavaScript angefreundet hat, für den sollte das auch kein Problem darstellen.

Der Start
Damit euer Programm die Funktionen der DIFxAPI kennt, müsst ihr noch die "difxapi.h" in den Suchpfad oder in den Pfad eures Sources legen und per #include einbinden. Die Datei findet ihr unter c:\Programme\Driver Installation Tools 2.01\DIFxAPI\.

Wenn ihr Unicode verwenden wollt, dann noch UNICODE definieren.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "difxapi.h"

// #define UNICODE
Die Funktionen
- DriverPackageInstall
Code:
DWORD
  DriverPackageInstall(
    IN LPCTSTR DriverPackageInfPath,
    IN DWORD Flags,
    IN PCINSTALLERINFO pInstallerInfo OPTIONAL,
    OUT BOOL *pNeedReboot
    );
Diese Funktion installiert einen Treiber über eine Inf-Datei und gibt im Erfolgsfall ERROR_SUCCESS (0) zurück.

Die Parameter sind wie folgt:

- IN LPCTSTR DriverPackageInfPath
Ein String, der den Pfad zur und den Namen der Inf-Datei enthält

- IN DWORD Flags
Ein DWORD Wert, der verschiedene Optionen zur Steuerung der Installation enthalten kann

- IN PCINSTALLERINFO pInstallerInfo OPTIONAL
Ein Parameter, der ein Record ist und Informationen über den Treiber wie GUID, Anwendung, Hersteller, Beschreibung usw. enthält, die dem Treiber bei der Installation zugeordnet werden. Dieser Parameter ist optional, d.h. er muss nicht mit angegeben werden sondern kann NULL sein.

- OUT BOOL *pNeedReboot
Ein Boolean-Wert, der nach der Funktion TRUE ist, falls ein Neustart benötigt wird, um die Treiberinstallation abzuschließen.

Flags steuert hier das Verhalten der Installation etwas. Die Erklärung aller Flags findet ihr in der Header-Datei. Das was ich in meinem Fall verwendet habe war DRIVER_PACKAGE_LEGACY_MODE, weil nicht alle Treiber eine digitale Signierung haben (sonst würde die Installation abgebrochen werden) und DRIVER_PACKAGE_FORCE, um sicher zu stellen, dass immer der Treiber der akt. Softwareversion verwendet wird.

pInstallerInfo kann mit Informationen über den Treiber, dessen Hersteller und der Anwendung zu der er gehört gefüttert werden. Diese Informationen werden dem Treiber zugeordnet, ist aber für den "Betrieb" nicht wirklich wichtig.

Das ganze als Code schaut zum Beispiel so aus:
Code:
char *InfFile = ".\\drivers\\NT_2K_XP\\lqr\\lqr_usb.inf";
BOOL NeedRestart;
DWORD Result;

Result = DriverPackageInstall (InfFile,
  DRIVER_PACKAGE_FORCE | DRIVER_PACKAGE_LEGACY_MODE, NULL, &NeedRestart);
if (!Result) {
  printf (" ** Fehler %d bei der Treiberinstallation.\n", Result);
  return -1;
}
- DriverPackageUninstall
Code:
DWORD
  DriverPackageUninstall(
    IN LPCTSTR DriverPackageInfPath,
    IN DWORD Flags,
    IN PCINSTALLERINFO pInstallerInfo, OPTIONAL
    OUT BOOL *pNeedReboot
    );
Diese Funktion ist das genaue Gegenstück zu DriverPackageInstall und gibt im Erfolgsfall ebenfalls ERROR_SUCCESS (0) zurück.

Die Funktion erwartet die gleichen Parameter wie ihr Gegenstück. Einzig unterscheiden sich hier die Flags. Um sicher zu gehen, sollte man hier einfach 0 übergeben, da es Anwendungen geben kann, die auf diesen Treiber noch mit zugreifen. Sollte es sich hier jedoch wirklich um einen unikaten Treiber handeln, der speziell für eine Anwendung entwickelt wurde, empfiehlt sich hier vielleicht DRIVER_PACKAGE_FORCE | DRIVER_PACKAGE_DELETE_FILES.

Der Code dazu:
Code:
char *InfFile = ".\\drivers\\NT_2K_XP\\lqr\\lqr_usb.inf";
BOOL NeedRestart;
DWORD Result;

Result = DriverPackageUninstall (InfFile,
  DRIVER_PACKAGE_FORCE | DRIVER_PACKAGE_DELETE_FILES, NULL, &NeedRestart);
if (!Result) {
  printf (" ** Fehler %d beim Entfernen des Treibers.\n", Result);
  return -1;
}
Mit der Version 2.01 der DIFxAPI funktioniert das Ganze auch unter Vista (getestet).

Wem das noch nicht reicht, kann sich hier noch anschauen, wie man ein Logging-Callback (ebenfalls ziemlich einfach) implementiert, welches aufschlussreiche Informationen über den Installationsprozess (und dessen evtl. Fehler) liefert. Allerdings muss man hier den Aufruf von SetDifxLogCallback durch DIFXAPISetLogCallback ersetzen, die Parameter bleiben gleich.

Linken
Damit der Code erfolgreich beim Compiler durchläuft, müsst ihr noch die difxapi.lib für den Linker mit einbinden. Bei mir hat der Borland-Compiler aber wegen dem Lib-Format gemeckert, was sich aber einfach mit dem Tool "coff2omf.exe", welches sich im Bin-Verzeichnis des Compilers befindet, beheben lässt.
Bei mir sieht der Build-Befehl so aus:
Code:
set path=%path%;C:\Programme\Borland\BCC55\Bin\
bcc32.exe -IC:\Programme\Borland\BCC55\Include\ -LC:\Programme\Borland\BCC55\Lib\ difxapi.lib main.c >make.log
Ebenfalls muss die difxapi.dll im Verzeichnis eurer Anwendung liegen, die die Treiber installiert.

Diese Dateien findet ihr nach der Installation des Packages unter (z.B.) c:\Programme\Driver Installation Tools 2.01\DIFxAPI\x86\

Ich hoffe, ich konnte mit diesem Tutorial einen kleinen Beitrag leisten. Falls etwas falsch oder unvollständig sein sollte, korrigiert oder ergänzt mich bitte. Ich bin in Sachen C und Windows-API nicht sonderlich erfahren - für das Nötigste reichts.
Auch für Fragen bin ich immer zu haben.

Grüße,

Mario
 
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:20 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz