Solved

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

Posted on 2002-07-30
12
3,686 Views
Last Modified: 2012-06-21
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: http://www.experts-exchange.com/questions/Q_20175600.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.
0
Comment
Question by:rlively
  • 8
  • 4
12 Comments
 
LVL 3

Author Comment

by:rlively
ID: 7188253
 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
0
 
LVL 23

Accepted Solution

by:
naveenkohli earned 400 total points
ID: 7188507
I don't think that there is any class or method available for this. But you can always use Interop to get this information. Use GetDiskFreeSpace API for that. Here is how you can use it.

public class Win32SDK
     {
          [DllImport("kernel32.dll", PreserveSig=true, CharSet=CharSet.Auto)]
          public static extern IntPtr CreateFile(string strFileName, int dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition,  int dwFlagsAndAttributes, IntPtr hTemplateFile);
         
[DllImport("kernel32.dll", PreserveSig= true, CharSet=CharSet.Auto)]
public static extern int GetDiskFreeSpaceEx(
               IntPtr lpDirectoryName,                 // directory name
               out long lpFreeBytesAvailable,    // bytes available to caller
               out long lpTotalNumberOfBytes,    // bytes on disk
               out long lpTotalNumberOfFreeBytes // free bytes on disk
               );
     }

private long GetAvailableDiskSpace(string strUncPath)
          {
               long lBytesAvailable = -1;
               long lTotalBytes;
               long lTotalFreeBytes;
               IntPtr pszPath = Marshal.StringToHGlobalAuto(strUncPath);
               try
               {
                    int iVal = Win32SDK.GetDiskFreeSpaceEx(pszPath, out lBytesAvailable, out lTotalBytes, out lTotalFreeBytes);
               }
               finally
               {
                    Marshal.FreeHGlobal(pszPath);
               }
               return lBytesAvailable;
          }
0
 
LVL 3

Author Comment

by:rlively
ID: 7188639
 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
0
 
LVL 3

Author Comment

by:rlively
ID: 7188734
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$"
0
 
LVL 3

Author Comment

by:rlively
ID: 7188750
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 :)
0
 
LVL 3

Author Comment

by:rlively
ID: 7188785
 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?
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 23

Expert Comment

by:naveenkohli
ID: 7188786
Sorru about C# code. I Am just not good at VB at all. Its great that things have worked out for you using Interop.
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7188793
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\
0
 
LVL 3

Author Comment

by:rlively
ID: 7188795
 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?
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7188796
UNC path.

\\Server\Drive\

In your case it would be..

\\Server2\E$\
0
 
LVL 3

Author Comment

by:rlively
ID: 7188817
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.
0
 
LVL 3

Author Comment

by:rlively
ID: 7188971
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)
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Normally the drop down box control found in the .Net framework tools is able to select just one data and value at a time, which is displayed on the text area.   But what if you want to have multiple values to be selected in the drop down box? As …
Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

757 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now