Finding out Unicode character name in .Net

前端 未结 6 522
长情又很酷
长情又很酷 2020-12-01 12:06

Is there a way in .Net to find out, what Unicode name certain character has?

If not, is there a library that can do this?

6条回答
  •  佛祖请我去吃肉
    2020-12-01 12:47

    If you use Process Monitor to look at the files accessed by charmap.exe, you'll see that it opens a file named C:\Windows\system32\getuname.dll. This file contains the character names in its resources (actually the resources themselves are in a .mui file in a culture-specific subdirectory).

    So all you have to do is get the names from this file, using the LoadString API. I wrote a helper class to do it:

    public class Win32ResourceReader : IDisposable
    {
        private IntPtr _hModule;
    
        public Win32ResourceReader(string filename)
        {
            _hModule = LoadLibraryEx(filename, IntPtr.Zero, LoadLibraryFlags.AsDataFile | LoadLibraryFlags.AsImageResource);
            if (_hModule == IntPtr.Zero)
                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
        }
    
        public string GetString(uint id)
        {
            var buffer = new StringBuilder(1024);
            LoadString(_hModule, id, buffer, buffer.Capacity);
            if (Marshal.GetLastWin32Error() != 0)
                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
            return buffer.ToString();
        }
    
        ~Win32ResourceReader()
        {
            Dispose(false);
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        public void Dispose(bool disposing)
        {
            if (_hModule != IntPtr.Zero)
                FreeLibrary(_hModule);
            _hModule = IntPtr.Zero;
        }
    
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);
    
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
    
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool FreeLibrary(IntPtr hModule);
    
        [Flags]
        enum LoadLibraryFlags : uint
        {
            AsDataFile = 0x00000002,
            AsImageResource = 0x00000020
        }
    }
    

    You can use it like this:

    string path = @"C:\Windows\System32\getuname.dll";
    using (var reader = new Win32ResourceReader(path))
    {
        string name = reader.GetString(0xA9);
        Console.WriteLine(name); // Copyright Sign
    }
    

提交回复
热议问题