2008-09-26 11 views
5

Jak ustalić, czy dysk zdalny ma wystarczająco dużo miejsca, aby przesłać dany plik przy użyciu C# w .Net?Jak określić, czy na napędzie zdalnym jest wystarczająco dużo miejsca do zapisu pliku przy użyciu C#?

+0

Jaki rodzaj napędu: zdalny dysk sieciowy, strony internetowej itp? – Brettski

+0

Pamiętaj, że nawet jeśli możesz to ustalić, jest to dokładne tylko przez jedną chwilę - przesyłanie może się nie powieść, jeśli inni użytkownicy/procesy zapisują na dysku. – Shog9

Odpowiedz

10

Istnieją dwa możliwe rozwiązania.

  1. Wywołanie funkcji Win32 GetDiskFreeSpaceEx. Oto przykładowy program:

    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. Skorzystaj z interfejsu zarządzania systemem. W tym poście jest inna odpowiedź, która to opisuje. Ta metoda jest naprawdę zaprojektowana do użycia w językach skryptowych, takich jak PowerShell. Wykonuje dużo puchu tylko po to, aby uzyskać właściwy obiekt. Ostatecznie podejrzewam, że ta metoda sprowadza się do wywoływania GetDiskFreeSpaceEx.

Każdy, kto robi poważny program dla systemu Windows w języku C#, prawdopodobnie zakończy wykonywanie wielu funkcji Win32. Struktura .NET nie pokrywa 100% interfejsu Win32 API. Każdy duży program szybko odkryje luki w bibliotekach .NET, które są dostępne tylko za pośrednictwem Win32 API. Chciałbym zdobyć jeden z owiników Win32 dla .NET i uwzględnić to w twoim projekcie. Zapewni to natychmiastowy dostęp do niemal każdego interfejsu Win32 API.

+0

Czy GetDiskFreeSpaceEx działa z udziałami sieciowymi? A co z uwierzytelnianiem? – FlySwat

+0

Kod jest nieprawidłowy. Musisz użyć 'ulong' zamiast' long'. –

+0

Technicznie, tak, kod jest niepoprawny, chociaż kompiluje się, ponieważ DllImport używa longs zamiast ulongs. Wystąpi on tylko wtedy, gdy dysk będzie większy niż 2^63 bajty. Dysk 1 TB ma około 2^40 bajtów. Musimy przedostać się przez dyski petabajtów do dyskietek exabyte, zanim się zawiedzie. –

2

Czy mówisz o mapowaniu udziału sieciowego na dysk logiczny na twoim komputerze?

Jeśli tak, możesz użyć DriveInfo.

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

    info.AvailableFreeSpace; 

DriveInfo działa tylko z dyskami logicznymi, więc jeśli tylko przy użyciu pełnej akcji (UNC) Nazwa nie sądzę powyższy kod będzie działać.

2

Nie jestem pewien, czy GetDiskFreeSpaceEx działa na udziałach UNC, ale jeśli nie używać, że w przeciwnym razie tutaj jest jak zamontować udział UNC do logal napędu:

EDIT GetDiskFreeSpaceEx działa na udziałach UNC , użyj tego ... jednak ten kod był zbyt dużym wysiłkiem, aby po prostu usunąć i jest przydatny, jeśli kiedykolwiek chcesz zamontować udział UNC jako dysk lokalny w swoim kodzie.

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; 
    } 
} 
5

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

na podstawie (skradzione) http://www.dreamincode.net/code/snippet1576.htm