beaconlightboy
asked on
WMI and Directory Sizes
ok, i have been searching forever trying to find the wmi code that will successfully give me the directory sizes. i found this code in ex A below, on this site. It works.
The code in Sample B does not returns only nulls, but works otherwise. example b code my have a few typos in it as i had made changes since i posted it. but you'll get the drift. i want to know why A works and B does not. i'd pay 1000 points if i could to know this answer.
EXAMPLE A
========================== ========== ========== ========== ========== ========== ========== ======
Public Shared Function GetDrives(ByVal RemotePc As String) As ArrayList
Dim P As String = "\\" & RemotePc & "\root\cimv2:"
Dim MyManagementClass As Management.ManagementClass = New Management.ManagementClass (P & "Win32_ComputerSystem")
Dim MyManagementObjectCollecti on As System.Management.Manageme ntObjectCo llection
Dim MyDrives As New ArrayList
Try
MyManagementClass.Path.Rel ativePath = "Win32_LogicalDisk"
MyManagementObjectCollecti on = MyManagementClass.GetInsta nces()
For Each obj As Management.ManagementObjec t In MyManagementObjectCollecti on
Dim MyDrive As New System.Text.StringBuilder
MyDrive.Append(obj("Descri ption"))
MyDrive.Append(obj("Size") )
MyDrives.Add(MyDrive.ToStr ing)
Next
Catch e As Exception
Finally
If Not MyManagementObjectCollecti on Is Nothing Then
MyManagementObjectCollecti on.Dispose ()
End If
If Not MyManagementClass Is Nothing Then
MyManagementClass.Dispose( )
End If
End Try
Return MyDrives
End Function
========================== ========== ========== ======
EXAMPLE B - not all the code is here, but a snippet that should show the logic
========================== ========== ========== ======
WMI related objects
Dim ManScope As New Management.ManagementScope
Dim ManScopePath As New Management.ManagementPath
Dim ManOptions As New Management.ConnectionOptio ns
Dim ManObject As New Management.ManagementObjec t
Dim ManCollection As Management.ManagementObjec tCollectio n
Dim ManObjectSearcher As New Management.ManagementObjec tSearcher
'
'SQL related objects
Dim SQLCommand As New SqlClient.SqlCommand
Dim SQLDataAdapter As New SqlClient.SqlDataAdapter
Dim SQLMonitoredServersDataSet As New DataSet
Dim SQLMonitoredServersDataSet Record As DataRow
'declaring parameters needed to save records
Dim ServerIDPar As New SqlClient.SqlParameter
'
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
'Setting sql command properties
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
SQLCommand.Connection = SQLConnection
SQLCommand.CommandType = CommandType.StoredProcedur e
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
'Populating tables we will need for this procedure
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
'
SQLCommand.Parameters.Add( ServerIDPa r)
SQLCommand.Parameters.Add( ServerSize Par)
ServerIDPar.ParameterName = "@ServerID"
ServerSizePar.ParameterNam e = "@Size"
ServerIDPar.Value = ServerID
SQLCommand.CommandText = "MonitoredServices_Query"
SQLDataAdapter.SelectComma nd = SQLCommand
SQLDataAdapter.Fill(SQLMon itoredServ ersDataSet )
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
'Setup the WMI variables needed to collec the information we want to gather
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
ManOptions.Authentication = AuthenticationLevel.Packet
ManOptions.Impersonation = ImpersonationLevel.Imperso nate
'
ManScopePath.Path = "\\" & ServerName & "\root\CIMV2"
ManScope.Path = ManScopePath
ManScope.Connect()
'
ManObjectSearcher.Scope = ManScope
'
If SQLMonitoredServersDataSet .Tables(0) .Rows.Coun t <> 0 Then
SubProgressBarIncrement = 100 / SQLMonitoredServersDataSet .Tables(0) .Rows.Coun t
For Each SQLMonitoredServersDataSet Record In SQLMonitoredServersDataSet .Tables(0) .Rows
ManObjectSearcher.Query.Qu eryString = "Select * from Win32_Directory where path = " & VBQuote & SQLMonitoredServersDataSet Record.Ite m(0) & VBQuote
ManCollection = ManObjectSearcher.Get
For Each ManObject In ManCollection
ServerIDPar.value = ServerID
ServiceSizePar.Value = ManObject.GetPropertyValue ("Size")
Next
'
SQLCommand.CommandText = "Win32_Server_Insert"
SQLCommand.ExecuteNonQuery ()
Me.StatusBar.Panels("SubPr ogressBar" ).Progress BarInfo.Va lue = Me.StatusBar.Panels("SubPr ogressBar" ).Progress BarInfo.Va lue + SubProgressBarIncrement
Me.StatusBar.Refresh()
Next
End If
'------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
The code in Sample B does not returns only nulls, but works otherwise. example b code my have a few typos in it as i had made changes since i posted it. but you'll get the drift. i want to know why A works and B does not. i'd pay 1000 points if i could to know this answer.
EXAMPLE A
==========================
Public Shared Function GetDrives(ByVal RemotePc As String) As ArrayList
Dim P As String = "\\" & RemotePc & "\root\cimv2:"
Dim MyManagementClass As Management.ManagementClass
Dim MyManagementObjectCollecti
Dim MyDrives As New ArrayList
Try
MyManagementClass.Path.Rel
MyManagementObjectCollecti
For Each obj As Management.ManagementObjec
Dim MyDrive As New System.Text.StringBuilder
MyDrive.Append(obj("Descri
MyDrive.Append(obj("Size")
MyDrives.Add(MyDrive.ToStr
Next
Catch e As Exception
Finally
If Not MyManagementObjectCollecti
MyManagementObjectCollecti
End If
If Not MyManagementClass Is Nothing Then
MyManagementClass.Dispose(
End If
End Try
Return MyDrives
End Function
==========================
EXAMPLE B - not all the code is here, but a snippet that should show the logic
==========================
WMI related objects
Dim ManScope As New Management.ManagementScope
Dim ManScopePath As New Management.ManagementPath
Dim ManOptions As New Management.ConnectionOptio
Dim ManObject As New Management.ManagementObjec
Dim ManCollection As Management.ManagementObjec
Dim ManObjectSearcher As New Management.ManagementObjec
'
'SQL related objects
Dim SQLCommand As New SqlClient.SqlCommand
Dim SQLDataAdapter As New SqlClient.SqlDataAdapter
Dim SQLMonitoredServersDataSet
Dim SQLMonitoredServersDataSet
'declaring parameters needed to save records
Dim ServerIDPar As New SqlClient.SqlParameter
'
'-------------------------
'-------------------------
'Setting sql command properties
'-------------------------
SQLCommand.Connection = SQLConnection
SQLCommand.CommandType = CommandType.StoredProcedur
'-------------------------
'-------------------------
'Populating tables we will need for this procedure
'-------------------------
'
SQLCommand.Parameters.Add(
SQLCommand.Parameters.Add(
ServerIDPar.ParameterName = "@ServerID"
ServerSizePar.ParameterNam
ServerIDPar.Value = ServerID
SQLCommand.CommandText = "MonitoredServices_Query"
SQLDataAdapter.SelectComma
SQLDataAdapter.Fill(SQLMon
'-------------------------
'-------------------------
'Setup the WMI variables needed to collec the information we want to gather
'-------------------------
ManOptions.Authentication = AuthenticationLevel.Packet
ManOptions.Impersonation = ImpersonationLevel.Imperso
'
ManScopePath.Path = "\\" & ServerName & "\root\CIMV2"
ManScope.Path = ManScopePath
ManScope.Connect()
'
ManObjectSearcher.Scope = ManScope
'
If SQLMonitoredServersDataSet
SubProgressBarIncrement = 100 / SQLMonitoredServersDataSet
For Each SQLMonitoredServersDataSet
ManObjectSearcher.Query.Qu
ManCollection = ManObjectSearcher.Get
For Each ManObject In ManCollection
ServerIDPar.value = ServerID
ServiceSizePar.Value = ManObject.GetPropertyValue
Next
'
SQLCommand.CommandText = "Win32_Server_Insert"
SQLCommand.ExecuteNonQuery
Me.StatusBar.Panels("SubPr
Me.StatusBar.Refresh()
Next
End If
'-------------------------
ASKER
the table actuall stores the path with double back slashes. i did notice however that the code in A is actually using win32_logicaldisk and i am trying to use win32_directory. so i am kinda comparing apples to oranges. i am going to modify example A to use win32_directory. i bet it wont work when i do that though.
I noticed that too, and did some research on Win32_Directory. I saw an example using it to pull directory info, thus appeared they were relatively similar in functionality. I'd be interested in your findings.
What is it that attracts you to using Example B? Maybe we can tweak Example A to meet your needs.
What is it that attracts you to using Example B? Maybe we can tweak Example A to meet your needs.
ASKER
I have never written code to use example A. i have always used example B, as that is how microsoft examples are. i can honestly say that i have no idea what the difference between the two is. My B example, while "bloated", is easy to follow and is not any less effecient than A. the trick now is to see if i can get win32_directory to return a value. if i can't then the whole purpose behind it is in my mind, and to be politically incorrect.. retarded.
No problem. I'm with you. I did find this code that uses the same query call and does calculate the size of the folders (listed below). I tested this and it actually returned the directory sizes. However, it has to go and sum up the size of each file. What this tells me (and also with some additional testing) is that win32_directory cannot tell us the size of the folder (unlike win32_logicaldisk).
Here's the script that I found and it did in fact return the directory sizes. Again, I'm not in favor of this method since it does have to query each file object.
'This script accompanies the book Windows Management Instrumentation
'by Matthew Lavy and Ashley Meggitt (New Riders, 2001)
'The code is copyright 2001, Matthew Lavy & Ashley Meggitt
'You are free to use and modify the script at will
'provided you understand that all code here is made available AS IS, with
'NO WARRANTY WHATSOEVER. The authors take NO RESPONSIBILITY AT ALL for
'problems that result from the use of this script or any part thereof
'dirsize.vbs - prints the size of all directories on a system
Option Explicit
Dim refWMIService
Dim strDirName
Dim refDirectory
'put the name of the directory you wish to find the size of here
strDirName="c:\program files"
'get reference to WMI. Also get a direct reference to the directory
'we want to know about
set refWMIService = GetObject("winMgmts:")
set refDirectory = GetObject("winMgmts:Win32_ Directory= '" & strDirName & "'")
'fire our recursive function and display results
WScript.echo "Size of " & strDirName & " is " & _
getDirectorySize(refDirect ory) & " bytes."
'clean up
set refDirectory = Nothing
set refWMIService = Nothing
'------- End of script --------
'This function returns the aggregated size
'of all files in a directory and its subdirectories
Function getDirectorySize(pCurrentD ir)
Dim numFSize
Dim numDSize
Dim strQuery
Dim refItem
Dim colFiles
Dim colSubdirs
numFSize = 0
numDSize = 0
'first get a reference to all files in the directory
strQuery = "ASSOCIATORS OF {Win32_Directory='" & _
pCurrentDir.Name & "'} WHERE " & _
"AssocClass=CIM_DirectoryC ontainsFil e " & _
"Role=GroupComponent ResultRole=PartComponent"
set colFiles = refWMIService.ExecQuery(st rQuery)
'loop through each file and add the size of each to numFSize
For Each refItem In colFiles
numFSize = numFSize + refItem.FileSize
Next
set colFiles = Nothing
'now get a reference to all the subdirectories
strQuery = "ASSOCIATORS OF {Win32_Directory='" & _
pCurrentDir.Name & "'} WHERE " & _
"AssocClass=Win32_SubDirec tory " & _
"ResultRole=PartComponent"
set colSubDirs = refWMIService.ExecQuery(st rQuery)
'loop through each subdirectory, and add its
'size to numDSize by recursively calling this function
For Each refItem in colSubDirs
numDSize = numDSize + getDirectorySize(refItem)
Next
set colSubdirs = Nothing
'finally, print stats and return the total size
WScript.echo pCurrentDir.Name & ": " & numFSize & _
" bytes in files - " & numDSize & _
" bytes in subdirs"
getDirectorySize = numFSize + numDSize
End Function
-------------------------- ---------- ---------- ---------- ---------- ---------- --
I also tried this code to see if in fact the win32_directory object can return the size:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colFolders = objWMIService. _
ExecQuery("Select * From Win32_Directory Where Name = 'C:\\MyFolder'")
For Each objFolder in colFolders
Wscript.Echo "Size: " & objFolder.Size
Next
But it returned an error, validating that the win32_directory object in fact cannot return the size.
I'm hoping some of this helps, but I'll continue to look for things.
Here's the script that I found and it did in fact return the directory sizes. Again, I'm not in favor of this method since it does have to query each file object.
'This script accompanies the book Windows Management Instrumentation
'by Matthew Lavy and Ashley Meggitt (New Riders, 2001)
'The code is copyright 2001, Matthew Lavy & Ashley Meggitt
'You are free to use and modify the script at will
'provided you understand that all code here is made available AS IS, with
'NO WARRANTY WHATSOEVER. The authors take NO RESPONSIBILITY AT ALL for
'problems that result from the use of this script or any part thereof
'dirsize.vbs - prints the size of all directories on a system
Option Explicit
Dim refWMIService
Dim strDirName
Dim refDirectory
'put the name of the directory you wish to find the size of here
strDirName="c:\program files"
'get reference to WMI. Also get a direct reference to the directory
'we want to know about
set refWMIService = GetObject("winMgmts:")
set refDirectory = GetObject("winMgmts:Win32_
'fire our recursive function and display results
WScript.echo "Size of " & strDirName & " is " & _
getDirectorySize(refDirect
'clean up
set refDirectory = Nothing
set refWMIService = Nothing
'------- End of script --------
'This function returns the aggregated size
'of all files in a directory and its subdirectories
Function getDirectorySize(pCurrentD
Dim numFSize
Dim numDSize
Dim strQuery
Dim refItem
Dim colFiles
Dim colSubdirs
numFSize = 0
numDSize = 0
'first get a reference to all files in the directory
strQuery = "ASSOCIATORS OF {Win32_Directory='" & _
pCurrentDir.Name & "'} WHERE " & _
"AssocClass=CIM_DirectoryC
"Role=GroupComponent ResultRole=PartComponent"
set colFiles = refWMIService.ExecQuery(st
'loop through each file and add the size of each to numFSize
For Each refItem In colFiles
numFSize = numFSize + refItem.FileSize
Next
set colFiles = Nothing
'now get a reference to all the subdirectories
strQuery = "ASSOCIATORS OF {Win32_Directory='" & _
pCurrentDir.Name & "'} WHERE " & _
"AssocClass=Win32_SubDirec
"ResultRole=PartComponent"
set colSubDirs = refWMIService.ExecQuery(st
'loop through each subdirectory, and add its
'size to numDSize by recursively calling this function
For Each refItem in colSubDirs
numDSize = numDSize + getDirectorySize(refItem)
Next
set colSubdirs = Nothing
'finally, print stats and return the total size
WScript.echo pCurrentDir.Name & ": " & numFSize & _
" bytes in files - " & numDSize & _
" bytes in subdirs"
getDirectorySize = numFSize + numDSize
End Function
--------------------------
I also tried this code to see if in fact the win32_directory object can return the size:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colFolders = objWMIService. _
ExecQuery("Select * From Win32_Directory Where Name = 'C:\\MyFolder'")
For Each objFolder in colFolders
Wscript.Echo "Size: " & objFolder.Size
Next
But it returned an error, validating that the win32_directory object in fact cannot return the size.
I'm hoping some of this helps, but I'll continue to look for things.
On a totally different wavelength, you can use the FSO and specify a UNC path name.
path="\\remotePC\c$\Direct ory1"
Dim fso, F
Set fso = CreateObject("Scripting.Fi leSystemOb ject")
Set f = fso.GetFolder(path)
MsgBox (f.Size)
Just trying to find ideas for you.
path="\\remotePC\c$\Direct
Dim fso, F
Set fso = CreateObject("Scripting.Fi
Set f = fso.GetFolder(path)
MsgBox (f.Size)
Just trying to find ideas for you.
ASKER
the problem with the FSO solution is that it does not work for remote servers. At least i have not found code to do that. it doesnt have a readily available authentication method.
also, how do you get the folder size with logicaldisk? i didnt see that as a property to read? only the disk sizes.
did i miss something.
also, how do you get the folder size with logicaldisk? i didnt see that as a property to read? only the disk sizes.
did i miss something.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
interesting.. i will try that fso code. i had tried some fso code that i found for vb.net but it gave me permission errors, which is odd because i the administrator. i can't believe that gathering this information is not easier. everything else i want to get out of WMI i can. sometimes i just don't understand how developers can take something good, and screw it up. lol. your help is greatly appreciated.
ManObjectSearcher.Query.Qu
- Make sure the path that is passed to the SELECT statement has double slashes. It would return an error if it doesn't, so this may not be your problem area.
Other than that, I'd do some incremental debugging, watching each variable, etc.