简体   繁体   中英

Cannot install fonts with Powershell on Windows 10

On my work computer, I don't have admin privileges.

Installing new fonts cannot be done "the easy way".

At the time I was using Windows 7, I managed to run a PowerShell script that was launched at session startup and that installed the fonts from a given folder.

Here is the code I used:

add-type -name Session -namespace "" -member @"
[DllImport("gdi32.dll")]
public static extern int AddFontResource(string filePath);
"@

$FontFolder = "C:\Users\myusername\Documents\Fonts"

$null = foreach($font in Get-ChildItem -Path $FontFolder -Recurse -Include *.ttf, *.otg, *.otf) {
    Write-Host "Installing : $($font.FullName)"
    $result = [Session]::AddFontResource($font.FullName)
    Write-Host "Installed $($result) fonts"
}

Now that I have switched to Windows 10, I thought I could go back to installing fonts "the easy way", as it is supposed to be possible to install fonts for your user without admin privileges.

This however still does not work: there is a popup window saying that "The requested file is not a valid font file". One solution is apparently to start the Windows firewall , which of course is not allowed by my administrator... but it is already running (see Edit below)

Back to the PowerShell then. The script unfortunately does not work anymore and does not provide any interesting pointers to where the problem comes from:

Installing : C:\Users\myusername\Documents\Fonts\zilla-slab\ZillaSlab-SemiBold.otf
Installed 0 fonts
Installing : C:\Users\myusername\Documents\Fonts\zilla-slab\ZillaSlab-SemiBoldItalic.otf
Installed 0 fonts
Installing : C:\Users\myusername\Documents\Fonts\zilla-slab\ZillaSlabHighlight-Bold.otf
Installed 0 fonts

I tried using a try catch, but still have no identified error:

add-type -name Session -namespace "" -member @"
[DllImport("gdi32.dll")]
public static extern int AddFontResource(string filePath);
"@

$FontFolder = "C:\Users\myusername\Documents\Fonts"

$null = foreach($font in Get-ChildItem -Path $FontFolder -Recurse -Include *.ttf, *.otg, *.otf) {
    try {
        Write-Host "Installing : $($font.FullName)"
        $result = [Session]::AddFontResource($font.FullName)
        Write-Host $result
    }
    catch {
        Write-Host "An error occured installing $($font)"
        Write-Host "$($error)"
        Write-Host "$($error[0].ToString())"
        Write-Host ""
        1
    }   
}

And the resulting output

Installing : C:\Users\myusername\Documents\Fonts\zilla-slab\ZillaSlabHighlight-Bold.otf
0
Installing : C:\Users\myusername\Documents\Fonts\zilla-slab\ZillaSlabHighlight-Regular.otf
0
Installing : C:\Users\myusername\Documents\Fonts\ZillaSlab-Light.otf
0

Any idea how to solve this issue?

Edit:

Regarding the status of the security applications, here is the McAfee status:

McAfee Data Exchange Layer OK 
McAfee DLP Endpoint OK 
Programme de mise à jour McAfee OK 
McAfee Endpoint Security OK 

"Programme de mise à jour" means "update program" in French.

I also checked the list of running services:

  • mpssvc service (Windows defender firewall) is running
  • mfefire (McAfee Firewall core service) is not running

Edit2:

My last attempt is the following:

  • I copied the font file manually to the $($env:LOCALAPPDATA)\Microsoft\Windows\Fonts\ folder
  • Using regedit, I added the entry as shown below

在此处输入图像描述

I restarted. Still no Bebas font in WordPad or Publisher

Here's how I do it with a com object. This works for me as non-admin based on Install fonts without administrative privileges . I can see the fonts installed to "$env:LOCALAPPDATA\Microsoft\Windows\Fonts" in the Fonts area under Settings. I have Windows 10 20H2 (it should work in 1803 or higher). I also see the fonts installed in Wordpad.

$Destination = (New-Object -ComObject Shell.Application).Namespace(20)

$TempFolder = "$($env:windir)\Temp\Fonts\"

New-Item -Path $TempFolder -Type Directory -Force | Out-Null

Get-ChildItem -Path $PSScriptRoot\fonts\* -Include '*.ttf','*.ttc','*.otf' | 
  ForEach {
    If (-not(Test-Path "$($env:LOCALAPPDATA)\Microsoft\Windows\Fonts\$($_.Name)")) {

        $Font = "$($env:windir)\Temp\Fonts\$($_.Name)"

        Copy-Item  $($_.FullName) -Destination $TempFolder
        
        $Destination.CopyHere($Font)

        Remove-Item $Font -Force

    } else { "font $($env:LOCALAPPDATA)\Microsoft\Windows\Fonts\$($_.Name) already installed" }

}

Example REG_SZ registry entry:

dir 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Fonts*' | ft -a


    Hive: HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion


Name  Property
----  --------
Fonts Nunito Black (TrueType) : C:\Users\myuser\AppData\Local\Microsoft\Windows\Fonts\Nunito-Black.ttf

You can install fonts on windows using following powershell scripts.

param(
[Parameter(Mandatory=$true,Position=0)]
[ValidateNotNull()]
[array]$pcNames,
[Parameter(Mandatory=$true,Position=1)]
[ValidateNotNull()]
[string]$fontFolder
)
$padVal = 20
$pcLabel = "Connecting To".PadRight($padVal," ")
$installLabel = "Installing Font".PadRight($padVal," ")
$errorLabel = "Computer Unavailable".PadRight($padVal," ")
$openType = "(Open Type)"
$regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"
$objShell = New-Object -ComObject Shell.Application
if(!(Test-Path $fontFolder))
{
    Write-Warning "$fontFolder - Not Found"
}
else
{
    $objFolder = $objShell.namespace($fontFolder)
    foreach ($pcName in $pcNames)
    {
        Try{
            Write-Output "$pcLabel : $pcName"
            $null = Test-Connection $pcName -Count 1 -ErrorAction Stop
            $destination = "\\",$pcname,"\c$\Windows\Fonts" -join ""
            foreach ($file in $objFolder.items())
            {
                $fileType = $($objFolder.getDetailsOf($file, 2))
                if(($fileType -eq "OpenType font file") -or ($fileType -eq "TrueType font file"))
                {
                    $fontName = $($objFolder.getDetailsOf($File, 21))
                    $regKeyName = $fontName,$openType -join " "
                    $regKeyValue = $file.Name
                    Write-Output "$installLabel : $regKeyValue"
                    Copy-Item $file.Path  $destination
                    Invoke-Command -ComputerName $pcName -ScriptBlock { $null = New-ItemProperty -Path $args[0] -Name $args[1] -Value $args[2] -PropertyType String -Force } -ArgumentList $regPath,$regKeyname,$regKeyValue
                }
            }
        }
        catch{
            Write-Warning "$errorLabel : $pcName"
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM