1. 程式人生 > >C#根據字體名通過註冊表獲取該字體文件路徑(win10)

C#根據字體名通過註冊表獲取該字體文件路徑(win10)

cat mic 約束 lec 運行 window mac war 控件

方法一:

直接先上源碼:

        private System.Collections.Generic.SortedDictionary<string, string> ReadFontInformation()
        {
            var dictionary = new System.Collections.Generic.SortedDictionary<string, string>();

           
                Microsoft.Win32.RegistryKey localMachineKey = Microsoft.Win32.Registry.LocalMachine;
                // 打開註冊表  
                Microsoft.Win32.RegistryKey localMachineKeySub = localMachineKey.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", false);

                //獲取字體名  
                string[] mynames = localMachineKeySub.GetValueNames();

                foreach (string name in mynames)
                {
                    //獲取字體的文件名  
                    string myvalue = localMachineKeySub.GetValue(name).ToString();

                    if (myvalue.Substring(myvalue.Length - 4).ToUpper() == ".TTF" && myvalue.Substring(1, 2).ToUpper() != @":\")
                    {
                        string val = name.Substring(0, name.Length - 11);
                        dictionary[val] = myvalue;
                    }
                }
            localMachineKeySub.Close();
            return dictionary;
        }

解決思路:

1. 打開windows/fonts目錄, 右鍵下圖, 勾選字體文件名稱, 發現其實字體文件名稱和顯示的名稱是有區別的

技術分享

技術分享

2. 然後去註冊表中看看, win+r→regedit, 定位 LocalMachine \\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts 可以看到, 對應的鍵值對

技術分享

3. 既然有思路了, 就開始操作註冊表, 註意, 如果在win7以上的系統中, 將localMachineKey.OpenSubKey("",true)第二個參數設置為true, 在xp下沒有問題, 在win7以上就會報以下錯誤:

技術分享

4. 解決此錯誤的方法是增加應用程序配置清單文件, 然後做下面的修改, 但是在運行的時候, 會提示要求用管理員權限(提權). 全部代碼和清單文件內容如下:

//[System.Security.Permissions.RegistryPermissionAttribute(System.Security.Permissions.SecurityAction.PermitOnly, Read = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts")]// 約束代碼僅可讀註冊表
        private System.Collections.Generic.SortedDictionary<string, string> ReadFontInformation()
        {
            var dictionary = new System.Collections.Generic.SortedDictionary<string, string>();

           
                Microsoft.Win32.RegistryKey localMachineKey = Microsoft.Win32.Registry.LocalMachine;
                // 打開註冊表  
                Microsoft.Win32.RegistryKey localMachineKeySub = localMachineKey.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", false);

                //獲取字體名  
                string[] mynames = localMachineKeySub.GetValueNames();

                foreach (string name in mynames)
                {
                    //獲取字體的文件名  
                    string myvalue = localMachineKeySub.GetValue(name).ToString();

                    if (myvalue.Substring(myvalue.Length - 4).ToUpper() == ".TTF" && myvalue.Substring(1, 2).ToUpper() != @":\")
                    {
                        string val = name.Substring(0, name.Length - 11);
                        dictionary[val] = myvalue;
                    }
                }
            localMachineKeySub.Close();
            return dictionary;
        }

清單文件:

技術分享

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC 清單選項
             如果想要更改 Windows 用戶帳戶控制級別,請使用
             以下節點之一替換 requestedExecutionLevel 節點。n
        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            指定 requestedExecutionLevel 元素將禁用文件和註冊表虛擬化。
            如果你的應用程序需要此虛擬化來實現向後兼容性,則刪除此
            元素。
        -->
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- 設計此應用程序與其一起工作且已針對此應用程序進行測試的
           Windows 版本的列表。取消評論適當的元素,Windows 將
           自動選擇最兼容的環境。 -->

      <!-- Windows Vista -->
      <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->

      <!-- Windows 7 -->
      <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->

      <!-- Windows 8 -->
      <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->

      <!-- Windows 8.1 -->
      <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->

      <!-- Windows 10 -->
      <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->

    </application>
  </compatibility>

  <!-- 指示該應用程序可以感知 DPI 且 Windows 在 DPI 較高時將不會對其進行
       自動縮放。Windows Presentation Foundation (WPF)應用程序自動感知 DPI,無需
       選擇加入。選擇加入此設置的 Windows 窗體應用程序(目標設定為 .NET Framework 4.6 )還應
       在其 app.config 中將 "EnableWindowsFormsHighDpiAutoResizing" 設置設置為 "true"。-->
  <!--
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>
  -->

  <!-- 啟用 Windows 公共控件和對話框的主題(Windows XP 和更高版本) -->
  <!--
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
  </dependency>
  -->

</assembly>

方法二:直接拿對應的文件名:

public  class FontNameFile
    {
        public static string getFontFileName(string fontname)
        {
            string folderFullName = System.Environment.GetEnvironmentVariable("windir") + "\\fonts";
            DirectoryInfo TheFolder = new DirectoryInfo(folderFullName);
            foreach (FileInfo NextFile in TheFolder.GetFiles())
            {
                if (NextFile.Exists)
                {
                    if (fontname==getFontName(NextFile.FullName))
                    {
                     
                        return NextFile.Name;
                    }
                }
            }
            return "";
        }

        private static string getFontName(string fontfilename)
        {
            PrivateFontCollection pfc = new PrivateFontCollection();
            //只要ttf和TTF, 其它的本項目不需要
            if (fontfilename.EndsWith(".ttf") || fontfilename.EndsWith(".TTF"))
            {
                pfc.AddFontFile(fontfilename);
            }
            if (pfc.Families.Length > 0)
            {
                return pfc.Families[0].Name;
            }
            return "";
        }
    }

技術分享

C#根據字體名通過註冊表獲取該字體文件路徑(win10)