2011-02-28 34 views
6

Tôi đang viết một chức năng trong C# nơi tôi được yêu cầu liệt kê tất cả các tên tệp/thư mục trong một thư mục nhất định. Chức năng này hoạt động tốt trên hệ điều hành EN, nhưng khi tôi chạy ứng dụng trên hệ điều hành cục bộ (ví dụ: tiếng Đức), tôi vẫn nhận được tên tiếng Anh của các thư mục đặc biệt (Program Files thay vì Program, Favorites thay vì Favoriten, vv). Tôi không nghĩ rằng Environment.GetFolderPath với Environment.SpecialFolder có thể được giúp đỡ vì nó hoàn toàn trái ngược với những gì tôi muốn nghĩa là nó cung cấp cho đường dẫn đầy đủ của thư mục đặc biệt liệt kê, trong khi, tôi muốn tên địa phương của con đường. Tôi đã thử sử dụng File, SHFileInfo, nhưng không sử dụng. Bất kỳ ý tưởng, làm thế nào tôi có thể nhận được tên thư mục như được hiển thị trong hệ điều hành?Làm cách nào để có được tên thư mục thực tế (được bản địa hóa)?

+0

tôi nghĩ rằng u cần phải thiết lập miền địa phương của bạn trong mã ... –

+0

tôi sẽ nói tên tiếng Anh là tên thật (bạn cần nó để truy cập tệp) và tên tiếng Đức chỉ là tên hiển thị. – CodesInChaos

Trả lời

10

Bạn có thể lấy tên hiển thị địa phương với SHGetFileInfo API:

public static string GetDisplayName(Environment.SpecialFolder specialFolder) 
    { 
     IntPtr pidl = IntPtr.Zero; 
     try 
     { 
      HResult hr = SHGetFolderLocation(IntPtr.Zero, (int) specialFolder, IntPtr.Zero, 0, out pidl); 
      if (hr.IsFailure) 
       return null; 

      SHFILEINFO shfi; 
      if (0 != SHGetFileInfo(
         pidl, 
         FILE_ATTRIBUTE_NORMAL, 
         out shfi, 
         (uint)Marshal.SizeOf(typeof(SHFILEINFO)), 
         SHGFI_PIDL | SHGFI_DISPLAYNAME)) 
      { 
       return shfi.szDisplayName; 
      } 
      return null; 
     } 
     finally 
     { 
      if (pidl != IntPtr.Zero) 
       ILFree(pidl); 
     } 
    } 

    public static string GetDisplayName(string path) 
    { 
     SHFILEINFO shfi; 
     if (0 != SHGetFileInfo(
        path, 
        FILE_ATTRIBUTE_NORMAL, 
        out shfi, 
        (uint)Marshal.SizeOf(typeof(SHFILEINFO)), 
        SHGFI_DISPLAYNAME)) 
     { 
      return shfi.szDisplayName; 
     } 
     return null; 
    } 

    private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; 
    private const uint SHGFI_DISPLAYNAME = 0x000000200;  // get display name 
    private const uint SHGFI_PIDL = 0x000000008;  // pszPath is a pidl 

    [DllImport("shell32")] 
    private static extern int SHGetFileInfo(IntPtr pidl, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint flags); 
    [DllImport("shell32")] 
    private static extern HResult SHGetFolderLocation(IntPtr hwnd, int nFolder, IntPtr token, int dwReserved, out IntPtr pidl); 
    [DllImport("shell32")] 
    private static extern void ILFree(IntPtr pidl); 

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] 
    private struct SHFILEINFO 
    { 
     public IntPtr hIcon; 
     public int iIcon; 
     public uint dwAttributes; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 
     public string szDisplayName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] 
     public string szTypeName; 
    } 

[StructLayout(LayoutKind.Sequential)] 
public struct HResult 
{ 
    private int _value; 

    public int Value 
    { 
     get { return _value; } 
    } 

    public Exception Exception 
    { 
     get { return Marshal.GetExceptionForHR(_value); } 
    } 

    public bool IsSuccess 
    { 
     get { return _value >= 0; } 
    } 

    public bool IsFailure 
    { 
     get { return _value < 0; } 
    } 
} 
+0

chính xác những gì tôi đang tìm kiếm. Cảm ơn. Tuy nhiên, tôi có thêm một vấn đề nữa (không phải là sự hồi quy của mã này, nhưng có sẵn từ trước). Trong khi tôi liệt kê các tập tin, Bây giờ tôi nhận được hai tập tin cho chương trình bằng tiếng Đức. Một là một thư mục và một cho thấy như là một liên kết mà thực sự có thể nhìn thấy trong hệ điều hành. Trước khi thực hiện thay đổi được đề xuất, tôi đã nhận được tên không được bản địa hóa cho các thư mục này và tên được bản địa hóa cho lối tắt. Tôi không muốn hiển thị các phím tắt khi chúng làm cho danh sách lặp đi lặp lại. – Scotti

+0

chỉ lọc ra các tệp .lnk –

+0

Tôi nhận được '敄 歳 潴 p 敄 歳 潴 p' cho' Environment.SpecialFolder.Desktop' với văn bản 'de-DE' (Đức). Tại sao? –

2

tôi đã tìm ra cách để có được điều này để làm việc. Bạn không chắc chắn những gì sai với các mã trên (tôi cũng có ký tự Unicode Trung Quốc), nhưng điều này dường như làm việc đáng tin cậy. Chỉ cần vượt qua trong đường dẫn (ví dụ, bằng cách gọi:

GetDisplayName(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); 

và nó sẽ trả về tên hiển thị của các thư mục (trong ví dụ này, "My Documents" hay bất cứ điều gì bạn đã đổi tên nó thành)

.
using System.Runtime.InteropServices; 
... 
public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; 
public const uint SHGFI_DISPLAYNAME = 0x000000200;  // get display name 

[DllImport("shell32")] 
public static extern int SHGetFileInfo(string pszPath, uint dwFileAttributes, 
    out SHFILEINFO psfi, uint cbFileInfo, uint flags); 

[StructLayout(LayoutKind.Sequential)] 
public struct SHFILEINFO 
{ 
    public IntPtr hIcon; 
    public IntPtr iIcon; 
    public uint dwAttributes; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 
    public string szDisplayName; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] 
    public string szTypeName; 
}; 


public static string GetDisplayName(string path) 
{ 
    SHFILEINFO shfi = new SHFILEINFO(); 
    if (0 != SHGetFileInfo(path,FILE_ATTRIBUTE_NORMAL,out shfi, 
     (uint)Marshal.SizeOf(typeof(SHFILEINFO)),SHGFI_DISPLAYNAME)) 
    { 
     return shfi.szDisplayName; 
    } 
    return null; 
} 
+0

Điều này hoạt động so với các giải pháp khác cung cấp cho một số ký tự Trung Quốc. – whywhywhy

0

bạn phải chắc chắn rằng charset được thiết lập để Unicode cho DllImport và StructLayout.

[DllImport("shell32", CharSet = CharSet.Unicode)] 
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 
Các vấn đề liên quan