2014-10-31 2 views
4

Мы создаем большое количество шрифтов для краткого использования. Шрифты встроены в документы. Я хочу удалить файлы шрифтов, если они больше не используются. Как мы можем это сделать? Следующий упрощенный код не работает:Как удалить файл PrivateFontCollection.AddFontFile?

PrivateFontCollection pfc = new PrivateFontCollection(); 
pfc.AddFontFile(fontFile); 
FontFamily family = pfc.Families[0]; 
Console.WriteLine(family.GetName(0)); 

family.Dispose(); 
pfc.Dispose(); 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 
File.Delete(fontFile); 

Удаление файла происходит из строя, поскольку файл заблокирован. Что я могу сделать еще, чтобы освободить блокировку файлов?

PS: Перед использованием AddMemoryFont. Эта работа с Windows 7. Но с Windows 8 .NET используйте неправильные файлы шрифтов после того, как первый FontFamily был удален. Поскольку каждый документ может содержать другие шрифты, нам нужно очень большое количество шрифтов и не может содержать ссылки на все.

+1

Добавлена ​​ошибка подключения https://connect.microsoft.com/VisualStudio/feedback/details/1379843 – Peter

ответ

8

Посмотрев в коде метода AddFontFile:

public void AddFontFile(string filename) 
{ 
    IntSecurity.DemandReadFileIO(filename); 
    int num = SafeNativeMethods.Gdip.GdipPrivateAddFontFile(new HandleRef(this, this.nativeFontCollection), filename); 
    if (num != 0) 
    { 
     throw SafeNativeMethods.Gdip.StatusException(num); 
    } 
    SafeNativeMethods.AddFontFile(filename); 
} 

мы видим, что шрифт зарегистрирован в 2 раза. Сначала в GDI + и в последней строке в GDI32. Это отличается от метода AddMemoryFont. В методе Dispose он только незарегистрирован в GDI +. Это приводит к утечке в GDI32.

Чтобы компенсировать это, вы можете вызвать последующие:

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
public static extern int RemoveFontResourceEx(string lpszFilename, int fl, IntPtr pdv); 

pfc.AddFontFile(fontFile); 
RemoveFontResourceEx(tempFile, 16, IntPtr.Zero); 
+1

Для тех, кому интересно о том, что «16»: это флаг FR_PRIVATE. –

+1

Если мы применим ваше исправление, что произойдет, если MS исправляет эту ошибку? – Peter

+1

@Peter Ничего не было бы, если вы удалите шрифт, который не был добавлен. Вы можете проверить это, если вы его назовете 2 раза. Или вы называете это без AddFontFIle. – Horcrux7