Skip to content

Instantly share code, notes, and snippets.

@lpsandaruwan
Last active March 3, 2024 22:34
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lpsandaruwan/7661e822db3be37e4b50ec9579db61e0 to your computer and use it in GitHub Desktop.
Save lpsandaruwan/7661e822db3be37e4b50ec9579db61e0 to your computer and use it in GitHub Desktop.
Install a font file in Windows - Python3
""" Python 3 Windows font installer
Script must be run with the privileges in order to access Windows fonts directory. System reboot is not necessary.
This will install the font and will inform programs that a new font has been added.
Python3 Windows font installer is a free python script: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This script is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See COPYING for a copy of the GNU General Public License.
If not, see <http://www.gnu.org/licenses/>.
Copyright (C) 2017 Lahiru Pathirage <lpsandaruwan@gmail.com> 20/02/17
"""
import ctypes
import os
import shutil
import sys
from ctypes import wintypes
try:
import winreg
except ImportError:
import _winreg as winreg
user32 = ctypes.WinDLL('user32', use_last_error=True)
gdi32 = ctypes.WinDLL('gdi32', use_last_error=True)
FONTS_REG_PATH = r'Software\Microsoft\Windows NT\CurrentVersion\Fonts'
HWND_BROADCAST = 0xFFFF
SMTO_ABORTIFHUNG = 0x0002
WM_FONTCHANGE = 0x001D
GFRI_DESCRIPTION = 1
GFRI_ISTRUETYPE = 3
if not hasattr(wintypes, 'LPDWORD'):
wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD)
user32.SendMessageTimeoutW.restype = wintypes.LPVOID
user32.SendMessageTimeoutW.argtypes = (
wintypes.HWND, # hWnd
wintypes.UINT, # Msg
wintypes.LPVOID, # wParam
wintypes.LPVOID, # lParam
wintypes.UINT, # fuFlags
wintypes.UINT, # uTimeout
wintypes.LPVOID # lpdwResult
)
gdi32.AddFontResourceW.argtypes = (
wintypes.LPCWSTR,) # lpszFilename
# http://www.undocprint.org/winspool/getfontresourceinfo
gdi32.GetFontResourceInfoW.argtypes = (
wintypes.LPCWSTR, # lpszFilename
wintypes.LPDWORD, # cbBuffer
wintypes.LPVOID, # lpBuffer
wintypes.DWORD) # dwQueryType
def install_font(src_path):
# copy the font to the Windows Fonts folder
dst_path = os.path.join(
os.environ['SystemRoot'], 'Fonts', os.path.basename(src_path)
)
shutil.copy(src_path, dst_path)
# load the font in the current session
if not gdi32.AddFontResourceW(dst_path):
os.remove(dst_path)
raise WindowsError('AddFontResource failed to load "%s"' % src_path)
# notify running programs
user32.SendMessageTimeoutW(
HWND_BROADCAST, WM_FONTCHANGE, 0, 0, SMTO_ABORTIFHUNG, 1000, None
)
# store the fontname/filename in the registry
filename = os.path.basename(dst_path)
fontname = os.path.splitext(filename)[0]
# try to get the font's real name
cb = wintypes.DWORD()
if gdi32.GetFontResourceInfoW(
filename, ctypes.byref(cb), None, GFRI_DESCRIPTION
):
buf = (ctypes.c_wchar * cb.value)()
if gdi32.GetFontResourceInfoW(
filename, ctypes.byref(cb), buf, GFRI_DESCRIPTION
):
fontname = buf.value
is_truetype = wintypes.BOOL()
cb.value = ctypes.sizeof(is_truetype)
gdi32.GetFontResourceInfoW(
filename, ctypes.byref(cb), ctypes.byref(is_truetype), GFRI_ISTRUETYPE
)
if is_truetype:
fontname += ' (TrueType)'
with winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE, FONTS_REG_PATH, 0, winreg.KEY_SET_VALUE
) as key:
winreg.SetValueEx(key, fontname, 0, winreg.REG_SZ, filename)
def uninstall_font(font_name):
"""Uninstalls a Windows font.
Args:
font_name: The name of the font to uninstall.
"""
# Open the registry key for fonts.
reg_key = winreg.OpenKey(
winreg.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",
)
# Get the value for the font name.
font_value = winreg.QueryValueEx(reg_key, font_name)[0]
# Close the registry key.
winreg.CloseKey(reg_key)
# Delete the font file.
os.remove(font_value)
# Notify running programs of the font change.
user32 = ctypes.WinDLL("user32", use_last_error=True)
user32.SendMessageTimeoutW(
HWND_BROADCAST, WM_FONTCHANGE, 0, 0, SMTO_ABORTIFHUNG, 1000, None
)
def main(argv):
for arg in argv:
if arg.endswith('.otf') or arg.endswith('.ttf'):
print('Installing ' + arg)
install_font(arg)
if __name__ == '__main__':
main(sys.argv[1:])
@ineshbose
Copy link

This is awesome! Thank you for open-sourcing it under GNU GPL v3.
I'm working on a package that'll require this. You will be credited. πŸ˜„ πŸŽ‰

@Dileesha-abilash
Copy link

machan kohomada use karanne πŸ˜…(file name eka denna one kothanatada)

@lpsandaruwan
Copy link
Author

machan kohomada use karanne πŸ˜…(file name eka denna one kothanatada)

python windows_font_installer.py PATH_TO_FONT

@lpsandaruwan
Copy link
Author

This is awesome! Thank you for open-sourcing it under GNU GPL v3. I'm working on a package that'll require this. You will be credited. πŸ˜„ πŸŽ‰

Glad it helped you. πŸ‘

@Dileesha-abilash
Copy link

Thanks Its working WellπŸ‘ŒπŸ‘

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment