Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows uninstall script #347

Open
tomscholz opened this issue Mar 21, 2020 · 0 comments
Open

Windows uninstall script #347

tomscholz opened this issue Mar 21, 2020 · 0 comments

Comments

@tomscholz
Copy link

tomscholz commented Mar 21, 2020

Hello everyone,
I just made the mistake to install almost all of the fonts on my windows machine by accident. I actually wanted to just install two fonts 😅. Should've read the docs. Wow.

Anyhow, after I realized, that there isn't an uninstall script for Windows, I've puzzled together the following script on my own.

Disclaimer: I've never written PowerShell before, so please be keep that in mind before running it on your own machine😬

function Uninstall-Font {
    [CmdletBinding()]
    param(
        [parameter(mandatory=$true,ValueFromPipeline=$true)][ValidateNotNullOrEmpty()][string[]]$fontname
    )
    Begin {
        # Add functions and assemblies
        if (!("gdi.font" -as [type])){
            Add-Type -AssemblyName System.Drawing
            Add-Type -MemberDefinition '
                [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, String lParam);
                [DllImport("gdi32.dll")] public static extern int RemoveFontResource(string lpszFilename);
            ' -Namespace gdi -Name font -EA Stop
        }
        # Get installed font collection
        $installedfonts = (New-Object System.Drawing.Text.InstalledFontCollection).Families

        $myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
        $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
        $UserisAdmin = $myWindowsPrincipal.IsInRole($adminRole)
        $keyuser = get-item 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Fonts' -EA SilentlyContinue
        $keymachine = get-item 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts' -EA SilentlyContinue
    }   
    Process{
        foreach ($font in $fontname){
            if ($font -notin $installedfonts.Name){
                write-Error "Font '$font' is not installed." -Category InvalidArgument
                continue
            }
            
            if ($keyuser){
                $keyuser.Property | ?{$_ -like "$font*"} | %{
                    $file = $keyuser.GetValue($_)
                    # remove open font resources
                    write-verbose "Removing open resources for Font '$_'"
                    [gdi.font]::RemoveFontResource($file) | out-null
                    # remove registry value
                    write-verbose "Removing font registry entry with name '$_'."
                    Remove-ItemProperty $keyuser.PSPath -Name $_
                    # Remove font file
                    write-verbose "Removing font file '$file'."
                    remove-item $file -Force
                }
            }
            if ($keymachine){
                $keymachine.Property | ?{$_ -like "$font*"} | %{
                    if (!$UserisAdmin){
                        write-error "Function needs to run elevated to uninstall the font '$_' from the system!" -Category PermissionDenied
                        continue
                    }
                    $file = $keymachine.GetValue($_)
                    # remove open font resources
                    write-verbose "Removing open resources for Font '$_'."
                    [gdi.font]::RemoveFontResource($file) | out-null
                    # remove registry value
                    write-verbose "Removing font registry entry with name '$_'."
                    Remove-ItemProperty $keymachine.PSPath -Name $_
                    # Remove font file
                    write-verbose "Removing font file '$file'."
                    remove-item "$([System.Environment]::GetFolderPath(20))\$file" -Force
                }
            }
        }
    }
    
    End {
        # inform all top level windows of font-change
        write-verbose "Notify all top level windows of font-change with broadcast message."
        [gdi.font]::SendMessage(0xffff,0x001D,[IntPtr]::Zero,[IntPtr]::Zero) | out-null
    }
}

# Get the name of a font by file
function Get-FontNameFromFile([string]$file){
    Add-Type -A System.Drawing
    $fc = New-Object System.Drawing.Text.PrivateFontCollection
    $fc.AddFontFile($file)
    return $fc.Families[0].Name
}

# Select all fonts
$FontName = '*'

# Get all fonts in $FontName 
$fontFiles = New-Object 'System.Collections.Generic.List[System.IO.FileInfo]'
foreach ($aFontName in $FontName) {
    Get-ChildItem $PSScriptRoot -Filter "${aFontName}.ttf" -Recurse | Foreach-Object {$fontFiles.Add($_)}
    Get-ChildItem $PSScriptRoot -Filter "${aFontName}.otf" -Recurse | Foreach-Object {$fontFiles.Add($_)}
}

# Uninstall the fonts
foreach ($fontFile in $fontFiles) {
    $fontName = Get-FontNameFromFile $fontFile.FullName
    Uninstall-Font -FontName $fontName -Verbose
}

The script only kind of works and I would love to get some input/feedback.

Bugs:

  1. Right now, I do get a lot of Uninstall-Font : Font '********* ' is not installed., but that's probably, because I stopped the install script halfway, so not all fonts are installed.

  2. Not all fonts are getting uninstalled. When I go to the Windows 10 font settings page there are still a lot of "Powerline" fonts there. Can anybody tell me why?

Cheers,
Tom

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant