Zu löschende Dateien mit VB6 in den Windows-Papierkorb verschieben
Veröffentlicht: 30. Mai 2005
Von Mathias Schiffer
Die Microsoft Newsgroups sind eine Quelle schier unerschöpflichen Wissens, das nahezu auf Knopfdruck abrufbar ist: Hunderte deutschsprachige Entwickler vom Einsteiger bis zum Profi treffen sich hier täglich virtuell, um Fragen zu stellen oder zu beantworten. Auch themennahe Probleme, Ansichten und Konzepte werden miteinander diskutiert. Sie kennen die Microsoft Newsgroups noch nicht? Detaillierte Information für Ihre Teilnahme finden Sie auf der Homepage der Microsoft Support Newsgroups.
Diese Kolumne greift regelmäßig ein besonders interessantes oder häufig nachgefragtes Thema aus einer der Entwickler-Newsgroups auf und arbeitet es aus.
Aus der Visual Basic Newsgroup microsoft.public.de.vb:
Wenn ich in Visual Basic 6.0 Dateien lösche, benutze ich die dafür vorgesehene Anweisung „Kill“. Damit sind die Dateien dann aber unwiederbringlich gelöscht, der Windows-Papierkorb wird schlicht ignoriert. Wie also kann ich Dateien in den Windows-Papierkorb verschieben (sofern er aktiviert ist)?
Visual Basic 6.0 kann mit reinen Bordmitteln keine Dateien in den Windows-Papierkorb verschieben. Dabei gab es den Papierkorb auch für Microsoft Windows schon mit der Vorstellung von Visual Basic 4.0, das parallel als 16-bit und erste 32-bit VB-Version zur Verfügung stand. Doch keine der beiden Versionen berücksichtigte dieses zentrale Detail, und dabei blieb es über viele Jahre hinweg auch bis zur letzten Version von Visual Basic (ohne „.NET“).
Da Visual Basic jedoch mit der offenen Möglichkeit ausgestattet ist, Funktionen des Win32-API in allen erdenklichen Lagen und Varianten zu nutzen, stellt diese Einschränkung kein wirkliches Problem dar. Denn natürlich können Sie Dateien unter Verwendung der Funktionen des Win32-API in den Papierkorb verschieben, statt sie unwiederbringlich löschen zu müssen.
Den Schlüssel zu allen möglichen Datei- und Verzeichnisoperationen stellt die Funktion SHFileOperation dar. Mit ihr können Sie Dateien und Verzeichnisse samt Windows-eigener Dialoganzeige verschieben, kopieren sowie löschen und damit in den Papierkorb verschieben (sofern dieser aktiviert ist – was nur sehr selten nicht der Fall ist, meist in entsprechend geheimhaltungsbedürftigen Umgebungen).
Wie immer beim Einsatz des Win32-API benötigen wir zunächst einige deklaratorische Zeilen, in denen Funktionen, Konstante und Typen vorab definiert werden. Der folgende Codeblock enthält viel mehr Konstantendefinitionen als die hier notwendigen – fühlen Sie sich eingeladen, den definitorisch eingeschränkten Umfang dieses Artikels mit dieser kleinen Hilfe auf eigene Initiative zu durchbrechen.
' Benötigte Typen Private Type SHFILEOPSTRUCT hWnd As Long wFunc As Long pFrom As String pTo As String fFlags As Integer fAborted As Boolean hNameMaps As Long sProgress As String End Type ' Benötigte und weitere, für den Leser ggf. nützliche Konstante Private Const FO_MOVE As Long = &H1& ' Dateien verschieben Private Const FO_COPY As Long = &H2& ' Dateien kopieren Private Const FO_DELETE As Long = &H3& ' Dateien in den Papierkorb verschieben Private Const FO_RENAME As Long = &H4& ' Dateien umbenennen Private Const FOF_MULTIDESTFILES As Long = &H1& ' Mehrere Zieldateien (für kopieren, verschieben, umbenennen) Private Const FOF_CONFIRMMOUSE As Long = &H2& ' Bestätigung Private Const FOF_SILENT As Long = &H4& ' Keine Darstellung des Löschvorgangs Private Const FOF_RENAMEONCOLLISION As Long = &H8& ' Falls Zielname vergeben, automatscih umbenennen Private Const FOF_NOCONFIRMATION As Long = &H10& ' Keine Bestätigungen anfordern Private Const FOF_ALLOWUNDO As Long = &H40& ' UNDO erlauben Private Const FOF_FILESONLY As Long = &H80& ' WildCards nur auf Dateien beziehen Private Const FOF_SIMPLEPROGRESS As Long = &H100& ' Einfache Fortschrittsanzeige Private Const FOF_NOCONFIRMMKDIR As Long = &H200& ' Anlegen von Verzeichnissen ohne Anfrage Private Const FOF_NOERRORUI As Long = &H400& ' Kein UserInterface bei Fehlern Private Const FOF_NOCOPYSECURITYATTRIBS As Long = &H800& ' Sicherheitsattribute nicht mit kopieren ' API-Funktionsprototypisierungen Private Declare Function SHFileOperation _ Lib "shell32.dll" ( _ ByRef FileOpStruct As SHFILEOPSTRUCT _ ) As Long
Für unsere Zwecke wichtig sind vorrangig drei Aspekte: Einerseits ist da die Funktion SHFileOperation, die am Ende den Job für uns erledigen soll. Geschenkt: Sie hat einen Parameter vom Typ SHFILEOPSTRUCT. Der jedoch hat weitere Betrachtung verdient. Und dabei spielt auch schon der dritte Aspekt mit: die definierten Konstanten, denen die Funktionalität steuernde Wirkung zukommt.
Betrachten wir einige der Parameter der Struktur SHFILEOPSTRUCT:
Trivial ist der Parameter hWnd – hier kann ein Fensterhandle eines Fensters angegeben werden, das als Elternfenster für Interaktionselemente dienen soll (i.A. schlicht „Form1.hWnd“). Weiter geht es mit wFunc: Hier wird angegeben, welche Art der Dateibehandlung (Kopieren, Verschieben, Löschen oder Umbenennen) gewünscht wird. Wir entscheiden uns für das Löschen (in den Papierkorb, versteht sich) und verwenden dafür die benannte Konstante FO_DELETE.
Der interessanteste Parameter für unsere Zwecke ist der Parameter pFrom: Hier wird definiert, woher („From“) die Dateien kommen, die in den Papierkorb verschoben werden sollen. Auf gut Deutsch: Hier sind die Pfade zu den zu löschenden Dateien anzugeben. Da es sich um nur einen einzigen Stringparameter handelt, muss es ein Trennzeichen geben, um mehrere Angaben voneinander trennen zu können (Sie könnten auch nur einen Dateipfad angeben und jeweils die Löschoperation durchführen – das würde in etwa dem Vorgehen entsprechen, 20 Dateien in einem Verzeichnis Stück für Stück zu löschen, statt zunächst die 20 Dateien zu markieren und erst dann den Löschbefehl zu erteilen). Gibt es auch: Das Trennzeichen ist das „Nullzeichen“ (Chr$(0)), das in Visual Basic statt über die jeweils auszuführende Chr-Funktion auch einfacher über die Stringkonstante vbNullChar abgerufen werden kann. So reihen Sie also einfach mehrere Dateipfade, die durch vbNullChar-Zeichen verbunden sind, in die Reihe der Löschkandidaten ein. Die Liste muss für die Funktion SHFileOperation beim Aufruf durch ein doppeltes vbNullChar als abgeschlossen erkennbar sein. Tief unter der Haube terminiert Visual Basic dem Win32-API gegenüber allerdings ohnehin jeden String mit einem zusätzlichen vbNullChar, so dass Sie auch einfach nach jedem Pfad ein vbNullChar anhängen könnten und damit „aus dem Schneider“ wären – letztlich eine Stilfrage. Ich selber hänge solche eigentlich nicht notwendigen Terminierungen gerne ausdrücklich mit an Strings an, um die Anforderungen der eingesetzten API-Funktion von mir aus zu erfüllen und damit transparenten Code zu schreiben, dessen Funktionsfähigkeit nicht von Interna abhängt, die nicht unter meiner Kontrolle stehen. Ich nenne das „Explizites Programmieren“.
Letztlich noch interessant ist der Parameter fFlags der Struktur: Hier kommen die oben aufgeführten und dort erklärten FOF_-Konstanten zur Anwendung. Um etwa das Rückgängigmachen einer Aktion zu erlauben, verwenden Sie die Konstante FOF_ALLOWUNDO. Mehrere Flags für den Parameter verknüpfen Sie mithilfe des Or-Operators.
So befüllt fehlt der SHFILEOPSTRUCT-Struktur eigentlich nur noch eines: der Aufruf der Funktion SHFileOperation, für die sie alle relevanten Ausführungsinformationen enthält.
Der folgende beispielhafte Sourcecode dient dem Löschen von Dateien in den Papierkorb. Übergeben werden können als ParamArray einzelne Dateipfade, aber auch String-Arrays, die Pfade für zu löschende Dateien enthalten. Selbst ein Mix daraus ist möglich:
Public Sub BinAddFiles(ParamArray Filename() As Variant) ' Dateien in den Papierkorb verschieben. Übergeben werden die Dateipfade zu den ' zu löschenden Dateien als Strings, z.B.: ' BinAddFiles "d:\text.txt", "d:\bild.bmp", "d:\musik.wav" ' Es können auch Arrays mit Dateipfaden übergeben werden. ' Ein Mix der beiden Möglichkeiten ist ebenfalls erlaubt. Dim SHOP As SHFILEOPSTRUCT ' API-Struktur Dim Files As String ' vbNullChar-separierte Dateipfade Dim i As Long Dim k As Long ' ParamArray in einen vbNullChar-separierten String wandeln For i = LBound(Filename) To UBound(Filename) ' Stellt der aktuelle Parameter ein Array dar? If IsArray(Filename(i)) Then ' Arraymitglieder jeweils einzeln hinzufügen For k = LBound(Filename(i)) To UBound(Filename(i)) Files = Files & Filename(i)(k) & vbNullChar Next k Else ' Kein Array, sondern ein einzelner Pfad Files = Files & Filename(i) & vbNullChar End If Next i Files = Files & vbNullChar ' abschließendes vbNullChar anfügen With SHOP ' Parameter festlegen .wFunc = FO_DELETE ' in den Papierkorb löschen .pFrom = Files ' Quelldateien übergeben .fFlags = FOF_ALLOWUNDO ' Rückgängigmachung erlauben End With ' Die Löschoperation ausführen SHFileOperation SHOP End Sub
Mathias Schiffer widmet sich als freier Softwareentwickler und Technologievermittler größeren Projekten ebenso wie arbeitserleichternden Alltagslösungen. Seit Jahren gibt er sein Wissen in unzähligen Publikationen auch an andere Entwickler und Entscheider weiter. Sie erreichen ihn per E-Mail an die Adresse Schiffer@mvps.org.