10

一連のフォントをフォントの特別なフォルダに自動的かつサイレントに移動して、エクスプローラから「インストール」したかのように使用できるようにするスクリプトを作成しようとしています(ドラッグアンドドロップ、コピー、または右クリックして[インストール]を選択します)。 )。私はShell.Applicationコピーまでずっとその部分を持っています。

$FONTS = 0x14
$shell = New-Object -ComObject Shell.Application
$source = $shell.Namespace($downloaded_path)
$target = $shell.Namespace($FONTS)
$target.CopyHere($source.Items())

ただし、一部のシステムにはすでにフォントがインストールされている可能性があり、進行状況ダイアログを非表示にして、プロンプトを黙って受け入れるようにします。

フォントのインストール フォントはすでにインストールされています

それで、私はFolder.CopyHereオプションフラグを調査しています。

  • 4進行状況ダイアログボックスを表示しない
  • 16表示されるダイアログボックスについては、「すべてはい」と応答してください。

このフォルダでサポートされていることを願っています(一部のオプションは設計上無視されています)。そして、これらは10進数だと思いますよね?それらを変換する必要がありますか?それらを渡しても、両方のダイアログが表示されます。私が試してみました

$options = 4           <-- don't expect int to work
$options = 0x4         <-- thought hexidecimal would be ok, the VB documentation shows &H4&
$options = "4"         <-- string's the thing?
$options = [byte]4     <-- no luck with bytes
$options = [variant]4  <-- this isn't even a type accelerator!

また、1つのオプションを機能させることができる場合、両方を機能させるにはどうすればよいですか?私はbor一緒にいますか?フォーマットはどうですか?

$options = 4 -bor 16

または、それらを追加するか、16進数に変換しますか?

$options = "{0:X}" -f (4 + 16)
4

8 に答える 8

4

を使用できます4 -bor 16。タイプがVARIANTであるため、このメソッドが何を期待するかを判断するのは困難です。整数値を取ると思っていたでしょう。それが機能しない場合は、Folder.CopyHereのMSDNトピックからのこのコメントは、文字列が機能する必要があることを意味します。

function CopyFileProgress
{
    param( $Source, $DstFolder, $CopyType = 0 )

    # Convert the decimal to hex
    $copyFlag = [String]::Format("{0:x}", $CopyType)

    $objShell = New-Object -ComObject "Shell.Application"
    $objFolder = $objShell.NameSpace($DestLocation) 
    $objFolder.CopyHere($Source, $copyFlag)
}

フォーマット文字列はどうあるべきかしら"0x{0:x}"

通常の.NETフラグスタイルの列挙型の場合、次のように列挙型に強く型付けされた.NET(またはコマンドパラメータ)に複数のフラグを渡すことができることに注意してください。

$srv.ReplicationServer.Script('Creation,SomeOtherValue')

Oisinは、このブログ投稿にこのテーマに関するいくつかの情報を書いています。

于 2012-08-28T19:16:31.860 に答える
3

私は同じ問題を抱えていて、これを別のスレッドで見つけました。私にとっては完璧に機能しました。

上書きしてサイレントにする場合は、0x10を0x14に変更します(ドキュメント)。

$destinationFolder.CopyHere($zipPackage.Items(), 0x14)
于 2013-10-15T21:02:22.940 に答える
2

Folder.CopyHereオプションフラグは単に機能しない可能性があります。これは私を悲しくさせます。私はこれらの他の方法の1つを調査する必要がありますが、それらはすべて私を少し拘束します。

別のプロセス

新しいプロセスでコピーを呼び出し、ProcessStartInfoプロパティを使用してウィンドウを非表示にします。私はまだこれを実装していませんが、既存のファイルを上書きするためのユーザープロンプトに対処できるのでしょうか?

Dim iProcess As New System.Diagnostics.ProcessStartInfo(AppDomain.CurrentDomain.BaseDirectory + “unzip.exe”)

iProcess.CreateNoWindow = True
Dim sArgs As String = ZippedFile
iProcess.Arguments = sArgs
iProcess.WindowStyle = ProcessWindowStyle.Hidden
Dim p As New System.Diagnostics.Process
iProcess.UseShellExecute = False
p = System.Diagnostics.Process.Start(iProcess)
p.WaitForExit(30000)
Dim s As Integer = p.ExitCode
iProcess.UseShellExecute = True

p.Dispose()
iProcess = Nothing

Forループ

存在しないアイテムのみをコピーします。既存のフォントを同じ名前の新しいフォントファイルで実際に更新したい場合、これは失敗するようです。

foreach($File in $Fontdir) {
    $fontName = $File.Name.Replace(".ttf", " Regular")
    $objFolderItem = $objFolder.ParseName($fontName);
    if (!$objFolderItem) {
      $objFolder.CopyHere($File.fullname,0x14)
    }
}

既存のものを削除

コピーしているフォントと同じ名前のフォントをすべて削除してから、セットをコピーすることを考えています。それはちょっと残酷ですが。また、使用中のためにそのフォントを削除できない場合は、別のプロンプトが表示されると思います。はぁ

于 2012-08-29T03:21:11.377 に答える
2

コピーフラグは私には機能しません。「フォントのインストール」ウィンドウを検出して送信するフォントのインストールスクリプトでジョブを設定し、{Enter}既存のフォントを上書きしないようにします。

Start-Job –Name DetectAndClosePrompt –Scriptblock {
  $i=1
  [void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")
  [void] [System.Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
  while ($i -eq 1) { 
    $windowPrompt = Get-Process -ErrorAction SilentlyContinue |? {$_.MainWindowTitle -like "*Installing Fonts*"} 
    [Microsoft.VisualBasic.Interaction]::AppActivate($windowPrompt.ID)
    [System.Windows.Forms.SendKeys]::SendWait("{Enter}")
    sleep 2 
  }
}

すべてのフォントがコピー/インストールされたら...名前でジョブを削除します。

Get-Job DetectAndClosePrompt | Remove-Job -Force

これは、Windows 7、8.x、および10で機能します。

于 2015-05-13T10:24:27.910 に答える
1

いくつかのUnzipフォルダー操作が表示されますが、Fontsフォルダーの状況に合うソリューションを作成している人は実際には誰もいません。だから私は自分で書いた!実は、FontsフォルダーはShell.Folder.CopyHereメソッドを実装していますが、メソッドの2番目の引数に渡されたオーバーロードを尊重していません。なんで?知るか!「 TheOldnewThing WindowsDeveloperブログのRaymondChenがそれを説明できると思いますが、答えはわかりません。したがって、フォントをコピーする前に、フォントをインテリジェントに探す必要があります。そうしないと、厄介なメッセージが表示されます。


私のコードでは、ワイルドカード検索を使用してフォント名の最初の4文字が一致するかどうかを確認することにより、フォントが存在するかどうかを確認します。フォントが存在しない場合は、このシステムにフォントをインストールするのはこれが初めてであると想定し、$FirstInstallという特別なフラグを設定します。

それ以降、スクリプトで$ FirstInstallがtrueの場合、すべてのフォントをソースフォントディレクトリにインストールします。その後の実行では、各フォントが一致するかどうかを確認し、一致する場合は、そのコピーを中止します。そうでない場合は、先に進んでコピーします。これまでのところ、これは私のクライアントのほとんどで機能しているようです。

どうぞ!

    <#
.SYNOPSIS
    Script to quietly handle the installation of fonts from a network source to a system

.DESCRIPTION
    We Can't just move files into the %windir%\Fonts directory with a script, as a simple copy paste from command line doesn't trigger windows to note the new font
If we used that approach, the files would exist within the directory, but the font files woudln't be registered in windows, nor would applications 
display the new font for use.  Instead, we can make a new object of the Shell.Application type (effectively an invisible Windows Explorer Windows) and use its Copy method
Which is the functional equivalent of dragging an dropping font files into the Font folder, which does trigger the font to be installed the same as if you right clicked the font
and choose install.

.PARAMETER FontPath
    The path of a folder where fonts reside on the network

.EXAMPLE
    .\Install-Fonts.ps1 -FontPath "\\corp\fileshare\Scripts\Fonts"

    Installing font...C:\temp\Noto\NotoSans-Bold.ttf
    Installing font...C:\temp\Noto\NotoSans-BoldItalic.ttf
    Installing font...C:\temp\Noto\NotoSans-Italic.ttf
    Installing font...C:\temp\Noto\NotoSans-Regular.ttf

    In this case, the fonts are copied from the network down to the system and installed silently, minus the logging seen here
    import files needed for step 1, step 2, and step 5 of the migration process.

.EXAMPLE
    .\Install-Fonts.ps1 -FontPath "\\corp\fileshare\Scripts\Fonts"

    Font already exists, skipping
    Font already exists, skipping
    Font already exists, skipping
    Font already exists, skipping
    In this case, the fonts already existed on the system.  Rather than display an annoying 'Overwrite font' dialog, we simply abort the copy and try the next file


.INPUTS
    String.

.OUTPUTS
    Console output

.NOTES
    CREATED: 06/11/2015
    Author: sowen@ivision.com

    MODIFIED:06/11/2015
    Author: sowen@ivision.com   -Reserved...

#> 
param
    ( 
        [Parameter(Mandatory)][string]$FontPath="C:\temp\Noto" 
    ) 

#0x14 is a special system folder pointer to the path where fonts live, and is needed below. 
$FONTS = 0x14

#Make a refrence to Shell.Application
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.Namespace($FONTS)

ForEach ($font in (dir $fontsPath -Recurse -Include *.ttf,*.otf)){

    #check for existing font (to suppress annoying 'do you want to overwrite' dialog box
    if ((($objShell.NameSpace($FONTS).Items() | where Name -like "$($font.BaseName.Split('-')[0].substring(0,4))*") | measure).Count -eq 0){
        $firstInstall = $true}

    if ($firstInstall -ne $true) {Write-Output "Font already exists, skipping"}

        else{    
        $objFolder.CopyHere($font.FullName)
        Write-Output "Installing font...$($font.FullName)"
        $firstInstall = $true
        }

    }

.\Install-Fonts.ps1 -FontPath "\\corp\fileshare\Scripts\Fonts"
于 2015-06-11T16:48:05.210 に答える
0

あなたはただあなたのオプションの合計を取ることができます。2つのオプション(SILENTとNOCONFIRMATION)を指定してCopyHereを実行する必要がありました。以下のサンプルを見てください。

function Unzip-Archive($targetpath, $destination)
{    
    $shell_app=new-object -com shell.application

    $FOF_SILENT_FLAG = 4
    $FOF_NOCONFIRMATION_FLAG = 16

    $zip_file = $shell_app.namespace("$targetpath")

    #Set the destination directory for the extracts
    $destination = $shell_app.namespace("$destination")

    #unzip the files
    $destination.Copyhere($zip_file.items(), $FOF_SILENT_FLAG + $FOF_NOCONFIRMATION_FLAG)    
}
于 2013-06-27T08:16:33.397 に答える
0

@FoxDeployの回答にはいくつかの問題があり、それが機能しない理由です。最初の問題は、%USERPROFILE%のFontsフォルダーも確認する必要があることです。そうしないと、確認ダイアログが表示されます。2番目の問題は、フォント名に「-」を使用しないようにすることです。

以下は、例としてCodeFontsリポジトリからフォントをインストールする修正バージョンです。

$ErrorActionPreference = "Stop"
Add-Type -AssemblyName System.Drawing

# Clone chrissimpkins/codeface from which we will install fonts
if (!(Test-Path /GitHubSrc/codeface)){
    git clone git://github.com/chrissimpkins/codeface.git /GitHubSrc/codeface
}

#0x14 is a special system folder pointer to the path where fonts live, and is needed below. 
$FONTS = 0x14
$fontCollection = new-object System.Drawing.Text.PrivateFontCollection

#Make a refrence to Shell.Application
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.Namespace($FONTS)

# local path

$localSysPath = "$Env:USERPROFILE\AppData\Local\Microsoft\Windows\Fonts"
$localSysFonts = Get-ChildItem -Path $localSysPath -Recurse -File -Name | ForEach-Object -Process {[System.IO.Path]::GetFileNameWithoutExtension($_)}

$fontsPath="\GitHubSrc\codeface\fonts"
ForEach ($font in (dir $fontsPath -Recurse -Include *.ttf,*.otf)){
    if ($localSysFonts -like $font.BaseName) {
        Write-Output "SKIP: Font ${font} already exists in ${localSysPath}"
    }
    else {
        $fontCollection.AddFontFile($font.FullName)
        $fontName = $fontCollection.Families[-1].Name

        #check for existing font (to suppress annoying 'do you want to overwrite' dialog box
        if ((($objShell.NameSpace($FONTS).Items() | where Name -ieq $fontName) | measure).Count -eq 0){
            Write-Output "INST: Font ${font}"
            $objFolder.CopyHere($font.FullName)
            $firstInstall = $true
        }
        else {
            Write-Output "SKIP: Font ${font} already exists in SYSTEM FONTS"
        }
    }
    # Read-Host -Prompt "Press Enter to continue"
}
于 2019-12-06T00:46:44.100 に答える
-1

+ieを使用するだけでこれが機能するようになりました

function Expand-ZIPFile($file, $destination)
{
    $shell = new-object -com shell.application
    $zip = $shell.NameSpace($file)
    foreach($item in $zip.items())
    {
        $shell.Namespace($destination).copyhere($item, 16+1024)
    }
} 
于 2014-11-21T20:24:24.880 に答える