Search code examples
powershellwinapiunicode

gdi32 install fonts for session with non latin names


I am trying to install fonts in a temporary manner for the current session via a PowerShell script.

My current script is provided below, but the problem is that if the font is called "somelatin_font.ttf" it will work fine, but if the font has some non Latin characters (example Japanese) in its name, it will fail to install


$dir="fonts"

$signature = @'
[DllImport("gdi32.dll")]
 public static extern int AddFontResource(string lpszFilename);
'@

$type = Add-Type -MemberDefinition $signature `
    -Name FontUtils -Namespace AddFontResource `
    -Using System.Text -PassThru

foreach($font in  (Get-ChildItem -LiteralPath $dir -Recurse  | Where-Object {$_.extension -in ".ttf", ".otf"}) ) {   
    $ffn= $font.FullName
    echo "loading($ffn)" >> file.txt
    $type::AddFontResource($font)
}

I also tried adding CharSet = CharSet.Auto or unicode but neither of them worked:

[DllImport("gdi32.dll", CharSet=CharSet.Unicode)]

The error I get when I add this:

Add-Type : Cannot add type. The type name 'AddFontResource.FontUtils' already exists.

Does anyone have an idea on how to handle this?

Thanks


Solution

  • For full Unicode support, you must qualify your P/Invoke declaration with CharSet = CharSet.Unicode, which ensures that the Unicode version of the WinAPI function, i.e. AddFontResourceW, is (implicitly) referenced:

    $signature = @'
      [DllImport("gdi32.dll", CharSet = CharSet.Unicode)]
      public static extern int AddFontResource(string lpszFilename);
    '@
    
    $type =
      Add-Type -MemberDefinition $signature `
        -Name FontUtils -Namespace AddFontResource `
        -Using System.Text -PassThru
    

    Note:

    • If you get error message The type name 'AddFontResource.FontUtils' already exists., start a new session, because that implies that a previous definition of that type prevents its redefinition.