8

PrivateFontCollection.AddMemoryFont を使用してフォントをメモリに読み込み、これらを使用して画像を生成する .NET 3.5 アプリケーションがあります。最近これを Windows Server 2012 R2 にインストールしましたが、断続的なエラーが発生しています。

この問題は、次の方法で示されます。

private Bitmap getImage(byte[] fontFile)
{
    using (PrivateFontCollection fontCollection = new PrivateFontCollection())
    {
        IntPtr fontBuffer = Marshal.AllocCoTaskMem(fontFile.Length);
        Marshal.Copy(fontFile, 0, fontBuffer, fontFile.Length);
        fontCollection.AddMemoryFont(fontBuffer, fontFile.Length);

        Bitmap image = new Bitmap(200, 50);
        using (Font font = new Font(fontCollection.Families[0], 11f, FontStyle.Regular))
        {
            using (Graphics graphics = Graphics.FromImage(image))
            {
                graphics.DrawString(String.Format("{0:HH:mm:ss}", DateTime.Now), font, Brushes.White, new PointF(0f, 0f));
            }
        }
        return image;
    }
}

Windows 7 では、これは一貫して機能します。Windows Server 2012 R2 では、複数のフォントを使用して繰り返し呼び出すと失敗します。例えば:

getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Arial.ttf"));

何百回も呼び出されても動作しますが、複数のフォントで呼び出します:

getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Wingding.ttf"));
getImage(File.ReadAllBytes("c:\\Windows\\Fonts\\Arial.ttf"));

最初の数回の呼​​び出し (20 回程度) では機能しますが、ランダムな結果が生成され始めます (2 回目の呼び出しでは、テキストが翼状に表示された画像が返されることがあります。つまり、フォントが混同されています)。

DrawString呼び出しで「GDI +で一般的なエラーが発生しました」というメッセージが時々(まれに)表示されます。

Windows 7 では、これらのエラーは発生しません。

クリーンアップするためにさまざまなオプションを試しましたが、成功しませんでした。

回避策として、フォント ファイルをディスクに書き込んで AddFontFile でロードしようとしましたが、(Windows 2012 R2 では) フォント ファイルはプロセスの存続期間中ロックされるため、削除できません。これにより、このオプションは受け入れられなくなります。

AddMemoryFont を一貫して動作させるか、AddFontFile を取得してファイルのロックを解除するための助けをいただければ幸いです。

4

1 に答える 1