2009-12-13 42 views
8

Tôi đang cố gắng liệt kê tất cả các ổ đĩa cục bộ trong ứng dụng của mình và DriveInfo.GetDrives trả lại các ký tự ổ đĩa cục bộ và tôi cũng cần các ổ đĩa được ánh xạ.Ổ đĩa mạng được ánh xạ không thể liệt kê trong C#

Hiện tại tôi có: C :, D :, và G: (HDD), E: và F: (CD) và S: và Z: (ổ đĩa mạng được ánh xạ). (Có, tất cả chúng đều hiển thị trong Windows Explorer và trong cả Total Commander nữa.) Nhưng chỉ có C, D, E, F, G được truy xuất theo chương trình.

Tôi cũng đã thử Environment.GetLogicalDrives(), GetLogicalDriveStrings (pInvoke), FindFirstVolumeFindNextVolumen (pInvoke). Tôi đã cố gắng tìm danh sách ổ đĩa được ánh xạ trong sổ đăng ký. Không có gì hoạt động, chỉ có các chữ cái HDD và CD được truy xuất lại.

Không có ngoại lệ nào xảy ra, không có lỗi nào được chỉ ra trong các cuộc gọi WinAPI trực tiếp và giờ tôi bị kẹt. Có một số loại cài đặt bảo mật không? Ở khắp mọi nơi tôi nhìn, những người nói rằng DriveInfo.GetDrives nên trả lại các ổ đĩa được ánh xạ. Nó có thực sự đúng không?

Tôi đang sử dụng Vista Home Pro. Ứng dụng đang chạy từ máy cục bộ, và nó cũng được xây dựng ở đây với Visual   Studio   2008.

Tôi đăng những gì tôi đã sử dụng, nhưng nó đơn giản đến nỗi tôi làm sai điều gì đó:

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

Kết quả: C: \ D: \ E: \ F: \ G: \ Nhấn phím bất kỳ để tiếp tục. . .

Tôi làm cách nào để nó hoạt động?

+0

Bạn có đang chạy chế độ này ở chế độ người dùng hoặc trong dịch vụ không? –

+0

Ở chế độ người dùng.Ứng dụng giao diện điều khiển hoàn hảo bình thường hoặc ứng dụng WinForm. – Zolka

Trả lời

5

Environment.GetLogicalDrives()DriveInfo.GetDrives() cả hai đều trả về tất cả các ổ đĩa được nối mạng của tôi.

Ứng dụng của bạn có đang chạy với tư cách người dùng khác không (Ví dụ: trang web asp.net)? Nếu có, các ổ đĩa có thực sự được ánh xạ cho người dùng đó không? Bạn có thể thấy rằng các ổ đĩa được ánh xạ cho bạn nhưng chúng không thực sự được ánh xạ cho người dùng mà ứng dụng của bạn đang chạy.

+0

Không, nó là một ứng dụng WinForm, và tôi không thay đổi người dùng. Điều này có thể là UAC (mà tôi tiếp tục bật) bắt đầu ứng dụng của tôi với người dùng bình thường, trong khi các ổ đĩa được ánh xạ được liên kết với người dùng thực (quản trị viên) của tôi? Tôi nghi ngờ nó ... nhưng có lẽ. – Zolka

+1

Tôi nghi ngờ điều đó, bạn thường không phải cấp quyền truy cập quản trị viên để xem các chia sẻ tệp. Bạn luôn có thể thử chạy ứng dụng với tư cách quản trị viên chỉ để xem. Một điều bạn có thể xem là System.Security.Principal.WindowsIdentity.GetCurrent(). Tên sẽ cho bạn biết người dùng đang chạy như thế nào, chỉ để chắc chắn. – fyjham

+0

Tôi đã thử nó mà không có UAC, stilll không hoạt động. Tôi đã kiểm tra người dùng hiện tại từ ứng dụng và nó giống như tôi đang sử dụng. Nhân tiện, các ổ đĩa được ánh xạ bị ngắt kết nối. Tôi không nghĩ điều đó có nghĩa là bất kỳ sự khác biệt nào, nhưng có lẽ nó sẽ giúp ích cho bạn. – Zolka

8

OK, tôi đã tìm hiểu cách lấy các ổ đĩa bị ngắt kết nối trên Vista. Không dễ dàng, nhưng nó là doable:

Trước tiên, bạn sẽ cần phải định nghĩa PInvoke trong những chức năng WinAPI sau:

  • WNetOpenEnum
  • WNetEnumResource
  • WNetCloseEnum

và những cần một cấu trúc và một số enums là tốt.

Sau đó, bạn cần gọi những lần đó nhiều lần và cuối cùng, bạn sẽ nhận được danh sách. Đây là đoạn mã, hãy cẩn thận, nó có chiều dài:

[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); 
    } 

Bạn phải gọi WNetResource(), và bạn sẽ lấy lại danh sách các ổ đĩa. (và bánh :-))

Các vấn đề liên quan