Virtuelles (partielles) Laufwerk Erstellen/Löschen

    • Offizieller Beitrag

    Hi,
    hiermit lassen sich Ordner-Pfade zu Virtuellen Laufwerken verknüpfen. Die so erstellten Laufwerke werden nicht in der Registry verewigt und sind nur für die Dauer der Sitzung gültig. Nach einem Neustart ist wieder alles 'normal'.

    Edit 27.12.08:
    Hab das noch etwas erweitert:
    - Standardmäßig wird jetzt der erste freie Laufwerksbuchstabe verwendet
    - der Verknüpfungspfad ist jetzt vorbelegt mit '@MyDocumentsDir' ( aber nur, weil ich die Parameterreihenfolge nicht ändern wollte :D )
    - bei Erfolg wird der Buchstabe des erstellten od. gelöschten Laufwerks zurückgegeben.

    Edit 28.12.08:
    Die Prüfung auf Existenz der Lw mit FileExists() funktioniert nicht bei leeren CD/DVD-Lw. Dadurch konnte bei Verknüpfung ohne Lw-Angabe dem CD-Lw der Buchstabe 'geklaut' werden :D. Habe den Abfragemodus geändert und auch die empfohlenen Änderungen von progandy und Oscar eingebunden - Dank an Euch.

    Edit 28.12.08 #2
    Dank eurer Hinweise wird die Funktion immer professioneller ;)
    Habe jetzt eingefügt, dass zum Löschen nicht mehr der Pfad angegeben werden muss. Den sucht sich die Funktion jetzt selbst raus.
    Zum Löschen reicht nun: _PartialDrive([Lw:], -1, 1)

    Edit 29.12.08
    Für all jene, die nicht nur vergessen haben, mit welchem Pfad verknüpft wurde, sondern auch welches Lw ertsellt wurde, habe ich noch eine Zusatzfunktion erstellt, die (sofern vorhanden) alle partiellen Laufwerke mit Lw-Buchstaben und verknüpftem Pfad als 2D-Array [Lw][Pfad] ausgibt. ;)
    Das ließe sich natürlich auch noch mit in die erste Funktion integrieren (z.B. mit Lw-Parameter '0' als erste Abfrage in der Func).

    _PartialDrive()
    [autoit]

    ; 'c:\test' als Laufwerk 'Q:'erstellen
    If _PartialDrive('Q:', 'c:\test') Then
    MsgBox(0, '', 'Partielles Laufwerk erstellt.')
    Else
    MsgBox(0, '', 'Erstellung Partielles Laufwerk fehlgeschlagen.')
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ; Laufwerk 'Q:' wieder löschen
    If _PartialDrive('Q:', -1, 1) Then
    MsgBox(0, '', 'Partielles Laufwerk gelöscht.')
    Else
    MsgBox(0, '', 'Löschen Partielles Laufwerk fehlgeschlagen.')
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ; Verknüpfung mit 'Eigene Dateien' auf erstes freies Laufwerk
    Local $newDrive = _PartialDrive()
    If Not @error Then
    MsgBox(0, '', 'Neues Laufwerk: ' & $newDrive)
    Else
    MsgBox(0, '', 'Fehler')
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ; Verknüpfung mit 'Eigene Dateien' wieder löschen
    _PartialDrive($newDrive, -1, 1)
    If Not @error Then
    MsgBox(0, '', 'Laufwerk gelöscht: ' & $newDrive)
    Else
    MsgBox(0, '', 'Fehler')
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;==================================================================================================
    ; Function Name: _PartialDrive($sDeviceName=-1, $sTargetPath=-1, $iDelete=0)
    ; Description:: Erstellt od. löscht ein Virtuelles Laufwerk. Das Laufwerk wird
    ; beim Herunterfahren des PC automatisch gelöscht.
    ; Parameter(s): $sDeviceName Buchstabe des zu erstellenden/löschenden Laufwerks
    ; -1 erster freier Lw-Buchstabe (Standard)
    ; $sTargetPath Verknüpfungspfad, -1= Erstellen: @MyDocumentsDir (Standard)
    ; Löschen: der mit dem Laufwerk verknüpfte Pfad wird automatisch zugeordnet
    ; optional: $iDelete 0=Erstellen (Standard); 1=Löschen des Laufwerks
    ; Return Value(s): Erfolg Lw-Buchstabe des erstellten/gelöschten Laufwerks
    ; Fehler 0 @error=1 übergebener Lw-Buchstabe existiert bereits (nur Erstellen)
    ; @error=2 kein freier Lw-Buchstabe vorhanden (nur Erstellen)
    ; @error=3 kein gültiger Verknüpfungspfad
    ; @error=4 Aktion fehlgeschlagen
    ; @error=5 kein gültiges Lw zum Löschen angegeben
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;==================================================================================================
    Func _PartialDrive($sDeviceName=-1, $sTargetPath=-1, $iDelete=0)
    If $sDeviceName = -1 And $iDelete = 0 Then
    Local $aDrives = DriveGetDrive("ALL")
    Local $oDrives = ObjCreate("System.Collections.ArrayList")
    For $i = 1 To UBound($aDrives) -1
    $oDrives.Add(Asc(StringLeft($aDrives[$i],1)))
    Next
    Local $j = 100
    While $oDrives.Contains($j)
    $j += 1
    If $j > 122 Then Return SetError(2,0,0)
    WEnd
    $sDeviceName = Chr($j) & ':'
    ElseIf ($sDeviceName = -1 Or Not FileExists($sDeviceName)) And $iDelete = 1 Then
    Return SetError(5,0,0)
    ElseIf $sTargetPath = -1 And $iDelete = 1 Then
    Local $ret = DllCall("kernel32.dll", "long", "QueryDosDeviceA", "str", $sDeviceName, "str", "", "long", 260)
    If $ret[0] = 0 Then
    Return SetError(4,0,0)
    Else
    $sTargetPath = StringRegExpReplace($ret[2], '(\W*)([a-zA-Z].*)', '$2')
    EndIf
    EndIf
    $sDeviceName = StringRegExpReplace(StringLower($sDeviceName), '(.*)([a-z]{1}:)(.*)', '$2')
    If $iDelete = 0 And FileExists($sDeviceName) Then Return SetError(1,0,0)
    If $sTargetPath = -1 Then $sTargetPath = @MyDocumentsDir
    If Not FileExists($sTargetPath) Then Return SetError(3,0,0)
    Local $iFlag = 0x0
    If $iDelete <> 0 Then $iFlag = 0x2
    Local $ret = DllCall('kernel32.dll', 'long', 'DefineDosDeviceA', _
    'long', $iFlag, 'str', $sDeviceName, 'str', $sTargetPath)
    If $ret[0] = 0 Then
    Return SetError(4,0,0)
    Else
    Return $sDeviceName
    EndIf
    EndFunc ;==>PartialDrive

    [/autoit]
    _PartialDriveGet()
    [autoit]

    #include<array.au3>
    $a = _PartialDriveGet()
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name: _PartialDriveGet()
    ; Description:: Ermittelt partiell erstellte Laufwerke
    ; Return Value(s): 2D-Array mit (sofern vorhanden) Lw-Buchstabe und Verknüpfungspfad
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;===============================================================================
    Func _PartialDriveGet()
    Local $aFixed = DriveGetDrive('FIXED')
    Local $aOut[1][2] = [['Lw','Pfad']]
    For $i = 1 To UBound($aFixed) -1
    Local $ret = DllCall("kernel32.dll", "long", "QueryDosDeviceA", "str", $aFixed[$i], "str", "", "long", 260)
    Local $path = StringRegExpReplace($ret[2], '(\W*)([a-zA-Z].*)', '$2')
    If StringRegExp($path, '[a-zA-Z]:.*') Then
    ReDim $aOut[UBound($aOut)+1][2]
    $aOut[UBound($aOut)-1][0] = $aFixed[$i]
    $aOut[UBound($aOut)-1][1] = $path
    EndIf
    Next
    Return $aOut
    EndFunc ;==>_PartialDriveGet

    [/autoit]
    • Offizieller Beitrag

    Sowas ist ganz nützlich, wenn irgendein Programm 'darauf besteht' Daten von Laufwerk A: einzulesen. Solche Scherze gibt es nach wie vor, nur haben die meisten Laptops und PC inzwischen kein Disketten-Lw mehr ;)
    Das kann man auch dauerhaft mit dem DOS-Befehl SUBST [Lw:] [Pfad] erstellen. Allerdings ist das Löschen dieser Verknüpfung laut Syntaxbeschreibung mit SUBST [Lw:] /D möglich - in der Praxis hat mir aber bisher jeder PC gesagt, dass er den Schalter /D nicht kennt. :rofl:

  • Also, bei mir fuktioniert Subst einwandfrei ;)

    Code
    subst J: D:\Vista
    ...
    subst J: /D


    (XP sp3, hat auch bei sp2 funktioiert, davor weiß ichs net)
    Subst funktioniert aber nicht dauerhaft, nur bis zum Neustart ;)
    Und die UDF hat nen Bug: Wenn DeviceName = -1 und Debug=True, sollte gleich ein Fehler rausgehen, nicht dei ganze Funktion durchlaufen ;)

    • Offizieller Beitrag

    BugFix : Den Anfang der Funktion kann man etwas kürzen:

    Spoiler anzeigen
    [autoit]


    Func _PartialDrive($sDeviceName = -1, $sTargetPath = -1, $iDelete = 0)
    If $sDeviceName = -1 And $iDelete = 0 Then
    $i = 99
    While FileExists(Chr($i) & ':')
    $i += 1
    If $i > 122 Then Return SetError(2, 0, 0)
    WEnd
    $sDeviceName = Chr($i) & ':'
    EndIf
    $sDeviceName = StringRegExpReplace(StringLower($sDeviceName), '(.*)([a-z]{1}:)(.*)', '$2')
    If $iDelete = 0 And FileExists($sDeviceName) Then Return SetError(1, 0, 0)
    If $sTargetPath = -1 Then $sTargetPath = @MyDocumentsDir
    If Not FileExists($sTargetPath) Then Return SetError(3, 0, 0)
    Local $iFlag = 0x0
    If $iDelete <> 0 Then $iFlag = 0x2
    Local $ret = DllCall('kernel32.dll', 'long', 'DefineDosDeviceA', _
    'long', $iFlag, 'str', $sDeviceName, 'str', $sTargetPath)
    If $ret[0] = 0 Then
    Return SetError(4, 0, 0)
    Else
    Return $sDeviceName
    EndIf
    EndFunc ;==>_PartialDrive

    [/autoit]

    Ansonsten: Wieder mal eine Klasse Funktion! :thumbup:

  • WOW

    Das ist doch ein schönes X-MAS Geschenk.

    Frage: Kann mal diesem V-LW auf eine Seriennummer oder ein Laufwerk zuordnen?

    Eine PN geht noch an BugFix. Hier weiß ich nicht, ob man das öffentlich diskutieren sollte. Das überlasse ich BugFix, der gerne aber mit Oscar oder anderen guten Stammies drüber diskutieren darf.

    LG, Alina.

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl

    • Offizieller Beitrag

    FirePanther:
    Danke für die Info, dadurch habe ich bemerkt, dass man mit FileExist('Drive:') keine LEEREN CD/DVD-Lw auf Existenz abfragen kann. deshalb wurde deines nicht erkannt.
    Ich habe die Abfrageroutine jetzt geändert, und somit sollte dein Problem gelöst sein. Korrektur s. 1. Post.

    Zitat von FirePanther

    gibts ne möglichkeit sowas dauerhaft zu erstellen? virtuelle laufwerke eben


    Der einfachste Weg: Du schreibst den Aufruf zum Erstellen des Lw in ein Autostart-Skript.

    • Offizieller Beitrag

    Stimmt! Das mit FileExists wusste ich auch noch nicht. Man kann aber stattdessen "DriveGetType" benutzen:

    [autoit]


    Func _PartialDrive($sDeviceName=-1, $sTargetPath=-1, $iDelete=0)
    If $sDeviceName = -1 And $iDelete = 0 Then
    Local $j = 100
    While DriveGetType(Chr($j) & ':')
    $j += 1
    If $j > 122 Then Return SetError(2,0,0)
    WEnd
    $sDeviceName = Chr($j) & ':'
    ElseIf ($sDeviceName = -1 Or Not FileExists($sDeviceName)) And $iDelete = 1 Then
    Return SetError(5,0,0)
    EndIf
    [...]

    [/autoit]

    Edit: BugFix, mir ist gerade noch aufgefallen, dass man zum Löschen auch den Zielpfad angeben muss. Musste gerade ganz schön suchen, mit welchem Pfad ich das LW erstellt hatte (wollte nicht neu starten). Kann man den Aufruf auch so ändern, dass man nur den Buchstaben angeben kann?

    • Offizieller Beitrag

    BugFix, mir ist gerade noch aufgefallen, dass man zum Löschen auch den Zielpfad angeben muss.


    Danke für den Hinweis. Habe jetzt eine Erweiterung eingefügt, dass der zugehörige Pfad selbständig ermittelt wird. Es braucht also nur noch der Laufwerksbuchsstabe angegeben werden. (s. Post1)

  • Tut mir leid, das ich diesen Thread wieder ausgrabe, aber bei mir gibt's immer diese Fehlermeldung beim _PartialDrive :(. Auf einem anderen PC funktioniert es. Liegt es an XP?

    Zitat

    ==> Variable must be of type "Object".:
    $oDrives.Add(Asc(StringLeft($aDrives[$i],1)))
    $oDrives^ ERROR

    Rechtschreibfehler sind Spezialeffekte meiner Tastatur.

    • Offizieller Beitrag

    Liegt es an XP?

    Nun dadran nicht. Vermutlich hast du das erforderliche NET Framework nicht installiert. Bin mir nicht ganz sicher - sollte im 2.0 enthalten sein. Aber es ist generell sinnvoll, alle Versionen zu installieren, da immer mehr Software das voraussetzt.

    Mit folgendem Skript kannst du prüfen ob das Objekt vorhanden ist.

    [autoit]

    $oArrayList = ObjCreate("System.Collections.ArrayList")
    If Not IsObj($oArrayList) Then ConsoleWrite( 'Das Objekt "System.Collections.ArrayList" ist auf dem PC nicht enthalten' & @CRLF )

    [/autoit]
  • kleiner tipp^^ dafür braucht man keine UDF's:
    geht nur unter windows und ist schon so mit dabei ab win 2k glaub ich:

    [autoit]

    Run("subst Z: C:\Programme")

    [/autoit]

    Kleine Beschreibung:

    subst: ist schon das Programm von Windows schon Serienmäßig dabei.
    Z: => ist das laufwerk das zum einbinden von dem jeweiligen ordner ist und beinhalten soll => siehe nächste zeile
    C:\Programme => der ordner der zu Z: eingebunden werden soll.

    Wenn du dann beim Explorer in das Laufwerk Z: gehst dann wird C:\Programme angezeigt und können vollständig verwendet, bearbeitet, und angezeigt werden.

    Nachteil: alles was du in Z: veränderst, wird auch in C:\Programme verändert...

    Wie man das eingebundene Laufwerk wie man wieder weg machen kann:

    [autoit]

    Run("subst Z: /D")

    [/autoit]

    Z: => das eingebundene Laufwerk
    /D => zum auswerfen ungefähr


    Edit: Oh Sorry hab ned gewusst dass des schon jemand gepostet hat -.-!

    Gruß
    Fabi