Как определить, достаточно ли места на удаленном диске для записи файла с использованием C #? - PullRequest
5 голосов
/ 26 сентября 2008

Как определить, достаточно ли места на удаленном диске для загрузки данного файла с помощью C # в .Net?

Ответы [ 4 ]

10 голосов
/ 26 сентября 2008

Есть два возможных решения.

  1. Вызов Win32 функции GetDiskFreeSpaceEx. Вот пример программы:

    internal static class Win32
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool GetDiskFreeSpaceEx(string drive, out long freeBytesForUser, out long totalBytes, out long freeBytes);
    
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            long freeBytesForUser;
            long totalBytes;
            long freeBytes;
    
            if (Win32.GetDiskFreeSpaceEx(@"\\prime\cargohold", out freeBytesForUser, out totalBytes, out freeBytes)) {
                Console.WriteLine(freeBytesForUser);
                Console.WriteLine(totalBytes);
                Console.WriteLine(freeBytes);
            }
        }
    }
    
  2. Использовать интерфейс управления системой. В этом посте есть другой ответ, который описывает это. Этот метод действительно предназначен для использования в языках сценариев, таких как PowerShell. Он выполняет много пуха только для того, чтобы получить нужный объект. В конечном счете, я подозреваю, что этот метод сводится к вызову GetDiskFreeSpaceEx.

Любой, кто занимается серьезной разработкой для Windows на C #, вероятно, в конечном итоге вызовет множество функций Win32. .NET Framework просто не покрывает 100% Win32 API. Любая большая программа быстро обнаружит пробелы в библиотеках .NET, которые доступны только через Win32 API. Я бы заполучил одну из оболочек Win32 для .NET и включил это в ваш проект. Это даст вам мгновенный доступ практически ко всем Win32 API.

5 голосов
/ 26 сентября 2008

Использовать WMI

using System.Management;

// Get all the network drives (drivetype=4)
SelectQuery query = new SelectQuery("select Name, VolumeName, FreeSpace from win32_logicaldisk where drivetype=4");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject drive in searcher.Get())
{
    string Name = (string)drive["Name"];
    string VolumeName = (string)drive["VolumeName"];
    UInt64 freeSpace = (UInt64)drive["FreeSpace"];
}

на основании (украдено у) http://www.dreamincode.net/code/snippet1576.htm

2 голосов
/ 26 сентября 2008

Я не уверен, работает ли GetDiskFreeSpaceEx на общих ресурсах UNC, но если он это использует, в противном случае вот как подключить общий ресурс UNC к логическому диску:

РЕДАКТИРОВАТЬ GetDiskFreeSpaceEx работает с общими ресурсами UNC, используйте это ... однако этот код был слишком сложным, чтобы его просто удалить, и удобен, если вы когда-нибудь захотите смонтировать общий ресурс UNC как локальный диск. в вашем коде.

public class DriveWrapper
{                    
    [StructLayout(LayoutKind.Sequential)]
    public struct NETRESOURCEA
    {
        public int dwScope;
        public int dwType;
        public int dwDisplayType;
        public int dwUsage;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpLocalName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpRemoteName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpComment;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpProvider;
        public override String ToString()
        {
            String str = "LocalName: " + lpLocalName + " RemoteName: " + lpRemoteName
                  + " Comment: " + lpComment + " lpProvider: " + lpProvider;
            return (str);
        }
    }

    [DllImport("mpr.dll")]
    public static extern int WNetAddConnection2A(
          [MarshalAs(UnmanagedType.LPArray)] NETRESOURCEA[] lpNetResource,
          [MarshalAs(UnmanagedType.LPStr)] string lpPassword,
          [MarshalAs(UnmanagedType.LPStr)] string UserName,
          int dwFlags);       
    [DllImport("mpr.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern int WNetCancelConnection2A(
          [MarshalAs(UnmanagedType.LPStr)]
        string lpName,
          int dwFlags,
          int fForce
          );

    public int GetDriveSpace(string shareName, string userName, string password)
    {
        NETRESOURCEA[] n = new NETRESOURCEA[1];
        n[0] = new NETRESOURCEA();

        n[0].dwScope = 0;
        n[0].dwType = 0;
        n[0].dwDisplayType = 0;
        n[0].dwUsage = 0;

        n[0].dwType = 1;

        n[0].lpLocalName = "x:";
        n[0].lpRemoteName = shareName;
        n[0].lpProvider = null;

        int res = WNetAddConnection2A(n, userName, password, 1);

        DriveInfo info = new DriveInfo("x:");
        int space = info.AvailableFreeSpace;

        int err = 0;
        err = WNetCancelConnection2A("x:", 0, 1);

        return space;
    }
}
2 голосов
/ 26 сентября 2008

Вы говорите о подключении общего сетевого ресурса к логическому диску на вашем компьютере?

Если это так, вы можете использовать DriveInfo.

    DriveInfo info = new DriveInfo("X:");

    info.AvailableFreeSpace;

DriveInfo работает только с логическими дисками, поэтому, если вы просто используете полное имя ресурса (UNC), я не думаю, что приведенный выше код будет работать.

...