Tech or Treat! Write an article about your scariest tech disaster to win gadgets!Learn more

x
?
Solved

Powershell script to get size of shares and freespace of volume

Posted on 2010-08-23
24
Medium Priority
?
5,045 Views
Last Modified: 2012-06-21
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
Comment
Question by:SSR-IS
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 6
  • 6
  • +2
24 Comments
 
LVL 42

Expert Comment

by:Meir Rivkin
ID: 33500105
can u post an example pf how the unc and shared folder is listed in the file?
0
 

Author Comment

by:SSR-IS
ID: 33500123
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
 
LVL 42

Expert Comment

by:Meir Rivkin
ID: 33500311
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:SSR-IS
ID: 33500437
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
 
LVL 42

Expert Comment

by:Meir Rivkin
ID: 33500490
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
 

Author Comment

by:SSR-IS
ID: 33500516
If it´s okay for you to do the coding I could wait a while!
0
 
LVL 42

Expert Comment

by:Meir Rivkin
ID: 33500551
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
 
LVL 13

Expert Comment

by:soostibi
ID: 33500592
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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 33500761

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
 

Author Comment

by:SSR-IS
ID: 33500836
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
 
LVL 42

Expert Comment

by:Meir Rivkin
ID: 33500924
@Chris-Dent

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

Author Comment

by:SSR-IS
ID: 33500932
@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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 33500954

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
 

Author Comment

by:SSR-IS
ID: 33501188
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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 33501321

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
 

Author Comment

by:SSR-IS
ID: 33501472
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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 33501501

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
 

Author Comment

by:SSR-IS
ID: 33508792
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
 
LVL 71

Accepted Solution

by:
Chris Dent earned 2000 total points
ID: 33508860

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
 

Author Comment

by:SSR-IS
ID: 33508918
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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 33508968
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
 

Author Comment

by:SSR-IS
ID: 33508984
So at least all my questions are answered and the results are great!
0
 
LVL 42

Expert Comment

by:Meir Rivkin
ID: 33509182
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
 
LVL 1

Expert Comment

by:jjoz
ID: 35799264
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A brief introduction to what I consider to be the best editor for PowerShell.
Previously, on our Nano Server Deployment series, we've created a new nano server image and deployed it on a physical server in part 2. Now we will go through configuration.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…

647 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question