[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 5225
  • Last Modified:

Powershell script to get size of shares and freespace of volume

I´m trying to build a powershell script, but I have definitely not enough know how about it. So maybe someone could help me with this or provide some information. What I want the script to do is the following:
I have an input-file with UNC-pathes to network shares on different servers. The script should use this file to get me the foldersize of the shares and also provide information about the freespace of the volume where the share exists.
An output like UNC - local Volume - total size - free space - sharesize would be perfect.
I´ve read and testet some scripts which I found here, but I can not get this to work...

At least this has not to be solved with powershell. If someone has a solution in VBS it would be fine also.

Any help would be welcome!

Regards
Steffen
0
SSR-IS
Asked:
SSR-IS
  • 10
  • 6
  • 6
  • +2
1 Solution
 
Meir RivkinFull stack Software EngineerCommented:
can u post an example pf how the unc and shared folder is listed in the file?
0
 
SSR-ISAuthor Commented:
Oh, at least it doesn´t matter how the input file should look like. The easiest for would be

\\server1\share1
\\server1\share2
\\server2\share1
...

But I could also provide an input-file without the backslashes...
0
 
Meir RivkinFull stack Software EngineerCommented:
the script reads from UNC_LIST_FILE (modify it in the script) and expect unc in the format you posted.
for example:

\\s004\temp

the output result is csv, for example:

UNC,FolderPath,FolderSize,DriveSize,DriveFreeSpace
s004,C:\temp,675.42124080658,152624.99609375,101631.92578125

all sizes are in MB.
const UNC_LIST_FILE = "c:\temp\shared_volume.txt"
const LOG_FILE = "c:\temp\output.log"

set objFSO = createobject("scripting.filesystemobject")
set objFile = objFSO.OpenTextFile(UNC_LIST_FILE, 1)

arrVolumes = Split(objFile.ReadAll, vbNewLine)
objFile.Close

set objLogFile = objFSO.CreateTextFile(LOG_FILE, 1)
objLogFile.WriteLine "UNC,FolderPath,FolderSize,DriveSize,DriveFreeSpace"

for each vol in arrVolumes
	
	Set objFolder = objFSO.GetFolder(vol)
	folderSize = (objFolder.Size/1048576)
	tokens = Split(vol, "\")
	name = tokens(UBound(tokens))
	server = tokens(UBound(tokens)-1)
	
	strLogLine = server
	
	Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & server & "\root\cimv2")
	Set colShares = objWMIService.ExecQuery("Select Path from Win32_Share where name = '" & name & "'")

	For each objShare in colShares
		strLogLine = strLogLine & "," & objShare.Path
		drive = Split(objShare.Path,":")(0)
		exit for
	Next

	strLogLine = strLogLine & "," & folderSize
	
	Set objWMIService = GetObject("winmgmts:\\" & server & "\root\cimv2")
	Set colItems = objWMIService.ExecQuery("Select FreeSpace,Size from Win32_LogicalDisk where Name='" & drive & ":'")
	For Each objItem in colItems
		size = (objItem.Size/1048576)
		freeSpace = (objItem.FreeSpace/1048576)
		
		strLogLine = strLogLine & "," & size
		strLogLine = strLogLine & "," & freeSpace
		exit for
	next
	
	objLogFile.WriteLine strLogLine
next

objLogFile.Close
wscript.echo "Done"

Open in new window

0
A Cyber Security RX to Protect Your Organization

Join us on December 13th for a webinar to learn how medical providers can defend against malware with a cyber security "Rx" that supports a healthy technology adoption plan for every healthcare organization.

 
SSR-ISAuthor Commented:
Thanks a lot, sedgwick! Yout Script runs really perfect for me!
Do you mind me asking you three more things?

Could we get the sizes in GB?
Could we get the output values seperated by semikolon instead of komma?

And another thing: Would it be a lot of work to get the results in an excel worksheet? Eventually written "live"? - But don´t spent to much time on this, I could even also import it there...

Regards
Steffen
0
 
Meir RivkinFull stack Software EngineerCommented:
now the script logs GB sizes, and use semikolon instead of comma.
regarding excel, it's gonna take sometime if you can wait...
const UNC_LIST_FILE = "c:\temp\shared_volume.txt"
const LOG_FILE = "c:\temp\output.log"

set objFSO = createobject("scripting.filesystemobject")
set objFile = objFSO.OpenTextFile(UNC_LIST_FILE, 1)

arrVolumes = Split(objFile.ReadAll, vbNewLine)
objFile.Close

set objLogFile = objFSO.CreateTextFile(LOG_FILE, 1)
objLogFile.WriteLine "UNC,FolderPath,FolderSize,DriveSize,DriveFreeSpace"

for each vol in arrVolumes
	
	Set objFolder = objFSO.GetFolder(vol)
	folderSize = (objFolder.Size/1073741824)
	tokens = Split(vol, "\")
	name = tokens(UBound(tokens))
	server = tokens(UBound(tokens)-1)
	
	strLogLine = server
	
	Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & server & "\root\cimv2")
	Set colShares = objWMIService.ExecQuery("Select Path from Win32_Share where name = '" & name & "'")

	For each objShare in colShares
		strLogLine = strLogLine & ";" & objShare.Path
		drive = Split(objShare.Path,":")(0)
		exit for
	Next

	strLogLine = strLogLine & ";" & folderSize
	
	Set objWMIService = GetObject("winmgmts:\\" & server & "\root\cimv2")
	Set colItems = objWMIService.ExecQuery("Select FreeSpace,Size from Win32_LogicalDisk where Name='" & drive & ":'")
	For Each objItem in colItems
		size = (objItem.Size/1073741824)
		freeSpace = (objItem.FreeSpace/1073741824)
		
		strLogLine = strLogLine & ";" & size
		strLogLine = strLogLine & ";" & freeSpace
		exit for
	next
	
	objLogFile.WriteLine strLogLine
next

objLogFile.Close
wscript.echo "Done"

Open in new window

0
 
SSR-ISAuthor Commented:
If it´s okay for you to do the coding I could wait a while!
0
 
Meir RivkinFull stack Software EngineerCommented:
here's output to excel.


const UNC_LIST_FILE = "c:\temp\shared_volume.txt"
const LOG_FILE = "c:\temp\output.log"
const OUTPUT_EXCEL_FILE = "c:\temp\Live.xlsx"
const SHEET_HEADERS = "UNC;FolderPath;FolderSize;DriveSize;DriveFreeSpace"

set objFSO = createobject("scripting.filesystemobject")
set objFile = objFSO.OpenTextFile(UNC_LIST_FILE, 1)

arrVolumes = Split(objFile.ReadAll, vbNewLine)
objFile.Close

Const xlExcel7 = 51

On Error Resume Next
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = false
 
If (Err.Number <> 0) Then
    On Error GoTo 0
    Wscript.Echo "Excel application not found."
    Wscript.Quit
End If
On Error GoTo 0

col=1
row=2

' Create a new workbook.
objExcel.Workbooks.Add

' Bind to worksheet.
Set objSheet = objExcel.ActiveWorkbook.Worksheets(1)

for each header in Split(SHEET_HEADERS,";")
	objSheet.Cells(1, col).Value = header
	col=col+1
next

for each vol in arrVolumes
	
	Set objFolder = objFSO.GetFolder(vol)
	folderSize = (objFolder.Size/1073741824)
	tokens = Split(vol, "\")
	name = tokens(UBound(tokens))
	server = tokens(UBound(tokens)-1)
	path=""	
	size=""
	freeSpace=""
	
	Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & server & "\root\cimv2")
	Set colShares = objWMIService.ExecQuery("Select Path from Win32_Share where name = '" & name & "'")

	For each objShare in colShares
		path = objShare.Path
		drive = Split(objShare.Path,":")(0)
		exit for
	Next
	
	Set objWMIService = GetObject("winmgmts:\\" & server & "\root\cimv2")
	Set colItems = objWMIService.ExecQuery("Select FreeSpace,Size from Win32_LogicalDisk where Name='" & drive & ":'")
	For Each objItem in colItems
		size = (objItem.Size/1073741824)
		freeSpace = (objItem.FreeSpace/1073741824)
		exit for
	next
	
	objSheet.Cells(row, 1).Value = server
	objSheet.Cells(row, 2).Value = path
	objSheet.Cells(row, 3).Value = folderSize
	objSheet.Cells(row, 4).Value = size
	objSheet.Cells(row, 5).Value = freeSpace

	row=row+1
next

objExcel.DisplayAlerts = False
objExcel.ActiveWorkbook.SaveAs OUTPUT_EXCEL_FILE, xlExcel7
objExcel.ActiveWorkbook.Close false

' Quit Excel.
objExcel.Application.Quit

Set objSheet = Nothing
Set objExcel = Nothing

Wscript.Echo "done."

Open in new window

0
 
soostibiCommented:
Let's try this PowerShell solution. This is raw data, we can format it to any format you like.
$shares = get-content c:\sharelist.txt # "\\server1\share1", "\\server2\share2"
$shares | %{
	if($_ -match "\\\\([^\\]+)\\(.+)$"){
		$server = $matches[1]
		$name = $Matches[2]
		$wmi = Get-WmiObject -ComputerName $server -Class Win32_Share -Filter "name = '$name'"
		$driveletter = if($wmi.path -match "^(\w:)"){$matches[1]}
		$drive = Get-WmiObject -ComputerName $server -Class Win32_logicaldisk -Filter "DeviceID = '$driveletter'"
		$sharesize = (Get-ChildItem $_ -Recurse -ErrorAction SilentlyContinue | ?{!$psiscontainer} | Measure-Object -Property length -Sum).sum
		New-Object -TypeName PSObject -Property @{UNC = $_; volume = $driveletter; size= $drive.size; freespace = $drive.freespace; sharesize = $sharesize}
	}
}

Open in new window

0
 
Chris DentPowerShell DeveloperCommented:

Just for fun... A PowerShell version.

All sizes are in Gb to two decimal places. Exports to a CSV file at the end, do yell if the comments aren't sufficient.

Chris
# Read the text file
Get-Content Test.txt | ForEach-Object {
  # Get the server name
  $Server = $_ -Replace '^\\\\|\\.*$'

  # Get the share
  $ShareName = $_ -Replace '^.*\\'
  $Share = [WMI]"\\$Server\root\cimv2:Win32_Share.Name='$Sharename'"

  # Get the disk
  $VolumeDeviceID = $Share.Path -Replace '\\.*$'
  $Volume = [WMI]"\\$Server\root\cimv2:Win32_LogicalDisk.DeviceID='$VolumeDeviceID'"

  # Build the output combining everything we found above
  "" | Select-Object `
    @{n='ServerName';e={ $Server }},
    @{n='ShareName';e={ $ShareName }},
    @{n='Path';e={ $Share.Path }},
    @{n='Volume';e={ $Volume.Name }},
    @{n='TotalSize';e={ '{0:N2}' -f ($Volume.Size / 1Gb) }},
    @{n='Freespace';e={ '{0:N2}' -f ($Volume.Freespace / 1Gb) }},
    @{n='ShareSize';e={ '{0:N2}' -f ((Get-ChildItem $_ -Recurse | Measure-Object Length -Sum).Sum / 1Gb) }}

# Export the results to a CSV file
} | Export-Csv File.csv -NoTypeInformation

Open in new window

0
 
SSR-ISAuthor Commented:
Thanks a lot guys!
You´re posting faster as I can test the scripts. But I´ll let you know when I managed to do so...
0
 
Meir RivkinFull stack Software EngineerCommented:
@Chris-Dent

i'm amazed everytime how many lines of code are required to perform a task in vbs as opposed to powershell.
0
 
SSR-ISAuthor Commented:
@Chris-Dent:
Something seems to be wrong with building ".sum". Please see my result:
"ServerName","ShareName","Path","Volume","TotalSize","Freespace","ShareSize"
"server01","share01","D:\share01","D:","54,15","9,58","0,01"
"server02","share01","I:\share01","I:","36,84","32,68","0,01"

The ShareSize is the same value for both, but on the server the second share is about 3 GB.
0
 
Chris DentPowerShell DeveloperCommented:

Apologies, I broke it :)

Fixed here.

Chris
# Read the text file
Get-Content Test.txt | ForEach-Object {
  # Get the server name
  $Server = $_ -Replace '^\\\\|\\.*$'

  # Get the share
  $ShareName = $_ -Replace '^.*\\'
  $Share = [WMI]"\\$Server\root\cimv2:Win32_Share.Name='$Sharename'"

  # Get the disk
  $VolumeDeviceID = $Share.Path -Replace '\\.*$'
  $Volume = [WMI]"\\$Server\root\cimv2:Win32_LogicalDisk.DeviceID='$VolumeDeviceID'"

  # Build the output combining everything we found above
  $_ | Select-Object `
    @{n='ServerName';e={ $Server }},
    @{n='ShareName';e={ $ShareName }},
    @{n='Path';e={ $Share.Path }},
    @{n='Volume';e={ $Volume.Name }},
    @{n='TotalSize';e={ '{0:N2}' -f ($Volume.Size / 1Gb) }},
    @{n='Freespace';e={ '{0:N2}' -f ($Volume.Freespace / 1Gb) }},
    @{n='ShareSize';e={ '{0:N2}' -f ((Get-ChildItem $_ -Recurse | Measure-Object Length -Sum).Sum / 1Gb) }}

# Export the results to a CSV file
} | Export-Csv File.csv -NoTypeInformation

Open in new window

0
 
SSR-ISAuthor Commented:
Okay, I´ll do some more testing, but for now I can say the following:
Sedgwick´s and Chris-Dent´s scripts are running both very smooth, with not a lot of differences if you want to work with the results in Excel.
It seems to me the the VBS-Solution runs a lot quicker than the powershell version:
VBS --> 6 seconds on the 3 GB testshare
PS --> 59 seconds on the 3 GB testshare

If I calculate this for 500 GB-shares.....
0
 
Chris DentPowerShell DeveloperCommented:

It's the bit that gets the folder size, we have to recurse down the folder structure if we use Get-ChildItem, counting all the files. We can use the same method as VbScript though.

You may find relatively small discrepancies in size, but it's worth a try :)

Chris
# Read the text file
Get-Content Test.txt | ForEach-Object {
  # Get the server name
  $Server = $_ -Replace '^\\\\|\\.*$'

  # Get the share
  $ShareName = $_ -Replace '^.*\\'
  $Share = [WMI]"\\$Server\root\cimv2:Win32_Share.Name='$Sharename'"

  # Get the disk
  $VolumeDeviceID = $Share.Path -Replace '\\.*$'
  $Volume = [WMI]"\\$Server\root\cimv2:Win32_LogicalDisk.DeviceID='$VolumeDeviceID'"

  # Build the output combining everything we found above
  $_ | Select-Object `
    @{n='ServerName';e={ $Server }},
    @{n='ShareName';e={ $ShareName }},
    @{n='Path';e={ $Share.Path }},
    @{n='Volume';e={ $Volume.Name }},
    @{n='TotalSize';e={ '{0:N2}' -f ($Volume.Size / 1Gb) }},
    @{n='Freespace';e={ '{0:N2}' -f ($Volume.Freespace / 1Gb) }},
    @{n='ShareSize';e={ '{0:N2}' -f ((New-Object -ComObject Scripting.FileSystemObject).GetFolder($_).Size / 1Gb) }}

# Export the results to a CSV file
} | Export-Csv File.csv -NoTypeInformation

Open in new window

0
 
SSR-ISAuthor Commented:
I understand the changes you made to use filesystem object, but the funny thing ist, that now the powershell script runs faster then vbs.
Maybe I have the opportunity to test the scripts on our larger shares (30 to 800 GB) tomorrow morning.
0
 
Chris DentPowerShell DeveloperCommented:

Good, that's the way it should be ;)

It's quite likely that the WMI pieces are where you get the speed improvement. In the case of mine we're connecting directly to a WMI resource rather than searching for it.

Chris
0
 
SSR-ISAuthor Commented:
Okay, I did some testing this morning on our larger shares and everthing worked fine. If yout time allows, there one more thing which would make the script perfect:
Is it possible to implement some kind of status/ progress bar? The script will run for al long time and it would be nice to know if its still alive...

Steffen
0
 
Chris DentPowerShell DeveloperCommented:

Sure! This uses Write-Progress.

Chris
# Read the text file
Get-Content Test.txt | ForEach-Object {

  Write-Progress -Activity "Scanning shares" -Status $_

  # Get the server name
  $Server = $_ -Replace '^\\\\|\\.*$'

  # Get the share
  $ShareName = $_ -Replace '^.*\\'
  $Share = [WMI]"\\$Server\root\cimv2:Win32_Share.Name='$Sharename'"

  # Get the disk
  $VolumeDeviceID = $Share.Path -Replace '\\.*$'
  $Volume = [WMI]"\\$Server\root\cimv2:Win32_LogicalDisk.DeviceID='$VolumeDeviceID'"

  # Build the output combining everything we found above
  $_ | Select-Object `
    @{n='ServerName';e={ $Server }},
    @{n='ShareName';e={ $ShareName }},
    @{n='Path';e={ $Share.Path }},
    @{n='Volume';e={ $Volume.Name }},
    @{n='TotalSize';e={ '{0:N2}' -f ($Volume.Size / 1Gb) }},
    @{n='Freespace';e={ '{0:N2}' -f ($Volume.Freespace / 1Gb) }},
    @{n='ShareSize';e={ '{0:N2}' -f ((New-Object -ComObject Scripting.FileSystemObject).GetFolder($_).Size / 1Gb) }}

# Export the results to a CSV file
} | Export-Csv File.csv -NoTypeInformation

Open in new window

0
 
SSR-ISAuthor Commented:
Thanks again - works nice and does anything I need!
I guess I should learn some powershell stuff, there´s a lot of things which can be done very elegant.

Can you recommend some books or so to get a good entry point?
0
 
Chris DentPowerShell DeveloperCommented:
Yeah, this is a good starting point:

http://powershell.com/Mastering-PowerShell.pdf

Once you start getting through that you can explore some of the resources listed here:

http://social.technet.microsoft.com/wiki/contents/articles/windows-powershell-survival-guide.aspx

And these physical books are highly regarded:

PowerShell Cookbook - http://oreilly.com/catalog/9780596801519
PowerShell in Action - http://www.manning.com/payette/

They have different focus, if you're looking at administrative work the Cookbook may be the best bet (just make sure you get the new edition, 2nd edition).

Chris
0
 
SSR-ISAuthor Commented:
So at least all my questions are answered and the results are great!
0
 
Meir RivkinFull stack Software EngineerCommented:
that's a whole new "project" and not really in this scope.
i've found something that create dynamically htmlfile object and update it but it needs major modification.
check http://www.computing.net/answers/programming/vbscript-show-progress/14186.html

i think you should open new question for it, i'd happily assist you if it wasn't like this.
sorry man.
0
 
jjozCommented:
Hi, is it possible to modify the script just to type the server name only and then get all of the network shares recursively then pipe that output to the script above ?
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

  • 10
  • 6
  • 6
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now