PowerShell (W10): „Entferne von Laufwerk X den Buchstaben“

cumulonimbus8

Fleet Admiral
Registriert
Apr. 2012
Beiträge
18.924
Moin!

Ich suche nach einer bescheidenen Lösung via Kommandozeile. So bescheiden, dass ich mich nicht durch die Dialog der Datenträgerverwaltung quälen muss. (Zum Buchstabenändern habe ich was gefunden…)

Typisches Szenario - ich hänge eine Systemplatte per Adapter an mein System und WIN schafft es neben dessen C auch (teilweise) den anderen Partitionen Buchstaben zuzuweisen. Gefährlich und verwirrend.

Welche (und ich vermute wohl PowerShell anstrengen zu müssen?) Kommandozeile ist nötig nur mit dem übergebenen Buchstaben (z.B. aus dem Kontextmenü heraus über ein Skript) jenem Laufwerk den Buchstaben zu entziehen?

Google lieferte in diverser Form immer umständliche Wege sich erst Partitionsnummer und Laufwerknummer per Abruf und Merken zu beschaffen. Das taugt auf keinen Fall so. Ein Skript muss sich bitte anhand des Buchstabens selbst solche Infos besorgen.

CN8
 
PowerShell:
Function DeleteDriveLetterWithCmdInput {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateScript({ if (-not ($_ -match '^[A-Z]$')) throw "Invalid input" })]
        [String] $DriveLetter
    )
    try {
        $Drive = Get-CimInstance -ClassName Win32_Volume -Filter "DriveLetter = '$DriveLetter:'"
        if ($Drive -ne $null -and $Drive.Count -eq 1 ) {
            $Drive | Set-CimInstance -Property @{DriveLetter = ""} -WhatIf
            Write-Host "Success"
        } else {
            Write-Warning "Drive $DriveLetter isn't existing!"
        }
    }
    catch {
        Write-Host "Error:"
        Write-Host $_.ErrorDetails
    }
}
Weiß nicht, ob das ganz deiner Vorstellung entspricht - jedenfalls geht es auch ohne Laufwerks- und Partitionsnummer?

Bleibt Gefährlich - man braucht dafür Adminrechte! (Ich hab extra mal nochl ein -WhatIf hingemacht...) - Verwendung auf eigene Gefahr!
 
Zuletzt bearbeitet:
cumulonimbus8 schrieb:
ich hänge eine Systemplatte per Adapter an mein System und WIN schafft es neben dessen C auch (teilweise) den anderen Partitionen Buchstaben zuzuweisen. Gefährlich und verwirrend.

Wenn dieser Adapter per USB an Deiner Kiste angeploppt wird, nimm den USB-Drivelettermanager (USBDLM) von Uwe Sieber und stell den so ein, dass angesteckte USB halt bestimmte Buchstaben bekommen. Dein A bis C und Buchstaben fuer Netzlaufwerke kannst Du von der Vergabe bei anploppen ausschliessen. Es geht damit sogar, dass keine Buchstaben vergeben werden sondern in Ordner gemountet wird.

Abgesehen davon hat es bei mir noch nie eine waehrend der Laufzeit eines Windows angesteckte Platte geschafft sich C:\ zu krallen.
 
Der USB DriveLetterManager nützt nichts da ich ihn so oft anlernen müsste wie mir Platten in die Hände fallen… 😉 Das sind immer andere. Und auch die freien Buchstaben variieren.


@ elgorro: ich »spreche leider kein PowerShell« und verlaufe mich in der Syntax was nun genau was tut…
Bitte nur wörtlich eine Zeile im Batch-Stil von REVOKE DRIVELETTER %1.

Das PS-Skript wird über das Kontextmenü ausgelöst. Genauer wird ein AutoIt-Skript ausgelöst das eine »GUI« (hüstel) erzeugt die (Plan, weil eben schon so vorhanden) alle möglichen freien Buchstaben abgibt zu denen man wechseln kann und die nun um ein ›Buchstabe-Entfernen‹ ergänzt werden soll. Den entscheidenden Schritt tut dann unser minimales PS-Skript.
Ändern tue ich bequem mit (reduziert)
C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.Exe Set-Partition -DriveLetter X -NewDriveLetter Y
Nichts mehr hätte ich gerne fürs Entfernen von X, wobei X der GUI übergeben wurde, Registry. So simpel Y einfach weglassen zu können ist unsere übermächtige PS ja leider nicht…

🙂 Ja, die Warnungen sind völlig richtig, und ich habe selbst auf C in meinem Skript den Daumen drauf.
🙂 Und der Code mit den Abfragen verdient ein Lob.

CN8
 
Lade dir einfach Change Letter 1.20 runter. Das bindet sich ins Kontextmenü ein. Dort kannst du dann "Remove X:" anklicken und der Laufwerksbuchstabe wird entfernt.

Und weiterhin kannst du mit Set-Partition sehr wohl den Laufwerksbuchstaben verstecken:
Set-Partition -DriveLetter Y -IsHidden $True
 
Ich habe mir dieses Change Letter runtergeladen - und es scheitert an meinen Ansprüchen.

Die ReadMe enthält keine Anleitung zum Einrichten [ich weiß wie ich was ins Kontextmenü bekomme, der Laie nicht], was der Button «Hide» tut, was «Remove» - oder genauer was Unterschiedliches diese Maßnahmen bewirken.

Weiterhin (ich verlinke jetzt mal nicht auf meinen zugehörigen Thread) wollte ich, und musste es|sie selbst bauen, eine GUI die mir unmittelbar alle freien Buchstaben angibt auf die ich Laufwerk X (Kontextmenü = Laufwerk bekannt) ändern könnte. Ich begnüge mich dem Klick einen zu wählen und einem weiteren Klick das auszulösen. Change Letter verlangt da (wie auch die unten erwähnte Konkurrenz) mehr Klicks. Und das wollte ich weghaben.

C:\>powershell Set-Partition -DriveLetter O -IsHidden $True
Set-Partition : Das angeforderte Objekt wurde nicht gefunden.
In Zeile:1 Zeichen:1
  • Set-Partition -DriveLetter O -IsHidden $True
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (PS_StorageCmdlets:ROOT/Microsoft/..._StorageCmdlets) [Set-Partition], C
imException
+ FullyQualifiedErrorId : MI RESULT 6,Set-Partition


O ist ein leeres Laufwerk eines CardReaders, daran scheitert auch mein gegebenes Beispiel [die Fehlermeldung ist analog; scheinbar kann Set-Partition nicht zugreifen?], der in Bereitschaft befindliche DriveLetterChanger indes schafft es. PowerShell sinkt massiv in meiner Achtung.
Auch mit dem belegten DVD-Brenner X scheitert der Hide-Befehl.
Mit einer normalen Platte klappts. (Mit einem belegten CardReader-LW wiederum nicht.)

💣
Damit hätte ich eine Lösung - Danke an Evil E-Lex - die aber nicht 100% funktioniert! PowerShell versagt auf voller Länge.
Daher leider eine neue, ergänzende Frage:
Welche wirklich verlässlichen Befehlszeilen (und es wird wohl wieder auf die PS hinauslaufen?!) erfassen wirklich alle Laufwerke um den Buchstaben zu ändern oder zu löschen?

CN8

PS: und noch will ich keine Funktion die mir namenlose Partitionen listet um ihnen einen Buchstaben zuzuweisen… noch nicht… 😇
 
cumulonimbus8 schrieb:
Der USB DriveLetterManager nützt nichts da ich ihn so oft anlernen müsste wie mir Platten in die Hände fallen… 😉 Das sind immer andere. Und auch die freien Buchstaben variieren.

Ganz ehrlich glaub ich nicht das Du ansatzweise Dich mit dem USBDLM beschaeftigt hast bzw. wirklich gelesen hast was ich dazu getippt habe.

Wenn bei Dir die freien Buchstaben variieren bring Ordnung in die Huette so dass immer und auf allen Geraeten Laufwerke gleich benamst und angeplopptes Krams die gleichen Buchstaben bekommt. Das Mittel dafuer siehe oben.

Komm jetzt nicht mit „Cheffe will das nicht“. 😉

cumulonimbus8 schrieb:
O ist ein leeres Laufwerk eines CardReaders

Wozu muss ein leeres Laufwerk einen Buchstaben haben?

Anyway.

Guten Rutsch 🎆
 
Ich habe mich schon vor langen Jahren mit diesem USBDLM beschäftigt.
Und meine Erfordernisse erlauben es nicht besagte Ordnung reinzubringen [als ob ich da grundsätzlich sogar was gegen hätte…] damit er greifen kann. Wäre ja auch zu einfach.

Warum ein leeres Laufwerk eines CardReaders einen Buchstaben hat? Weil es nun mal so ist, dass das Laufwerk des CardReades überhaupt einen Buchstaben hat. (Wie das DVD-LW ja auch oder einst die Floppy :D ) So ganz ohne wäre es nicht ansprechbar und damit nutzlos, gelle?

Guten Rutsch allen bevor ich’s vergesse!

CN8
 
cumulonimbus8 schrieb:
Warum ein leeres Laufwerk eines CardReaders einen Buchstaben hat? Weil es nun mal so ist, dass das Laufwerk des CardReades überhaupt einen Buchstaben hat.
Bei neueren Windows-Versionen ist das standardmäßig nicht mehr der Fall. Alle Laufwerke ohne Partition dahinter werden ausgeblendet. Daher funktioniert auch Set-Partition nicht. Wenn keine Partition da ist, kann auch nichts bearbeitet werden.
 
  • Gefällt mir
Reaktionen: BFF
Nanu..?!
Ja, ich habe das Ausblenden leerer Laufwerke aktiv (oder bin ich blöd? nee, ist auf Aus); aber alle Cardreader (ein fest angeschlossener und einer für den Bedarf) tauchen {auch} als leere Laufwerke auf, ganz so wie es ein DVD-LW auch tut, ganz so wie ich das erwarten würde.
Nein, es liegt auch nicht an dieser Einstellung… Set-Partition klappt einfach nicht so wie ich das gerne hätte. Gibt es denn keine andere Schraube an der man drehen kann?

CN8
 
Hier sind alle Cmdlets aufgelistet, die mit dem Thema "Storage" zu tun haben: Powershell - Storage
Theoretisch gäbe es noch Set-Volume, dort gibt es aber keinen -IsHidden Parameter. Passt also nicht.

Der Tipp von @elgorro mit Get-CimInstance und Set-CimInstance ist da schon ganz gut. Das sind aber natürlich universelle Cmdlets die alle WMI-Klassen manipulieren können, daher ist dort mehr Aufwand nötig, damit man die richtigen Werte findet.

Eine weitere Möglichkeit wäre das Bearbeiten des Schlüssels NoDrives in Registry. Das ist aber durch den Aufbau des Schlüssels recht aufwändig zu skripten. Nichts anderes wie den NoDrives-Schlüssel zu bearbeiten macht übrigens der Hide-Button von ChangeLetter. Daher muss nach klick auf den Button auch der Explorer neu gestartet werden, um die Änderungen zu übernehmen.

Eine Idee wäre noch diskpart zu nutzen. Das lässt mittels Parameter /s die Angabe von Skriptdateien zu. Vielleicht kannst du dir daraus was bauen.

Ebenfalls einen guten Rutsch!
 
Evil E-Lex schrieb:
Daher muss nach klick auf den Button auch der Explorer neu gestartet werden, um die Änderungen zu übernehmen.
Das wäre ein effektives Unding… Aber es ist offenbar eine MS-Krankheit, dass genug Einstellungen in z.B. den Ansichts-Optionen live funktionieren, ohne offensichtlichen Explorer-Neustart, identische manuelle Änderungen in der Registry aber nur so wirksam werden.

Bei DiskPart sehe ich weniger den Aufruf denn das Problem auch die richtige Partition (des richtigen Laufwerks) zu erwischen.

Get-CimInstance und Set-CimInstance - ich scheitere am vollständigen Befehlssatz… Wenn dieser Zugriff aber »durchzieht« werde ich wohl darauf umschwenken müssen.
Wenn Set-CimInstance -Property @{DriveLetter = ""} statt der "" zum Löschen auch eine neuen Buchstaben annimmt wäre das schon sehr nützlich.

Für den Augenblick aber werde ich mal am Wechsel zu 2022 herumbasteln - da will Einiges umgestellt werden.

CN8
 
cumulonimbus8 schrieb:
Wenn Set-CimInstance -Property @{DriveLetter = ""} statt der "" zum Löschen auch eine neuen Buchstaben annimmt wäre das schon sehr nützlich.
Natürlich - is ja ein Setter aus der wahrscheinlich größten Softwareschmiede auf dem Planeten ;-)
PowerShell:
Function DeleteDriveLetterWithCmdInput {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateScript({ if (-not ($_ -match '^[A-Z]$')) throw "Invalid input" })]
        [String] $OldDriveLetter

        [Parameter()]
        [ValidateScript({ if (-not ($_ -match '^[A-Z]$')) throw "Invalid input" })]
        [String] $NewDriveLetter = ""
    )
    try {
        $Drive = Get-CimInstance -ClassName Win32_Volume -Filter "DriveLetter = '$OldDriveLetter:'"
        if ($Drive -ne $null -and $Drive.Count -eq 1 ) {
            $Drive | Set-CimInstance -Property @{DriveLetter = "$NewDriveLetter:"} -WhatIf
            Write-Host "Success"
        } else {
            Write-Warning "Drive $OldDriveLetter isn't existing!"
        }
    }
    catch {
        Write-Host "Error:"
        Write-Host $_.ErrorDetails
    }
}

Damit wäre ScripName.ps1 -OldDriveLetter A -NewDriveLetter B - wobei NewDriveLetter optional ist.
 
  • Gefällt mir
Reaktionen: PHuV
Ah, hervorglänzend 🙂
Wenn mich nicht ein anderes Problem geärgert hätte dann hätte ich schon längst damit probiert.

CN8
 
  • Gefällt mir
Reaktionen: elgorro
cumulonimbus8 schrieb:
Ja, ich habe das Ausblenden leerer Laufwerke aktiv (oder bin ich blöd? nee, ist auf Aus); aber alle Cardreader (ein fest angeschlossener und einer für den Bedarf) tauchen {auch} als leere Laufwerke auf,
Ich hab das jetzt bei mir nachvollziehen können. Tatäschlich ist es so, dass die Laufwerke auftauchen, obwohl die Einstellung "Leere Laufwerke ausblenden" aktiv ist. Ich habe mein Windows 10 21H2 frisch installiert. Bei meiner alten Installation wurde die Einstellung noch korrekt übernommen.
 
Am Rande… Das Problem war der neue PC. Da ist das Board wohl auch etwas eigen. Ich habe vorsichtshalber alle SATAs auf HotPlug gestellt. Belohnung ist ein überquellender Explorer.

Die Befehlszeile habe ich mittlerweile eingeflochten.
WIN scheint aber ein seltsames Gedächtnis zu haben was Hide meint. Ein so entfernter Buchstabe war nach Wiederzuweisung per Datenträgerverwaltung nach einem Reboot wieder flöten. (Genialerweise saß da dann das DVD-LW drauf sodass das nicht mal gleich auffiel; wohl Folge von Entziehnugsversuchen dort die scheinbar nicht gegriffen hatten…)

CN8
 
cumulonimbus8 schrieb:
WIN scheint aber ein seltsames Gedächtnis zu haben was Hide meint. Ein so entfernter Buchstabe war nach Wiederzuweisung per Datenträgerverwaltung nach einem Reboot wieder flöten.
Das ist das erwartbare Verhalten. Beachte, dass die "Hide"-Funktion eigentlich für große voll verwaltete Netzwerke mit Gruppenrichtlinien gedacht ist. Dort will man, dass einmalig eingestellte Parameter dauerhaft gültig sind.
Mich wundert eher, dass du ein so verstecktes Laufwerk überhaupt noch in der Datenträgerverwaltung angezeigt bekommst. Allerdings ist es schon immer ein Kreuz gewesen mit der Logik der Laufwerksbuchstabenzuweisung, da gebe ich dir vollkommen recht.
 
Warum ein physisches Laufwerk denn nicht ohne seine Buchstaben auftauchen sollte… Es wäre entsetzlich wenn nicht 😉
Ich habe da mal wild rumprobiert, zugewiesen, entzogen. Wäre kein Wunder wenn noch irgendwas irgendwie offen gewesen wäre von dem man nichts merkt, weswegen das LW sichtbar bleibt und dann nach dem reboot verschwindet.

Es ist allerdings wirklich ein Kreuz. Ich hänge Backupplatten an USB - Buchstabe passt. Ich ändere was Anderes bei den Buchstaben - kompletter Gedächtnisschwund… Und nun rate mal jemand wozu ich so einen unmittelbaren Sktiptbefehl brauche 🙂

PS: Den alten Rechner habe ich eben noch mal aus Neugier und Notreserve in Gang genommen. »Alte« SSD, selbe Hardware, aber, oh Wunder, WIN sucht einen Schwung Updates. Dabei das DVD-LW vergessen. eine wenig hot gepluggt und siehe, es war da. Nur eine andere Platte mit zufällig diesem Betriebssystem (Image) hatte für C keine Buchstaben bekommen. Warum nur? WIN ist wirklich komisch.

Und um zu liefern - hier das AutoIt Skript das direkt aus dem Kontextmenü und %L aufgerufen wird.
Code:
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
;#NoTrayIcon

#Region Konstanten
Const $Pipe = "|"
Local $LaufwerkeListe = ""
Local $FreieLaufwerke
Const $FensterName = '(Keiner)' ; ´written by CyRoX
Const $LaufwerkeTypen = 'ALL'
Local $UserForm
Const $XKoordinate = 35
Const $YAbstand = 20
Const $FormularBreite = 90
Const $FormularXNull = 60
Const $FormularYNull = 70
Const $KnopfXNull = 10
Const $KnopfYNull = 5
Const $KnopfHoch = 20
Const $KnopfBreit = 70
$YKoordinate = $KnopfYNull
Local $QuellLaufwerk
Local $KnopfText
Local $EntfernKnopfText
Local $RechenHilfe
Local $GeklicktesLaufwerk
Local $ZielLaufwerk
Const $ProgPfad = "C:\Windows\System32\WindowsPowerShell\v1.0\"
Const $ProgName = "PowerShell.Exe"
#EndRegion

#Region Kommandozeile
If $CmdLine[0] = 0 Then
 Exit
Else
 $QuellLaufwerk = $CmdLine[1]
    $KnopfText = StringLeft($CmdLine[1], 2) & " ->"
     $EntfernKnopfText = StringLeft($CmdLine[1], 2) & " Entfernen"
EndIf
#EndRegion

#Region Freie Laufwerke
$Laufwerke = DriveGetDrive("All")
$LaufwerkeAlle = _ArrayToString($Laufwerke, $Pipe, 1) & $Pipe
$LaufwerkeAlle = StringUpper($LaufwerkeAlle)
For $i = 67 to 90 ;97 to 122
 If StringInStr($LaufwerkeAlle, Chr($i) & ":" & $Pipe) = 0 Then $LaufwerkeListe = $LaufwerkeListe & Chr($i) & $Pipe
Next
$LaufwerkeListe = StringLeft($LaufwerkeListe, StringLen($LaufwerkeListe) -1)
$FreieLaufwerke = StringSplit($LaufwerkeListe, $Pipe)
#EndRegion

#Region GUI
$RechenHilfe = $KnopfYNull + $KnopfHoch + $KnopfYNull + $YKoordinate + ($FreieLaufwerke[0] * $YAbstand) + $KnopfHoch
$UserForm = GUICreate($FensterName, $FormularBreite, $RechenHilfe, $FormularXNull, $FormularYNull)
Dim $RadioKnopf[$FreieLaufwerke[0]]
For $I = 1 To $FreieLaufwerke[0]
; $RadioKnopf[$I-1] = GUICtrlCreateCheckbox(StringUpper($FreieLaufwerke[$I]), $XKoordinate, $YKoordinate)
 $RadioKnopf[$I-1] = GUICtrlCreateRadio(StringUpper($FreieLaufwerke[$I]), $XKoordinate, $YKoordinate)
 $YKoordinate = $YKoordinate + $YAbstand
Next
$FormularStarter = GUICtrlCreateButton($KnopfText, $KnopfXNull, $YKoordinate + $KnopfYNull, $KnopfBreit, $KnopfHoch)
$YKoordinate = $YKoordinate + $YAbstand
$EntfernBolzen = GUICtrlCreateButton($EntfernKnopfText, $KnopfXNull, $YKoordinate + $KnopfYNull, $KnopfBreit, $KnopfHoch)
GUISetState(@SW_SHOW)
#EndRegion

#Region AusLeseSchleife
$ZielLaufwerk = ''
While $ZielLaufwerk = ''
    $FormularKlickWert = GUIGetMsg()
    Switch $FormularKlickWert
        Case -3
            Exit
        Case $FormularStarter
            $GeklicktesLaufwerk = ''
            For $I = 1 To $FreieLaufwerke[0]
                If BitAND(GUICtrlRead($RadioKnopf[$I-1]), 1) Then
                 ;$GeklicktesLaufwerk &= ControlGetText($FensterName, '', $RadioKnopf[$I-1]) & ' '
                 $GeklicktesLaufwerk = ControlGetText($FensterName, '', $RadioKnopf[$I-1])
                EndIf
            Next
            If $GeklicktesLaufwerk <> '' Then
             $ZielLaufwerk = $GeklicktesLaufwerk
            Else
                Exit
            EndIf
            GUISetState(@SW_HIDE)
        Case $EntfernBolzen
            $ZielLaufwerk = "HIDE"
            GUISetState(@SW_HIDE)
    EndSwitch
WEnd
#EndRegion

#Region Schalten
If $ZielLaufwerk <> '' Then
 If StringLen($ZielLaufwerk) = 1 Then
        ;MsgBox(64, 'Ente', $ProgPfad & $ProgName & " Set-Partition -DriveLetter " & StringLeft($QuellLaufwerk, 1) & " -NewDriveLetter " & $ZielLaufwerk, $ProgPfad)
        Run ($ProgPfad & $ProgName & " Set-Partition -DriveLetter " & StringLeft($QuellLaufwerk, 1) & " -NewDriveLetter " & $ZielLaufwerk, $ProgPfad)
 Else
        ;MsgBox(64, 'Ente', $ProgPfad & $ProgName & " Set-Partition -DriveLetter " & StringLeft($QuellLaufwerk, 1) & " -IsHidden $True" & "  [" & $ZielLaufwerk & "]", $ProgPfad)
        Run ($ProgPfad & $ProgName & " Set-Partition -DriveLetter " & StringLeft($QuellLaufwerk, 1) & " -IsHidden $True", $ProgPfad)
 EndIf
EndIf
#EndRegion
Bitte nicht nach wirklichem Kommentieren und Ordnung fragen 😇
Und es wäre möglich, dass die verwiesene PowerShell nicht die Neueste ist.

Ach ja, die Registry:
Code:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Drive\shell\DLC CN8]
@="Drive-Letter-Changer CN8"

[HKEY_CLASSES_ROOT\Drive\shell\DLC CN8\command]
@="J:\\ANW\\AutoIt3\\Examples\\DriveLetterChangerCN8.exe %L"
Der Pfand und der Name müssen natürlich angepasst sein

CN8
 
Danke für das Skript!
cumulonimbus8 schrieb:
Und es wäre möglich, dass die verwiesene PowerShell nicht die Neueste ist.
Das passt schon. Aktuell ist in WIndows 10 Version 5.1 der "Windows PowerShell" aka powershell.exe. Im Pfadnamen steht trotzdem immer v1.0. Muss man nicht verstehen. Diese PowerShell wird nicht weiterentwickelt.
Daneben gibt es noch die "PowerShell" in Version 7.2.1 aka pwsh.exe. Die muss man separat installieren.
 
Von Letzterem hatte ich was aufgeschnappt, deswegen auch der Hinweis 👍
CN8
 
Zurück
Oben