Link to home
Start Free TrialLog in
Avatar of SSR-IS
SSR-ISFlag for Germany

asked on

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
Avatar of Meir Rivkin
Meir Rivkin
Flag of Israel image

can u post an example pf how the unc and shared folder is listed in the file?
Avatar of SSR-IS

ASKER

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...
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

Avatar of SSR-IS

ASKER

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
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

Avatar of SSR-IS

ASKER

If it´s okay for you to do the coding I could wait a while!
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

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


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

Avatar of SSR-IS

ASKER

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...
@Chris-Dent

i'm amazed everytime how many lines of code are required to perform a task in vbs as opposed to powershell.
Avatar of SSR-IS

ASKER

@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.

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

Avatar of SSR-IS

ASKER

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.....

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

Avatar of SSR-IS

ASKER

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.

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
Avatar of SSR-IS

ASKER

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
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of SSR-IS

ASKER

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?
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
Avatar of SSR-IS

ASKER

So at least all my questions are answered and the results are great!
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.
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 ?