2009-12-13 7 views
8

Sto cercando di elencare tutte le unità locali nella mia applicazione, e DriveInfo.GetDrives restituire le lettere di unità locali, e ho bisogno anche delle unità mappate.Le unità di rete mappate non possono essere elencate in C#

Attualmente ho: C :, D :, e G: (HDD), E: e F: (CD) e S: e Z: (unità di rete mappate). (Sì, sono tutti visibili in Esplora risorse e anche in Total Commander.) Ma solo C, D, E, F, G vengono recuperati a livello di programmazione.

Ho anche provato Environment.GetLogicalDrives(), GetLogicalDriveStrings (pInvoke), FindFirstVolume e FindNextVolumen (pInvoke). Ho provato a trovare l'elenco delle unità mappate nel registro. Nulla funziona, solo le lettere HDD e CD vengono recuperate.

Non c'è nessuna eccezione in arrivo, nessun errore indicato nelle chiamate dirette WinAPI, e ora sono bloccato. È una specie di impostazione di sicurezza? Ovunque guardi, la gente dice che il DriveInfo.GetDrives dovrebbe restituire le unità mappate. È proprio vero?

Sto usando Vista Home Pro. L'applicazione è in esecuzione dal computer locale, ed è costruito anche qui con Visual   Studio   2008.

inserisco quello che ho usato, ma è così semplice, non può essere il caso che faccio qualcosa di sbagliato:

foreach (System.IO.DriveInfo di in System.IO.DriveInfo.GetDrives()) 
    Console.WriteLine(di.Name); 

Risultato: C: \ D: \ E: \ F: \ G: \ Premere un tasto qualsiasi per continuare. . .

Come posso farlo funzionare?

+0

Stai eseguendo questo in modalità utente o in un servizio? –

+0

In modalità utente.Applicazione console perfettamente normale o app WinForm. – Zolka

risposta

5

Environment.GetLogicalDrives() e DriveInfo.GetDrives() restituiscono entrambe le unità di rete.

L'applicazione è in esecuzione come utente diverso (ad esempio un sito Web asp.net)? Se lo è, le unità sono effettivamente mappate per quell'utente? Potresti scoprire che le unità sono mappate per te ma in realtà non sono mappate per l'utente in cui è in esecuzione l'applicazione.

+0

No, è un'applicazione WinForm e non ho cambiato utenti. È possibile che l'UAC (che continuo ad accendere) avvii la mia app con l'utente normale, mentre le unità mappate sono collegate al mio vero utente (amministratore)? Ne dubito ... ma forse. – Zolka

+1

Ne dubito, in genere non devi concedere l'accesso come amministratore per vedere le condivisioni di file. Puoi sempre provare a eseguire l'app come amministratore solo per vedere. Una cosa che potresti dare un'occhiata è System.Security.Principal.WindowsIdentity.GetCurrent(). Nome che ti dirà a quale utente sta correndo attualmente, solo per essere sicuro. – fyjham

+0

L'ho provato senza UAC, stilll non funziona. Ho controllato l'utente corrente dall'app ed è lo stesso che stavo usando. A proposito, le unità mappate sono disconnesse. Non penso che questo dovrebbe significare alcuna differenza, ma forse aiuta. – Zolka

8

OK, ho scoperto come ottenere le unità disconnesse su Vista. Non è facile, ma è fattibile:

In primo luogo, è necessario la definizione PInvoke delle seguenti funzioni WinAPI:

  • WNetOpenEnum
  • WNetEnumResource
  • WNetCloseEnum

e quelli ho bisogno di una struttura e di alcune enumerazioni.

Quindi è necessario chiamare quelle più volte, e alla fine, si ottiene la lista. Ecco il codice, attenzione, è lunga:

[DllImport("MPR.dll", CharSet = CharSet.Auto)] 
    static extern int WNetEnumResource(IntPtr hEnum, ref int lpcCount, IntPtr lpBuffer, ref int lpBufferSize); 

    [DllImport("MPR.dll", CharSet = CharSet.Auto)] 
    static extern int WNetOpenEnum(RESOURCE_SCOPE dwScope, RESOURCE_TYPE dwType, RESOURCE_USAGE dwUsage, 
     [MarshalAs(UnmanagedType.AsAny)][In] object lpNetResource, out IntPtr lphEnum); 

    [DllImport("MPR.dll", CharSet = CharSet.Auto)] 
    static extern int WNetCloseEnum(IntPtr hEnum); 

    public enum RESOURCE_SCOPE : uint 
    { 
     RESOURCE_CONNECTED = 0x00000001, 
     RESOURCE_GLOBALNET = 0x00000002, 
     RESOURCE_REMEMBERED = 0x00000003, 
     RESOURCE_RECENT = 0x00000004, 
     RESOURCE_CONTEXT = 0x00000005 
    } 
    public enum RESOURCE_TYPE : uint 
    { 
     RESOURCETYPE_ANY = 0x00000000, 
     RESOURCETYPE_DISK = 0x00000001, 
     RESOURCETYPE_PRINT = 0x00000002, 
     RESOURCETYPE_RESERVED = 0x00000008, 
    } 
    public enum RESOURCE_USAGE : uint 
    { 
     RESOURCEUSAGE_CONNECTABLE = 0x00000001, 
     RESOURCEUSAGE_CONTAINER = 0x00000002, 
     RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004, 
     RESOURCEUSAGE_SIBLING = 0x00000008, 
     RESOURCEUSAGE_ATTACHED = 0x00000010, 
     RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED), 
    } 
    public enum RESOURCE_DISPLAYTYPE : uint 
    { 
     RESOURCEDISPLAYTYPE_GENERIC = 0x00000000, 
     RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001, 
     RESOURCEDISPLAYTYPE_SERVER = 0x00000002, 
     RESOURCEDISPLAYTYPE_SHARE = 0x00000003, 
     RESOURCEDISPLAYTYPE_FILE = 0x00000004, 
     RESOURCEDISPLAYTYPE_GROUP = 0x00000005, 
     RESOURCEDISPLAYTYPE_NETWORK = 0x00000006, 
     RESOURCEDISPLAYTYPE_ROOT = 0x00000007, 
     RESOURCEDISPLAYTYPE_SHAREADMIN = 0x00000008, 
     RESOURCEDISPLAYTYPE_DIRECTORY = 0x00000009, 
     RESOURCEDISPLAYTYPE_TREE = 0x0000000A, 
     RESOURCEDISPLAYTYPE_NDSCONTAINER = 0x0000000B 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct NetResource 
    { 
     public RESOURCE_SCOPE dwScope; 
     public RESOURCE_TYPE dwType; 
     public RESOURCE_DISPLAYTYPE dwDisplayType; 
     public RESOURCE_USAGE dwUsage; 
     [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)] 
     public string lpLocalName; 
     [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)] 
     public string lpRemoteName; 
     [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)] 
     public string lpComment; 
     [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)] 
     public string lpProvider; 
    } 

    static System.Collections.Generic.Dictionary<string, NetResource> WNetResource(object resource) 
    { 
     System.Collections.Generic.Dictionary<string, NetResource> result = new System.Collections.Generic.Dictionary<string, NetResource>(); 

     int iRet; 
     IntPtr ptrHandle = new IntPtr(); 
     try 
     { 
      iRet = WNetOpenEnum(
       RESOURCE_SCOPE.RESOURCE_REMEMBERED, RESOURCE_TYPE.RESOURCETYPE_DISK, RESOURCE_USAGE.RESOURCEUSAGE_ALL, 
       resource, out ptrHandle); 
      if (iRet != 0) 
       return null; 

      int entries = -1; 
      int buffer = 16384; 
      IntPtr ptrBuffer = Marshal.AllocHGlobal(buffer); 
      NetResource nr; 

      iRet = WNetEnumResource(ptrHandle, ref entries, ptrBuffer, ref buffer); 
      while ((iRet == 0) || (entries > 0)) 
      { 
       Int32 ptr = ptrBuffer.ToInt32(); 
       for (int i = 0; i < entries; i++) 
       { 
        nr = (NetResource)Marshal.PtrToStructure(new IntPtr(ptr), typeof(NetResource)); 
        if (RESOURCE_USAGE.RESOURCEUSAGE_CONTAINER == (nr.dwUsage 
         & RESOURCE_USAGE.RESOURCEUSAGE_CONTAINER)) 
        { 
         //call recursively to get all entries in a container 
         WNetResource(nr); 
        } 
        ptr += Marshal.SizeOf(nr); 
        result.Add(nr.lpLocalName, nr); 
       } 

       entries = -1; 
       buffer = 16384; 
       iRet = WNetEnumResource(ptrHandle, ref entries, ptrBuffer, ref buffer); 
      } 

      Marshal.FreeHGlobal(ptrBuffer); 
      iRet = WNetCloseEnum(ptrHandle); 
     } 
     catch (Exception) 
     { 
     } 

     return result; 
    } 
    public static System.Collections.Generic.Dictionary<string, NetResource> WNetResource() 
    { 
     return WNetResource(null); 
    } 

Hai avuto modo di chiamare il WNetResource(), e si otterrà indietro l'elenco delle unità. (e torta :-))

Problemi correlati