简体   繁体   English

Powershell 安装字体系列的脚本

[英]Powershell script to install font family

Below is my script istalling Monserrat fonts from zip file.下面是我从 zip 文件安装 Monserrat fonts 的脚本。 I can't figure how to check if a font already installed.我不知道如何检查是否已安装字体。 After installation I can open folder C:\Windows\Fonts\Montserrat and I see al of them.安装后,我可以打开文件夹 C:\Windows\Fonts\Montserrat,我会看到所有这些文件夹。 When I am running script second time, it is not recognize existance of this folder.当我第二次运行脚本时,无法识别该文件夹的存在。 Where is my mistake?我的错误在哪里?

$Source = "Montserrat.zip"
$FontsFolder = "FontMontserrat"
Expand-Archive $Source -DestinationPath $FontsFolder
$FONTS = 0x14
$CopyOptions = 4 + 16;
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.Namespace($FONTS)
$allFonts = dir $FontsFolder
foreach($File in $allFonts)
{
    If((Test-Path "C:\Windows\Fonts\Montserrat") -eq $True)
    {
        echo "Font $File already installed"
    }
    Else
    {
        echo "Installing $File"
        $CopyFlag = [String]::Format("{0:x}", $CopyOptions);
        $objFolder.CopyHere($File.fullname,$CopyFlag)
    }
}

Finally my script:最后我的脚本:

$Source = "Montserrat.zip"
$FontsFolder = "FontMontserrat"
Expand-Archive $Source -DestinationPath $FontsFolder -Force
$FONTS = 0x14
$CopyOptions = 4 + 16;
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.Namespace($FONTS)
$allFonts = dir $FontsFolder
foreach($font in Get-ChildItem -Path $fontsFolder -File)
{
    $dest = "C:\Windows\Fonts\$font"
    If(Test-Path -Path $dest)
    {
        echo "Font $font already installed"
    }
    Else
    {
        echo "Installing $font"
        $CopyFlag = [String]::Format("{0:x}", $CopyOptions);
        $objFolder.CopyHere($font.fullname,$CopyFlag)
    }
}

I am running this script by following cmd:我正在通过以下 cmd 运行此脚本:

set batchPath=%~dp0
powershell.exe -noexit -file "%batchPath%InstMontserrat.ps1"

I don't have to run it as administrator, but user have admin permissions.我不必以管理员身份运行它,但用户具有管理员权限。

Corrections of your script based on my comment assuming Windows 10 :根据我假设 Windows 10 的评论更正您的脚本:

# well-known SID for admin group
if ('S-1-5-32-544' -notin [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups) {
    throw 'Script must run as admin!'
}

$source = 'Montserrat.zip'
$fontsFolder = 'FontMontserrat'

Expand-Archive -Path $source -DestinationPath $fontsFolder

foreach ($font in Get-ChildItem -Path $fontsFolder -File) {
    $dest = "C:\Windows\Fonts\$font"
    if (Test-Path -Path $dest) {
        "Font $font already installed."
    }
    else {
        $font | Copy-Item -Destination $dest
    }
}

If you do not want to install the font on OS level but only make it available for programs to use until reboot you may want to use this script that:如果您不想在操作系统级别安装字体,而只是让它可供程序使用直到重新启动,您可能需要使用以下脚本:

  • Will fail/throw if it cannot register/unregister font.如果无法注册/取消注册字体,将失败/抛出。
  • Broadcasts WM_FONTCHANGE to inform all windows that fonts have changed广播 WM_FONTCHANGE 通知所有 windows fonts 已经改变
  • Does not require administrator privileges不需要管理员权限
  • Does not install fonts in Windows, only makes them available for all programs in current session until reboot不在Windows安装fonts,只让当前session所有程序可用,直到重启
  • Has verbose mode for debugging具有用于调试的详细模式
  • Does not work with font folders不适用于字体文件夹

Usage:用法:

register-fonts.ps1 [-v] [-unregister <PATH>[,<PATH>...]] [-register  <PATH>[,<PATH>...]] # Register and unregister at same time
register-fonts.ps1 [-v] -unregister <PATH>
register-fonts.ps1 [-v] -register <PATH>
register-fonts.ps1 [-v] <PATH> # Will register font path
Param (
  [Parameter(Mandatory=$False)]
  [String[]]$register,

  [Parameter(Mandatory=$False)]
  [String[]]$unregister
)

# Stop script if command fails https://stackoverflow.com/questions/9948517/how-to-stop-a-powershell-script-on-the-first-error
$ErrorActionPreference = "Stop"

add-type -name Session -namespace "" -member @"
[DllImport("gdi32.dll")]
public static extern bool AddFontResource(string filePath);
[DllImport("gdi32.dll")]
public static extern bool RemoveFontResource(string filePath);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam = 0, int lParam = 0);
"@

$broadcast = $False;
Foreach ($unregisterFontPath in $unregister) {
  Write-Verbose "Unregistering font $unregisterFontPath"
  # https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-removefontresourcea
  $success = [Session]::RemoveFontResource($unregisterFontPath)
  if (!$success) {
    Throw "Cannot unregister font $unregisterFontPath"
  }
  $broadcast = $True
}

Foreach ($registerFontPath in $register) {
  Write-Verbose "Registering font $registerFontPath"
  # https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-addfontresourcea
  $success = [Session]::AddFontResource($registerFontPath)
  if (!$success) {
    Throw "Cannot register font $registerFontPath"
  }
  $broadcast = $True
}

if ($broadcast) {
  # HWND_BROADCAST https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagea
  $HWND_BROADCAST = New-Object IntPtr 0xffff
  # WM_FONTCHANGE https://learn.microsoft.com/en-us/windows/win32/gdi/wm-fontchange
  $WM_FONTCHANGE  = 0x1D

  Write-Verbose "Broadcasting font change"
  # Broadcast will let other programs know that fonts were changed https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagea
  $success = [Session]::PostMessage($HWND_BROADCAST, $WM_FONTCHANGE)
  if (!$success) {
    Throw "Cannot broadcase font change"
  }
}

The script was inspired by this gisthttps://gist.github.com/Jaykul/d53a16ce5e7d50b13530acb4f98aaabd该脚本的灵感来自这个要点https://gist.github.com/Jaykul/d53a16ce5e7d50b13530acb4f98aaabd

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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