¿Cómo puedo determinar si una unidad remota tiene suficiente espacio para escribir un archivo con C #?

StackOverflow https://stackoverflow.com/questions/137255

Pregunta

¿Cómo puedo determinar si una unidad remota tiene suficiente espacio para cargar un archivo determinado utilizando C # en .Net?

¿Fue útil?

Solución

Hay dos soluciones posibles.

  1. Llame a la función Win32 GetDiskFreeSpaceEx. Aquí hay un programa de muestra:

    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. Use la interfaz de administración del sistema. Hay otra respuesta en este post que describe esto. Este método está realmente diseñado para su uso en lenguajes de scripting como PowerShell. Realiza una gran cantidad de pelusa solo para obtener el objeto correcto. En última instancia, sospecho que este método se reduce a llamar a GetDiskFreeSpaceEx.

Cualquiera que esté realizando un desarrollo serio de Windows en C # probablemente terminará llamando a muchas funciones de Win32. El marco .NET simplemente no cubre el 100% de la API de Win32. Cualquier programa grande descubrirá rápidamente las brechas en las bibliotecas .NET que solo están disponibles a través de la API de Win32. Me gustaría conseguir uno de los envoltorios Win32 para .NET e incluir esto en su proyecto. Esto le dará acceso instantáneo a casi todas las API de Win32.

Otros consejos

Usa 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"];
}

basado en (robado de) http://www.dreamincode.net/code/snippet1576. htm

¿Está hablando de asignar un recurso compartido de red a una unidad lógica en su computadora?

Si es así, puedes usar DriveInfo.

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

    info.AvailableFreeSpace;

DriveInfo solo funciona con unidades lógicas, por lo que si solo está utilizando el nombre de recurso compartido completo (UNC), no creo que el código anterior funcione.

No estoy seguro de si GetDiskFreeSpaceEx funciona en recursos compartidos UNC, pero si lo utiliza, de lo contrario, aquí se explica cómo montar un recurso compartido UNC en una unidad de registro:

EDIT GetDiskFreeSpaceEx funciona en recursos compartidos UNC, use eso ... sin embargo, este código fue demasiado esfuerzo para simplemente eliminar, y es útil si alguna vez desea montar un recurso compartido UNC como local conducir en su código.

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;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top