Removable media holding D drive letter - windows

I have on my system some SD card or removable media drive which by default takes the D drive letter.
I have this:
PS C:\Windows\System32\WindowsPowerShell\v1.0> get-volume | where DriveType -Match "Removable"
DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining Size
----------- --------------- ---------- --------- ------------ ------------- ----
E Removable Healthy 0 B 0 B
And I want to change it to G like this:
PS C:\Windows\System32\WindowsPowerShell\v1.0> get-volume | where DriveType -Match "Removable" |Set-Partition -NewDriveLetter G
But I get:
Set-Partition : One or more parameter values passed to the method were invalid.
At line:1 char:50
+ ... | where DriveType -Match "Removable" |Set-Partition -NewDriveLetter G
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (PS_StorageCmdlets:ROOT/Microsoft/..._StorageCmdlets) [Set-Partition],
CimException
+ FullyQualifiedErrorId : MI RESULT 4,Set-Partition
How can I change this? Or what is the issue? I tried with the get-disk to pass but doesn't work either.
I can change in the computer management gui but I need commandline.

You should be able to do it with something like this.
$DriveLetter = (Get-Volume | Where-Object {$_.DriveType -eq "Removable"}).DriveLetter
Get-Partition -DriveLetter $DriveLetter | Set-Partition -NewDriveLetter G

Removable drives (at least without media) does not work with Set-Partition
Worked around this by scripting diskpart
"SELECT VOLUME D`nREMOVE LETTER=D`nASSIGN LETTER=G NOERR" | diskpart
This selects volume d, removes given letter and assigns new letter (ignoring error)

Related

Mount ISO with a drive letter via Powershell

I am trying to mount an ISO and I would like to associate a drive letter with that mount. I would like to specify the drive letter as say Y:\
The below does not work, can anyone help me out. Thanks
#Variable Declaration
$isoImg = "P:\Software\Windows10CurrentVersion\Windows10.iso"
#Mount ISO and Gather Drive Letter
Mount-DiskImage -ImagePath $isoImg -PassThru | Out-Null
#Obtain Drive Letter
$driveletter = (Get-DiskImage $isoImg | Get-Volume).DriveLetter
You could mount the ISO and accept (for now) the automatically assigned drive letter.
It is possible to change that afterwards, but you will need to run that as Administrator:
# the full path to the ISO file
$isoPath = "P:\Software\Windows10CurrentVersion\Windows10.iso"
# mount the ISO, but first check if it is already mounted
$isoDrive = Get-DiskImage -ImagePath $isoPath
if (!$isoDrive) {
$isoDrive = Mount-DiskImage -ImagePath $isoPath -PassThru
}
# $isoDrive is a Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/Storage/MSFT_DiskImage
# get the DriveLetter currently assigned to the drive (a single [char])
$isoLetter = ($isoDrive | Get-Volume).DriveLetter
Rename the driveletter for this drive.
This part needs to be run as Administrator
# find the volume by its automatically assigned driveletter and set the new drive letter
$drive = Get-WmiObject Win32_Volume -Filter ('DriveLetter = "{0}:"' -f $isoLetter)
$drive.DriveLetter = 'Y:'
$null = $drive.Put()
To dismount the iso drive:
$isoDrive | Dismount-DiskImage | Out-Null
Hope that helps
You can mount the ISO image and then assign the drive letter like this:
# ISO image - replace with path to ISO to be mounted
$isoImg = "P:\Software\Windows10CurrentVersion\Windows10.iso"
# Drive letter - use the required drive letter instead of Y:
$driveLetter = "Y:"
# Mount the ISO, without having a drive letter auto-assigned
$diskImg = Mount-DiskImage -ImagePath $isoImg -NoDriveLetter
# Get mounted ISO volume
$volInfo = $diskImg | Get-Disk | Get-Partition | Get-Volume
# Mount volume with specified drive letter (requires Administrator access)
mountvol $driveLetter $volInfo.UniqueId

Select-Object changes selected value

Short problem description:
I'm trying to get the path of a network drive in PowerShell. With Get-PSDrive I get all the information I need.
PS X:\> Get-PSDrive -Name X
Name Used (GB) Free (GB) Provider Root CurrentLocation
---- --------- --------- -------- ---- ---------------
X 1527,59 214,61 FileSystem \\Path\to\network\drive
Now I want to save Root in a variable, but when I do
PS X:\> Get-PSDrive -Name X | Select-Object Root
I get
X:\
Why does Select-Object change the value? How can I get the "raw" value?
The default table display of Get-PSDrive displays the DisplayRoot property value as Root unless it is empty. You can see this behavior by piping your Get-PSDrive to Format-List *. To control the output, you can use a calculated property with Select-Object.
Get-PSDrive -Name X | Select-Object #{
Name='Root'
Expression = {
if ([string]::IsNullOrEmpty($_.DisplayRoot)) {
$_.Root
}
else {
$_.DisplayRoot
}
}
}
Explanation:
If you check the $pshome\PowerShellCore.format.ps1xml file, it defines the root value with the following expression, which is why you see this behavior.
if($_.DisplayRoot -ne $null) { $_.DisplayRoot } else { $_.Root }

How to get every disk in Windows and filter on DeviceType and then add the size of the disk next to it, separated by a comma?

I'm writing an PowerShell script to collect some data of a computer. I'm almost done, but I don't know how to get size of all the disks on the computer. I know how to do it with a couple of If statements, but I want it to automatically detect the drives, not that I have to write a new If statement if a new disk is attached. The output I want is as follows: "A:,250GB". The "A:," bit works, but not the disk size bit.
This is the code I used and tweaked, but to no avail:
$Drives = Get-WmiObject Win32_logicaldisk| ?{$_.DriveType -eq 3} | ForEach-Object {$_.name}
ForEach ($Drivename in $Drives) {
$Drivenames = Get-WMIObject -Query "Select * From win32_logicaldisk Where DriveType = '3'" -computer localhost | Select-Object DeviceID
$Drive = [Math]::Round($Drivenames.Size / 1GB)
"$Drivenames,", $Drive | Out-File "C:\HDS\HDS_DRIVES.csv" -Append
}
In addition, [Math]::Round($Drivenames.Size / 1GB) throws me an error:
Method invocation failed because [System.Object[]] does not contain a method named 'op_Division'"
You can use Calculated Property with Select-Object to make it much more simple:
Get-WmiObject Win32_logicaldisk| ? {$_.DriveType -eq 3} |
Select-Object #{N="DeviceId";E={$_.DeviceId}},`
#{N="VolumeName";E={$_.VolumeName}},`
#{N="Size";E={[Math]::Round($_.Size / 1GB)}} |
Out-File "C:\HDS\HDS_DRIVES.csv" -Append
Note that you don't need to Invoke Get-WmiObject Twice like in your example.
Why it doesn't work?
The issue is that $Drivenames contains only DeviceID (as you used Select-Object to get only that property). Therefore you're getting an error where trying to round it (as rounding nothing is not supposed to work).
How to fix it?
You have to add Size and then access it using .PropertyName:
$DriveInfo = Get-WMIObject -Query "Select * From win32_logicaldisk Where DriveType = '3'" -computer localhost | Select-Object DeviceID, Size
$DriveInfo | ForEach-Object {
$DriveSize = [Math]::Round($_.Size / 1GB)
"$($_.DeviceID),$DriveSize" | Out-File "C:\HDS\HDS_DRIVES.csv" -Append
}
How can I make it more elegant
Also, take a look at #Avshalom's answer which uses calculated property.

For loop to connect to 3 machines and get the disk space and convert the values

Invoke-Command -ComputerName server01 {Get-PSDrive D} | Select-Object PSComputerName,Used,Free
Invoke-Command -ComputerName server02 {Get-PSDrive D} | Select-Object PSComputerName,Used,Freecode
Invoke-Command -ComputerName server03 {Get-PSDrive D} | Select-Object PSComputerName,Used,Free
OUTPUT:
PSComputerName Used Free
server01 2534760280064 256550076416
server02 2534760280061 20000000010
server03 2534760280061 2000000001011
DESIRED OUTPUT: That will send an email.
server01 2.53T 238.9G
server02 2.53T 18.62G
server03 2.53T 1.86T
I think the 2nd column or USED SPACE will be divided by 1000000000 and the Free Space or 3rd Column will be divded by 1073741824.
What you want to use here is a Calculated Property, which allows you to perform operations on values in the pipeline.
Here's the syntax, just add this to your Select-Object list of properties.
#{ Name = ''; Expression = {}}
So to use it in your example
Select-Object PSComputerName,#{ Name = 'Used (TB)'; Expression = {$_.Used/1tb}},Free
You can add additional logic within the Expression Script block to alternate between GB and TB, but this answer should get you heading in the right direction.
If you find that this carries too many digits, you can round up to the nearest tenth using the .net class [math] and its static method of ::Round(). Round takes two inputs (or overloads, as we call them in methods), like this.
[math]::Round(NumberToBeRounded, PositionsToRound)
[math]::Round(3.14159627, 3)
>3.141
So, to round your hard drive space figures:
"$([math]::Round(($_.Used/1gb),2)) GB"
PSComputerName Used
-------------- ---------
localhost 1454.39 GB

Can wmic get model info of path or physical names?

Is it possible to do this powershell script in plane old wmic commands? I need to get disk model info based off a path or drive letter if possible but am having issues running powershell scripts.
Get-WmiObject Win32_DiskDrive | % {
$disk = $_
$partitions = "ASSOCIATORS OF " +
"{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " +
"WHERE AssocClass = Win32_DiskDriveToDiskPartition"
Get-WmiObject -Query $partitions | % {
$partition = $_
$drives = "ASSOCIATORS OF " +
"{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " +
"WHERE AssocClass = Win32_LogicalDiskToPartition"
Get-WmiObject -Query $drives | % {
New-Object -Type PSCustomObject -Property #{
Disk = $disk.DeviceID
DiskSize = $disk.Size
DiskModel = $disk.Model
Partition = $partition.Name
RawSize = $partition.Size
DriveLetter = $_.DeviceID
VolumeName = $_.VolumeName
Size = $_.Size
FreeSpace = $_.FreeSpace
}
}
}
}
Script was shared in this question:
Combine `Get-Disk` info and `LogicalDisk` info in PowerShell?
I'm not sure I understand:
wmic is for making single, simple queries.
If you want to make more sophisticated queries (for example, the nested loops above), you're going to need some kind of "programming language". Like C#, VBScript ... or Powershell.
Q: What exactly are the "problems" you've encountered trying to execute this script?
Here is sample output from your script:
d:\>powershell -ExecutionPolicy ByPass -File tmp.ps1
DiskSize : 128034708480
RawSize : 117894545408
FreeSpace : 44036825088
Disk : \\.\PHYSICALDRIVE1
DriveLetter : C:
DiskModel : SanDisk SD6SF1M128G
VolumeName : OS_Install
Size : 117894541312
Partition : Disk #1, Partition #2
DiskSize : 320070320640
RawSize : 320070836224
FreeSpace : 29038071808
Disk : \\.\PHYSICALDRIVE2
DriveLetter : E:
DiskModel : TOSHIBA External USB 3.0 USB Device
VolumeName : TOSHIBA EXT
Size : 320070832128
Partition : Disk #2, Partition #0
DiskSize : 1000202273280
RawSize : 734673240064
FreeSpace : 141853818880
Disk : \\.\PHYSICALDRIVE0
DriveLetter : D:
DiskModel : HGST HTS721010A9E630
VolumeName : Data
Size : 734673235968
Partition : Disk #0, Partition #0
PS:
See also PowerShell says "execution of scripts is disabled on this system."

Resources