Retrieving disk capacity with powershell - powershell

I made this code to count disk capacity, but when i run it with only the SSD in my laptop i get 0GB. after I insert USB/external space it count the ssd + the USB.
$disk = Get-WmiObject Win32_DiskDrive
$capacity = 0;
for($i = 0;$i -lt $disk.Count; $i++){
$capacity = $capacity + [math]::round(($disk[$i].Size/1GB),2)
}
Write-Host $capacity "GB"
This works fine -> $disk.Size
Why does it not take the first [0] in my for loop?

I cannot answer why your for loop is failing without observing your environment, but there is almost never a use-case for it. You should instead opt for a foreach loop:
$capacity = foreach ($disk in Get-WmiObject -Class Win32_DiskDrive)
{
[Math]::Round(($disk.Size / 1GB), 2)
}
"$(($capacity | Measure-Object -Sum).Sum)GB"

Assuming Windows 10 since you didn't mention OS and the CMDLETS in Windows 10 are so much better. *See at the bottom for a Windows 7 version.
For disk information, I prefer using Get-PhysicalDisk, like this for example:
$DiskInfo = foreach ($disk in Get-PhysicalDisk) {
[string]$name = $disk.FriendlyName
[string]$type = $disk.MediaType
[int]$capacity = $disk.size / 1GB
[pscustomobject]#{
"Type"=$type;
"Name"=$name;
"Capacity (GB)"=$capacity;
}
}
$DiskInfo
In my environement where I have one SSD and one mechanical HDD, it will return:
Name Type Capacity (GB)
---- ---- -------------
SAMSUNG MZ7TY256HDHP-000L7 SSD 238
ST500LX025-1U717D HDD 466
If you wanted information for JUST the SSD for example, you could do this :
$DiskInfo = foreach ($disk in Get-PhysicalDisk | Where-Object {$_.MediaType -eq "SSD"} ) {
[string]$name = $disk.FriendlyName
[string]$type = $disk.MediaType
[int]$capacity = $disk.size / 1GB
[pscustomobject]#{
"Type"=$type;
"Name"=$name;
"Capacity (GB)"=$capacity;
}
}
$DiskInfo
Which returns only the SSD:
Type Name Capacity (GB)
---- ---- -------------
SSD SAMSUNG MZ7TY256HDHP-000L7 238
Explanation: Foreach disk connected, store name, media type and capacity in variables. *Divide byte capacity by 1GB to get a better number to look at.
Still in the Foreach, create a custom object at every iteration containing the 3 variables.
All put together, you can then output your variable DiskInfo which contains all the objects.
If on Windows 7, media type isn't available so you can't use it. Instead you can do:
$DiskInfo = foreach ($disk in Get-WmiObject -Class Win32_DiskDrive) {
[string]$name = $disk.model
[int]$capacity = $disk.size / 1GB
[pscustomobject]#{
"Name"=$name;
"Capacity (GB)"=$capacity;
}
}
$DiskInfo
Which will return something like:
Name Capacity (GB)
---- -------------
SAMSUNG MZ7TY256HDHP-000L7 238
ST500LX025-1U717D 466

Related

Get Column values from text file

Below is the text file data I have
Disk ### Status Size Free Dyn Gpt
-------- ------------- ------- ------- --- ---
Disk 0 Online 100 GB 1024 KB
Disk 1 Online 6144 MB 1024 KB
Disk 2 Online 200 GB 1024 KB
Disk 3 Online 10 GB 1024 KB
I want to put this data in csv like below, removing the last 2 columns and adding the server value
server Disk ### Status Size Free
------ -------- ------------- ------- -------
s1 Disk 0 Online 100 GB 1024 KB
s1 Disk 1 Online 6144 MB 1024 KB
s1 Disk 2 Online 200 GB 1024 KB
s1 Disk 3 Online 10 GB 1024 KB
below is the code
$list = Get-Content -Path "C:\server.txt"
foreach($server in $list)
{
$diskpart = cmd /c 'echo list disk | diskpart'
}
$Lines = $diskpart
$Out = $False
$Line=#()
ForEach ($Line In $Lines)
{
If ($Line -match 'DISKPART>')
{
$Out = $False
}
If ($Out -eq $True)
{
$Line | Out-File "C:\d.txt" -Append
}
If ($Line -match 'DISKPART>')
{
$Out = $True
}
}
$data = Import-Csv -Path C:\d.txt
I tried reading line using foreach,but getting output with headers and ---
Disk ### Status Size Free Dyn Gpt
---------------------------------------------------
Disk 0 Online 100 GB 1024 KB
Please let me know how can I extract columns from text file and append the servername to it. Need some idea to do this
One way of converting this into a CSV file is like below.
Assuming you have the output from diskpart in a string array $lines and the current server is called 's1' :
$result = switch -Regex ($lines) {
'^\s*Disk \d' {
$disk,$status,$size,$free = $_.Trim() -split '\s{2,}'
[PsCustomObject]#{
'Server' = $server # 's1' in this example
'Disk ###' = $disk
'Status' = $status
'Size' = $size
'Free' = $free
}
}
}
# output on console screen
$result | Format-Table -AutoSize
# output to CSV file
$result | Export-Csv -Path 'C:\diskinfo.csv' -NoTypeInformation
Result on screen:
Server Disk ### Status Size Free
------ -------- ------ ---- ----
s1 Disk 0 Online 100 GB 1024 KB
s1 Disk 1 Online 6144 MB 1024 KB
s1 Disk 2 Online 200 GB 1024 KB
s1 Disk 3 Online 10 GB 1024 KB
P.S. It is strongly not recommended to use Out-File to build a CSV file. Use that only if other options are not available. To create CSV use Export-Csv
If you need to do this on a series of computers, you might use this:
$list = Get-Content -Path "C:\server.txt"
# parameter -ComputerName can handle an array of computer names at once
$lines = Invoke-Command -ComputerName $list -ScriptBlock { "list disk" | diskpart }
$result = switch -Regex ($lines) {
'^On computer: (\w+)' { $server = $Matches[1].Trim() }
'^\s*Disk \d' {
$disk,$status,$size,$free = $_.Trim() -split '\s{2,}'
[PsCustomObject]#{
'Server' = $server
'Disk ###' = $disk
'Status' = $status
'Size' = $size
'Free' = $free
}
}
}
# output on console screen
$result | Format-Table -AutoSize
# output to CSV file
$result | Export-Csv -Path 'C:\diskinfo.csv' -NoTypeInformation

powershell script for finding the total memory space of c drive

I want a PowerShell script to get the total memory space of C drive and used memory space in GB, if the total space is less than 200 GB it should print disk space is less than 200.
gwmi win32_logicaldisk | Format-Table DeviceId, MediaType, #{n="Size";e={[math]::Round($_.Size/1GB,2)}},#{n="FreeSpace";e={[math]::Round($_.FreeSpace/1GB,2)}}
$task=gwmi win32_logicaldisk | Format-Table DeviceId, MediaType, #{n="Size";e={[math]::Round($_.Size/1GB,2)}},#{n="FreeSpace";e={[math]::Round($_.FreeSpace/1GB,2)}}
if($task.Size -lt 200)
{
Write-Host "Hard Disk Space is less than 200."
}
else
{
Write-Host "Hard Disk Space is greater than 200."
}
I am getting all drive space on the above code, I need only C drive information and if condition is not working properly,Some one help me through this. Thanks in advance
You can use the Get-Volume cmdlet -
if (((Get-Volume -DriveLetter C).Size)/1GB -lt 200)
{
Write-Host "Hard Disk Space is less than 200."
}
else
{
Write-Host "Hard Disk Space is greater than 200."
}
if you need to run this test on win7 - even with ps5.1 - you can't use the Get-Volume cmdlet. [sigh ...] so here is one that uses CMI/WMI for that.
what it does ...
sets a min free space threshold
uses the faster, non-deprecated CIM stuff to get the info on drive C:
only returns info if the C: drive meets the min freespace requirement
uses [string]::IsNullOrEmpty() to see if the result has any info in it
then uses an IF structure to decide what message to show
if space is too low, it uses the Write-Warning cmdlet for the nice orange text [grin]
here's the code ...
$MinFreeSpace_GB = 800
$CDriveMinFree = [string]::IsNullOrEmpty((Get-CimInstance -ClassName CIM_LogicalDisk |
Where-Object {
$_.DeviceID -eq 'C:' -and
$_.FreeSpace -lt $MinFreeSpace_GB * 1GB
}))
if ($CDriveMinFree)
{
'The C: drive has at least {0} GB free.' -f $MinFreeSpace_GB
}
else
{
Write-Warning ('Low free space on Drive C:!')
}
output on my 600 GB free C: drive with the test threshold set to 800 ...
WARNING: Low free space on Drive C:!

How to Get Actual Hard Disk Memory of A VM?

Is it possible to get the actual hard disk usage of a virtual machine?
Measure-VM -Name * | select-object -property TotalDiskAllocation
The TotalDiskAllocation property gets the total disk space assigned to the VM and even though this is helpful I also need to know how much is really being used.
For example, if a VM has 150 GB of allocated memory and it only uses 50 GB, is there any Powershell command that will be able to extract the 50 GB? If yes, how will I be able to incorporate that script to the script above?
Based on your attempt to use Measure-VM, I assumed you are using Hyper-V. I use something similar to this in one of my Hyper-V scripts:
(Get-VM dechiro1).HardDrives | ForEach {
$GetVhd = Get-VHD -Path $_.Path
[pscustomobject]#{
Name = $_.Name
Type = $GetVhd.VhdType
ProvisionedGB = ($GetVhd.Size / 1GB)
CommittedGB = ($GetVhd.FileSize / 1GB)
}
}
Basically, for each of the virtual machine's hard drives, use Get-VHD to get the VHD details which includes the full size and what I refer to as the committed size (actual space on disk).
Example output:
Name Type ProvisionedGB CommittedGB
---- ---- ------------- -----------
Hard Drive on IDE controll... Dynamic 20 0.00390625
Hard Drive on IDE controll... Dynamic 40 0.00390625
Edit:
If you wanted to pull from every VM and include the VM name with the returned object and you prefer to use the pipeline form, this will work:
Get-VM | ForEach { $Vm = $_; $_.HardDrives } | ForEach {
$GetVhd = Get-VHD -Path $_.Path
[pscustomobject]#{
Vm = $Vm.Name
Name = $_.Name
Type = $GetVhd.VhdType
ProvisionedGB = ($GetVhd.Size / 1GB)
CommittedGB = ($GetVhd.FileSize / 1GB)
}
}

Powershell Multidimensional associative table

Greatings, I'm trying to extract WMI informations with Powershell in order to push them in a Mysql DB via PHP.
If a machine has no access to the internet, I export an XML file (that is working).
$filePath = $PSScriptRoot + '\processors.xml'
$XmlWriter = New-Object System.XMl.XmlTextWriter($filePath,$Null)
$processor = Get-WmiObject Win32_Processor
$xmlWriter.WriteStartElement("Processor")
foreach ($item in $processor){
$xmlWriter.WriteStartElement($item.DeviceID)
$xmlWriter.WriteElementString("Name",$item.Name)
$xmlWriter.WriteElementString("AddressWidth",$item.AddressWidth)
$xmlWriter.WriteElementString("NumberOfCores",$item.NumberOfCores)
$xmlWriter.WriteElementString("NumberOfLogicalProcessors",$item.NumberOfLogicalProcessors)
$xmlWriter.WriteElementString("L2CacheSize",$item.L2CacheSize)
$xmlWriter.WriteElementString("L3CacheSize",$item.L3CacheSize)
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement()
$xmlWriter.Finalize
$xmlWriter.Flush()
$xmlWriter.Close()
But if a machine has access to the internet, I prefer to push informations directly to a page, via HTTP POST, which will verify informations and store them in the DB.
Here is my problem, as I don't know the number of items (here processors but imagine with memories, hard drives... etc.) I use a foreach statement to create the XML file (and it works) but, I don't know how to create the equivalent structure to create and fill a multi dimensionnal arry $postprocessor that stores CPUs informations. I have tried the following code but I'm stuck (that is not working) :
$processor = Get-WmiObject Win32_Processor
$postprocessor = #()
foreach ($item in $processor){
$itemarr = #()
$itemarr += 'Name="'+$item.Name+'"'
$itemarr += 'AddressWidth="'+$item.AddressWidth+'"'
$itemarr += 'NumberOfCores="'+$item.NumberOfCores+'"'
$itemarr += 'NumberOfLogicalProcessors="'+$item.NumberOfLogicalProcessors+'"'
$itemarr += 'L2CacheSize="'+$item.L2CacheSize+'"'
$itemarr += 'L3CacheSize="'+$item.L3CacheSize+'"'
$postprocessor.Add($item.DeviceID+'='+$itemarr)
# write-host $itemarr
Remove-Variable itemarr
}
$postParams = $postprocessor
$sending = Invoke-WebRequest -Uri http://localhost:8080/wmi/test.php -Method POST -Body $postParams
In fact I just wanted to store those informations like this :
$postParam[]
$postProcessors[]
->Processor1[]
->Name = value
...
->L3Cachesize = value
->Processor2[]
->Name = value
...
->L3Cachesize = value
postMemories[...]
postHardDrives[...]
etc
Maybe I have not found previous answer that solve my problem, if it is the case excuse me by advance and I'll be glad to read as many links that you'll send to me.
Best
What you'd probably need is a dictionary and not an array of arrays.
$processor = Get-WmiObject Win32_Processor
$postprocessor = #{}
foreach ($item in $processor){
$itemHash = #{
Name = $item.Name
AddressWidth = $item.AddressWidth
NumberOfCores = $item.NumberOfCores
NumberOfLogicalProcessors = $item.NumberOfLogicalProcessors
L2CacheSize = $item.L2CacheSize
L3CacheSize = $item.L3CacheSize
}
$postprocessor.Add($item.DeviceID, $itemHash)
}
$postParams = $postprocessor
This is what I see in the output.
PS C:\> $postprocessor
Name Value
---- -----
CPU0 {Name, NumberOfCores, AddressWidth, NumberOfLogicalProcessors...}
PS C:\> $postprocessor["cpu0"]
Name Value
---- -----
Name Intel(R) Core(TM) i7-3630QM CPU # 2.40GHz
NumberOfCores 4
AddressWidth 64
NumberOfLogicalProcessors 8
L2CacheSize 1024
L3CacheSize 6144
PS C:\> ConvertTo-Json -InputObject $postprocessor
{
"CPU0": {
"Name": "Intel(R) Core(TM) i7-3630QM CPU # 2.40GHz",
"NumberOfCores": 4,
"AddressWidth": 64,
"NumberOfLogicalProcessors": 8,
"L2CacheSize": 1024,
"L3CacheSize": 6144
}
}

Unable to retrieve physical size of available storage for cluster

I am half way down with my work and now stuck.
I am trying to fetch information about available storage devices for a cluster.
I am able to fetch the list of available storage devices but unable to retrieve the physical disk, available free space, etc of these available storage.
I want like this. Is there any command to fetch physical disk name from Cluster Disk Name or directly can I get the disk details.
For Shared Disk I am able to retrieve the details (Get-ClusterSharedVolume) but not for a non-shared disk.
I want powershell or WMI script for doing so.
You can get this information from WMI, but it takes a couple steps:
$resources = Get-WmiObject -namespace root\MSCluster MSCluster_Resource -filter "Type='Physical Disk'"
$resources | foreach {
$res = $_
$disks = $res.GetRelated("MSCluster_Disk")
$disks | foreach {
$_.GetRelated("MSCluster_DiskPartition") |
select #{N="Name"; E={$res.Name}}, #{N="Status"; E={$res.State}}, Path, VolumeLabel, TotalSize, FreeSpace
}
} | ft
That will give you output like the following:
Name Status Path VolumeLabel TotalSize FreeSpace
---- ------ ---- ----------- --------- ---------
Cluster Disk 2 2 K: New Volume 5220 5163
SQL - FAS3070 SiteB 2 S: MC_SQL 5597 5455
SM Test 2 M: SM Test 1024 992
DTC - FAS3070B 2 F: MC_WITNESS 5346 5289
Cluster Disk Witness 2 E: New Volume 5322 5267
Cluster Disk 1 2 G: MC_DTC 5088 5035
Cluster Disk 3 2 T: SQL 5119 4999
If you don't care about the resource name/status you can skip those steps and jump straight to the partition (and it'll run much quicker):
gwmi -namespace root\MSCluster MSCluster_DiskPartition | ft Path, VolumeLabel, TotalSize, FreeSpace
Edit: Note that the size is in MB and a Status of "2" means that the disk is online.
you can use wmi like this:
Get-WMIObject Win32_LogicalDisk -filter "DriveType=3" | Select DeviceID, FreeSpace
throw in a computername parameter if you wish to do it remotely
HTH,
Matt
PS. for a more readable report you can try this:
Get-WMIObject Win32_LogicalDisk -filter "DriveType=3" |
Select DeviceID, #{Name = "Free Space (%)" ; Expression= {[int] ($_.FreeSpace / $_.Size* 100)}},#{Name = "Free Space (GB)"; Expression = {[int]($_.Freespace / 1GB)}}, #{Name = "Size (GB)"; Expression = {[int]($_.Freespace / 1GB)}}