DSCResources/cFont/cFont.psm1
$CSharpCode = @' using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Runtime.InteropServices; namespace FontResource { public class AddRemoveFonts { private static IntPtr HWND_BROADCAST = new IntPtr(0xffff); [DllImport("gdi32.dll")] static extern int AddFontResource(string lpFilename); [DllImport("gdi32.dll")] static extern int RemoveFontResource(string lpFileName); [DllImport("user32.dll",CharSet=CharSet.Auto)] private static extern int SendMessage(IntPtr hWnd, WM wMsg, IntPtr wParam, IntPtr lParam); [return: MarshalAs(UnmanagedType.Bool)] [DllImport("user32.dll", SetLastError = true)] private static extern bool PostMessage(IntPtr hWnd, WM Msg, IntPtr wParam, IntPtr lParam); public static bool PostFontChangedMessage() { bool posted = PostMessage(HWND_BROADCAST, WM.FONTCHANGE, IntPtr.Zero, IntPtr.Zero); return posted; } public static int AddFont(string fontFilePath) { FileInfo fontFile = new FileInfo(fontFilePath); if (!fontFile.Exists){ return 0; } try{ int retVal = AddFontResource(fontFilePath); bool posted = PostMessage(HWND_BROADCAST, WM.FONTCHANGE, IntPtr.Zero, IntPtr.Zero); return retVal; } catch{ return 0; } } public static int RemoveFont(string fontFileName) { try{ int retVal = RemoveFontResource(fontFileName); bool posted = PostMessage(HWND_BROADCAST, WM.FONTCHANGE, IntPtr.Zero, IntPtr.Zero); return retVal; } catch { return 0; } } public enum WM : uint { FONTCHANGE = 0x001D } } } '@ Add-Type $CSharpCode # //////////////////////////////////////////////////////////////////////////////////////// # //////////////////////////////////////////////////////////////////////////////////////// function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [ValidateSet('Present', 'Absent')] [string] $Ensure = 'Present', [parameter(Mandatory = $true)] [ValidatePattern('\.(ttf|ttc|otf|fon)$')] [string] $FontFile, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $FontName, [pscredential] $Credential ) $GetRes = @{ Ensure = 'Absent' FontFile = $FontFile FontName = $FontName } $SystemFontFolder = Join-Path $Env:windir '\Fonts' $UserFontFolder = Join-Path $Env:LOCALAPPDATA '\Microsoft\Windows\Fonts' $SystemFontRegistry = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts' $UserFontRegistry = 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts' $FileName = Split-Path $FontFile -Leaf # Search system fonts if (Test-Path (Join-Path $SystemFontFolder $FileName) -PathType Leaf) { if ($Value = (Get-ItemProperty $SystemFontRegistry).PsObject.Properties | where { $_.value -eq $FileName }) { $GetRes.FontFile = $FileName $GetRes.FontName = $Value.Name $GetRes.Ensure = 'Present' } } elseif ($global:PsDscContext.RunAsUser) { # Search user fonts if (Test-Path (Join-Path $UserFontFolder $FileName) -PathType Leaf) { if ($Value = (Get-ItemProperty $UserFontRegistry).PsObject.Properties | where { $_.value -eq (Join-Path $UserFontFolder $FileName) }) { $GetRes.FontFile = $FileName $GetRes.FontName = $Value.Name $GetRes.Ensure = 'Present' } } } $GetRes } # end of Get-TargetResource # //////////////////////////////////////////////////////////////////////////////////////// # //////////////////////////////////////////////////////////////////////////////////////// function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [ValidateSet('Present', 'Absent')] [string] $Ensure = 'Present', [parameter(Mandatory = $true)] [ValidatePattern('\.(ttf|ttc|otf|fon)$')] [string] $FontFile, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $FontName, [pscredential] $Credential ) return ((Get-TargetResource @PSBoundParameters).Ensure -eq $Ensure) } # end of Test-TargetResource # //////////////////////////////////////////////////////////////////////////////////////// # //////////////////////////////////////////////////////////////////////////////////////// function Set-TargetResource { [CmdletBinding()] param ( [ValidateSet('Present', 'Absent')] [string] $Ensure = 'Present', [parameter(Mandatory = $true)] [ValidatePattern('\.(ttf|ttc|otf|fon)$')] [string] $FontFile, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $FontName, [pscredential] $Credential ) $ErrorActionPreference = 'Stop' if ($Ensure -eq 'Absent') { #Uninstall $Filename = Split-Path $FontFile -Leaf Write-Verbose ('Uninstalling font...') UnInstall-Font $Filename -ErrorAction Stop } elseif ($Ensure -eq 'Present') { #Install $private:tmpFolder = $Env:TEMP $TempFont = (Get-RemoteFile -Path $FontFile -DestinationFolder $tmpFolder -Credential $Credential -Force -PassThru -ErrorAction Stop) # TEMPフォルダに一度コピー if (Test-Path $TempFont) { try { Write-Verbose ('Installing font...') Install-Font -Path $TempFont.Fullname -Name $FontName -ErrorAction Stop Write-Verbose ('Font Installed') } catch { Write-Error $_.Exception.Message } finally { if (Test-Path $TempFont) { Remove-Item $TempFont -Force -ErrorAction SilentlyContinue } } } else { Write-Error 'Failed to copy the font file' } } } # end of Set-TargetResource # //////////////////////////////////////////////////////////////////////////////////////// # //////////////////////////////////////////////////////////////////////////////////////// function Install-Font { [CmdletBinding()] Param( [Parameter(Mandatory, Position = 0)] [ValidateScript( { Test-Path $_ })] [string] $Path, [Parameter(Mandatory, Position = 1)] [string] $Name ) $FullPath = Resolve-Path $Path -ErrorAction Stop $FileName = Split-Path $FullPath -Leaf $SystemFontFolder = Join-Path $Env:windir '\Fonts' $UserFontFolder = Join-Path $Env:LOCALAPPDATA '\Microsoft\Windows\Fonts' $SystemFontRegistry = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts' $UserFontRegistry = 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts' if ($global:PsDscContext.RunAsUser) { if (-not (Test-Path -LiteralPath $UserFontFolder -PathType Container)) { $null = New-Item $UserFontFolder -ItemType Directory -Force } Copy-Item $FullPath (Join-Path $UserFontFolder $FileName) -Force $null = New-ItemProperty $UserFontRegistry -Value (Join-Path $UserFontFolder $FileName) -Name $Name -PropertyType String -Force } else { Copy-Item $FullPath (Join-Path $SystemFontFolder $FileName) -Force $null = New-ItemProperty $SystemFontRegistry -Value $FileName -Name $Name -PropertyType String -Force } try { [void][FontResource.AddRemoveFonts]::PostFontChangedMessage() } catch { Write-Error $_.Exception.Message } } # //////////////////////////////////////////////////////////////////////////////////////// # //////////////////////////////////////////////////////////////////////////////////////// function UnInstall-Font { [CmdletBinding()] Param( [Parameter(Mandatory, Position = 0)] $FontFileName ) $SystemFontFolder = Join-Path $Env:windir '\Fonts' $UserFontFolder = Join-Path $Env:LOCALAPPDATA '\Microsoft\Windows\Fonts' $SystemFontRegistry = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts' $UserFontRegistry = 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts' $FileName = Split-Path $FontFileName -Leaf try { [void][FontResource.AddRemoveFonts]::RemoveFont($FileName) [void][FontResource.AddRemoveFonts]::PostFontChangedMessage() } catch { Write-Error $_.Exception.Message } if (Test-Path -LiteralPath $SystemFontRegistry) { if ($Value = (Get-ItemProperty $SystemFontRegistry).PsObject.Properties | where { $_.value -eq $FileName }) { Remove-ItemProperty -LiteralPath $SystemFontRegistry -Name $Value.Name } } if (Test-Path -LiteralPath $UserFontRegistry) { if ($Value = (Get-ItemProperty $UserFontRegistry).PsObject.Properties | where { $_.value -eq (Join-Path $UserFontFolder $FileName) }) { Remove-ItemProperty -LiteralPath $UserFontRegistry -Name $Value.Name } } if ((Get-Service 'FontCache').Status -eq 'Running') { Restart-Service 'FontCache' -ea SilentlyContinue } Start-Sleep -Seconds 2 if (Test-Path -LiteralPath (Join-Path $SystemFontFolder $FileName) -PathType Leaf) { Remove-Item -LiteralPath (Join-Path $SystemFontFolder $FileName) -Force } if (Test-Path -LiteralPath (Join-Path $UserFontFolder $FileName) -PathType Leaf) { Remove-Item -LiteralPath (Join-Path $UserFontFolder $FileName) -Force -ea SilentlyContinue } } # //////////////////////////////////////////////////////////////////////////////////////// # //////////////////////////////////////////////////////////////////////////////////////// function Get-RemoteFile { [CmdletBinding()] Param( [Parameter(Mandatory = $true, Position = 0)] [Alias('Uri')] [Alias('SourcePath')] [System.Uri[]] $Path, # ダウンロードするファイルパス(URI) [Parameter(Mandatory = $true, Position = 1)] [string]$DestinationFolder, # ダウンロード先フォルダ [Parameter()] [AllowNull()] [pscredential]$Credential, # 資格情報 [Parameter()] [int]$TimeoutSec = 0, [Parameter()] [switch]$Force, [Parameter()] [switch]$PassThru ) begin { if (-not (Test-Path $DestinationFolder -PathType Container)) { Write-Verbose ('DestinationFolder Folder "{0}" is not exist. Will create it.' -f $DestinationFolder) New-Item $DestinationFolder -ItemType Directory -Force -ErrorAction Stop } } Process { foreach ($private:tempPath in $Path) { try { $private:OutFile = '' $private:valid = $true $private:tmpDriveName = [Guid]::NewGuid() if ($tempPath.IsLoopback -eq $null) { $valid = $false throw ('{0} is not valid uri.' -f $tempPath) } # ファイルの場所によって処理分岐(ローカル or 共有フォルダ or Web) if ($tempPath.IsLoopback -or $tempPath.IsUnc) { # ローカル or 共有フォルダ # 資格情報を使う場合は一度ドライブをマップする必要あり if ($PSBoundParameters.Credential) { New-PSDrive -Name $tmpDriveName -PSProvider FileSystem -Root (Split-Path $tempPath.LocalPath) -Credential $Credential -ErrorAction Stop | Out-Null } # ローカルにコピーする $OutFile = Join-Path $DestinationFolder ([System.IO.Path]::GetFileName($tempPath.LocalPath)) if (Test-Path $OutFile -PathType Leaf) { if ($tempPath.LocalPath -eq $OutFile) { if ($PassThru) { if (Test-Path $OutFile) { Get-Item $OutFile } } continue } elseif ($Force) { Write-Warning ('"{0}" will be overwritten.' -f $OutFile) } else { $valid = $false throw ("'{0}' is exist. If you want to replace existing file, Use 'Force' switch." -f $OutFile) } } Write-Verbose ("Copy file from '{0}' to '{1}'" -f $tempPath.LocalPath, $DestinationFolder) Copy-Item -Path $tempPath.LocalPath -Destination $DestinationFolder -ErrorAction Stop -Force:$Force } elseif ($tempPath.Scheme -match 'http|https|ftp') { # WebからDL $OutFile = Join-Path $DestinationFolder ([System.IO.Path]::GetFileName($tempPath.AbsoluteUri)) if (Test-Path $OutFile -PathType Leaf) { if ($Force) { Write-Warning ('"{0}" will be overwritten.' -f $OutFile) } else { $valid = $false throw ("'{0}' is exist. If you want to replace existing file, Use 'Force' switch." -f $OutFile) } } Write-Verbose ("Download file from '{0}' to '{1}'" -f $tempPath.AbsoluteUri, $OutFile) $private:origVerbose = $VerbosePreference; $VerbosePreference = 'SilentlyContinue' Invoke-WebRequest -Uri $tempPath.AbsoluteUri -OutFile $OutFile -Credential $Credential -TimeoutSec $TimeoutSec -ErrorAction stop $VerbosePreference = $origVerbose } else { $valid = $false throw ('{0} is not valid uri.' -f $tempPath) } if ($valid -and $OutFile -and $PassThru) { if (Test-Path $OutFile) { Get-Item $OutFile } } } catch [Exception] { Write-Error $_.Exception.Message } finally { if (Get-PSDrive | where { $_.Name -eq $tmpDriveName }) { Remove-PSDrive -Name $tmpDriveName -Force } } } } } # //////////////////////////////////////////////////////////////////////////////////////// # //////////////////////////////////////////////////////////////////////////////////////// Export-ModuleMember -Function *-TargetResource |