Link to home
Start Free TrialLog in
Avatar of rlively
rlivelyFlag for United States of America

asked on

Disk free space on network drives using UNC path? (400 pts)

How can I get a list of drives available on a server by passing in the
server UNC (\\ServerName) and then for each of those drives get the
available disk space? (or at least for one known server and drive be able to get the free space on that drive - \\ServerName\E$).

What I want to do is very similar to this question but it will be done from a Windows Forms application instead of an ASP page: https://www.experts-exchange.com/questions/20175600/Get-disksize-and-free-space-of-hd's-from-remote-server.html 

I have looked at the System.Management and System.IO classes in help,
searched newsgroup postings (dotnet247.com, etc) and on google and I have
had no luck finding any examples.  There are plenty of examples for getting
the free disk space and enumerating drives for the local machine using FSO and System.Management classes and WQL, but not
for network servers.
Avatar of rlively
rlively
Flag of United States of America image

ASKER

 Here is one of my failed attempts:  \\ServerName has only one drive, but moMOC contains more than one object.  
  The first MessageBox I see is blank, and the second throws an exception: "System.ArgumentException: Argument 'Prompt' cannot be converted to type 'String'."
  When I change MsgBox to MessageBox.Show I get a different exception: "System.InvalidCastException: Cast from type 'UInt64' to type 'String' is not valid.  at Microsoft.VisualBasic.CompilerServices.StringType.FromObject(Object Value)"

moMOC.Count and moMOC.Items.Count both throw exceptions:

Count: <error: an exception of type: {System.NotSupportedException} occurred>


            Dim oOptions As New System.Management.ConnectionOptions()
            Dim moMOS As System.Management.ManagementObjectSearcher
            Dim moMOC As System.Management.ManagementObjectCollection
            Dim moObject As System.Management.ManagementObject

            'Dim moScope As New System.Management.ManagementScope("\\ServerName")

            oOptions.Username = "DOMAIN\USERID"
            oOptions.Password = "PASSWORD"
            moMOS = New System.Management.ManagementObjectSearcher("\\ServerName\", _
              "select * from Win32_LogicalDisk")
            moMOC = moMOS.Get

            For Each moObject In moMOC
                'There should only be one.
                MsgBox(moObject("FreeSpace"))
            Next
ASKER CERTIFIED SOLUTION
Avatar of naveenkohli
naveenkohli

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 rlively

ASKER

 Here is one of my failed attempts:  \\ServerName has only one drive, but moMOC contains more than one object.  
  The first MessageBox I see is blank, and the second throws an exception: "System.ArgumentException: Argument 'Prompt' cannot be converted to type 'String'."
  When I change MsgBox to MessageBox.Show I get a different exception: "System.InvalidCastException: Cast from type 'UInt64' to type 'String' is not valid.  at Microsoft.VisualBasic.CompilerServices.StringType.FromObject(Object Value)"

moMOC.Count and moMOC.Items.Count both throw exceptions:

Count: <error: an exception of type: {System.NotSupportedException} occurred>


            Dim oOptions As New System.Management.ConnectionOptions()
            Dim moMOS As System.Management.ManagementObjectSearcher
            Dim moMOC As System.Management.ManagementObjectCollection
            Dim moObject As System.Management.ManagementObject

            'Dim moScope As New System.Management.ManagementScope("\\ServerName")

            oOptions.Username = "DOMAIN\USERID"
            oOptions.Password = "PASSWORD"
            moMOS = New System.Management.ManagementObjectSearcher("\\ServerName\", _
              "select * from Win32_LogicalDisk")
            moMOC = moMOS.Get

            For Each moObject In moMOC
                'There should only be one.
                MsgBox(moObject("FreeSpace"))
            Next
Avatar of rlively

ASKER

Thanks for getting me on the right track!  I needed to convert your code to VB.NET so this is what I have:

        Declare Function GetDiskFreeSpaceEx Lib "kernel32.dll" Alias "GetDiskFreeSpaceExA" _
          (ByVal lpDirectoryName As IntPtr, _
          ByVal lpFreeBytesAvailableToCaller As Long, _
          ByVal lpTotalNumberOfBytes As Long, _
          ByVal lpTotalNumberOfFreeBytes As Long) As Integer

        Public Function GetAvailableDiskSpace(ByVal strUncPath As String) As Long
            Dim lBytesAvailable As Long = -1
            Dim lTotalBytes As Long = 0
            Dim lTotalFreeBytes As Long = 0

            Dim pszPath As IntPtr
            pszPath = System.Runtime.InteropServices.Marshal.StringToHGlobalAuto(strUncPath)

            Try
                Dim iVal As Integer
                iVal = GetDiskFreeSpaceEx(pszPath, lBytesAvailable, _
                                          lTotalBytes, lTotalFreeBytes)
            Catch excep As Exception
                MessageBox.Show(excep.ToString)
            Finally
                System.Runtime.InteropServices.Marshal.FreeHGlobal(pszPath)
            End Try

            Return lBytesAvailable

        End Function
--------------------

But when I run it I get an "Object reference not set to an instance of an object." exception on the line calling the API and I can't figure out why. The contents of the parameters are as follows:  pszPath = 1886200, lBytesAvailable = -1, lTotalBytes = 0, lTotalFreeBytes = 0.

Any idea why this doesn't work for me and I get an exception every time?  The string I am sending in is "\\ServerName\C$"
Avatar of rlively

ASKER

Nevermind! I just realized my mistake.  All the params defaulted to ByVal in my API declaration and I forgot to  change them to ByRef.  It works now :)
Avatar of rlively

ASKER

 Ok, the call goes through just fine, but it doesn't matter which server I send into the call I get the same return value each time.  It appears to be returning the disk free space on my own local C:\ drive, and never the free space on the server that I am querying.  I even sent a UNC path  for a drive that doesn't even exist ("\\Server2\E$" where Server2 only has a C:\ drive) and it still returned the free space on my own C:\ drive.

In what format do UNC paths need to be for this function to work on them?
Avatar of naveenkohli
naveenkohli

Sorru about C# code. I Am just not good at VB at all. Its great that things have worked out for you using Interop.
Put a break point in GetAvailableDiskSpace function and see if you are getting right values or not. And most importantly check what folder path is being sent as input to API. I have been using this component for some time and never had any trouble.

UNC path should be ..

\\Server\\Drive\
Avatar of rlively

ASKER

 Ok, the call goes through just fine, but it doesn't matter which server I send into the call I get the same return value each time.  It appears to be returning the disk free space on my own local C:\ drive, and never the free space on the server that I am querying.  I even sent a UNC path  for a drive that doesn't even exist ("\\Server2\E$" where Server2 only has a C:\ drive) and it still returned the free space on my own C:\ drive.

In what format do UNC paths need to be for this function to work on them?
UNC path.

\\Server\Drive\

In your case it would be..

\\Server2\E$\
Avatar of rlively

ASKER

I'm sending in for strUNCPath "\\ATLCPAIMSWEB\\C\" "\\ATLCPAIMSWEB\\E\" "\\ATLCPDSQL03\\C\" and various others, but lTotalFreeBytes is still always the available space on my C:\ drive.

These are the values returned each time (always the same) - these values are accurate for my C:\ drive (I have converted the bytes to GB).

ltotalbytes     29.21964 GB
ltotalbytes     37.2601  GB
ltotalfreebytes 29.21964 GB

Does anything look amiss in the API Declaration or the function?  

If this function should work with UNC paths then I should be very close to a solution.

Sorry for all the double-posts. I only hit submit once for each post.
Avatar of rlively

ASKER

I did get it working.  The help for GetDiskFreeSpaceEx states that you can send a UNC path in directly.  Thanks for the help.  GetAvailableDiskSpace("\\SERVER\E$\")) works with the API called to use the passed in UNC path instead of the pszPath:

iVal = GetDiskFreeSpaceEx(strUncPath, lBytesAvailable, lTotalBytes, lTotalFreeBytes)