EDIT *** WORKING SOLUTION POSTED BELOW INITIAL QUESTION ***
Hello,
I think the issue with the script is my use of the -Scriptblock. It is confusing because the only variables I am using in the -Scriptblock are created there. They are not(?) local variables, but I get the error: You cannot call a method on a null-valued expression.
Here is my script:
#provide lab pc names $labPCs = @("pc1","pc2") #foreach lab $labPC, check for \tempFont directory. if false, create it and copy fonts. if true, copy new fonts to it ForEach ($pc in $labPCs) { #define $localFolder $localFolder = "\\$($pc)\c$\tempFont\" #test path to $localFolder, create and copy fonts if false, else copy fonts if (!(Test-Path -Path $localFolder)) { New-Item -ItemType Directory -Path $localFolder -Force Copy-Item -Path $newFonts -Destination $localFolder } Else { Copy-Item -Path $newFonts -Destination $localFolder } #for each font, check if it exists by name in the Fonts folder on the target machine. if not, attempt to install it... ForEach ($font in $newFonts) { if (!(Test-Path -Path ('\\'+$($pc)+'\C$\Windows\Fonts\'+$($font).Name))) { #start scriptblock Invoke-Command -ComputerName $pc -ScriptBlock { #create a new com object Shell.Application $shell = New-Object -ComObject Shell.Application #create fonts com object $fontNS = $shell.NameSpace(0x14) #grab newly copied fonts $copiedFonts = Get-ChildItem "C:\tempFont\" #create com object from that directory $copiedFontsNS = $shell.NameSpace($copiedFonts) #use CopyHere method to copy items in $copiedFonts to Fonts namespace $fontNS.CopyHere($copiedFontsNS.Items(), 0x14) } } } }
*** WORKING SOLUTION *** - my issues were a lack of understand of Invoke-Command, Scriptblock, and the asynchronous CopyHere method. I read up and understand these much better (so I stopped using CopyHere altogether :)), and now the script works great…
#grab new fonts from share $newFonts = Get-ChildItem -Path C:\path\to\newFonts -Recurse -Include *.ttf,*.otf,*.fon #provide lab pc names $labPCs = @("pc1","pc2") #foreach lab $labPC, check for \tempFont directory. if false, create it and copy fonts. if true, copy new fonts to it ForEach ($pc in $labPCs) { #define $localFolder $localFolder = "\\$($pc)\c$\tempFont\" #test path to $localFolder, create and copy fonts if false, else copy fonts if (!(Test-Path -Path $localFolder)) { New-Item -ItemType Directory -Path $localFolder -Force Copy-Item -Path $newFonts -Destination $localFolder } Else { Copy-Item -Path $newFonts -Destination $localFolder } #run the following commands on target lab PC's Invoke-Command -ComputerName $pc -ScriptBlock { #set dest path $destPath = "C:\Windows\Fonts\" #grab existing dest objects $destFiles = Get-ChildItem -Path $destPath -Recurse #set new font source path $sourcePath = 'C:\tempFont\' #use this to grab all new font source objects $sourceFiles = Get-ChildItem -Path $sourcePath -Include *.ttf,*.otf,*.fon -Recurse #set directory for placing fonts to install $fontInstall = New-Item -Path $sourcePath -ItemType Directory -Name 'Install' -Force #set path to \Fonts in registry $regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" #for each source file, see if it exists in \Fonts on the lab PC... ForEach ($s in $sourceFiles) { $regName = "$($s.Name)" #if not... if (-not(Test-Path ($destPath + $s.Name))) { #copy to the Install directory... Copy-Item -Path $s.FullName -Destination $fontInstall.FullName -Force; #grab the full path to the font in it's new location... $install = $fontInstall.FullName + '\' + $s.Name; #for each font in the Install directory, copy it to \Fonts via shell object. This copy method is asynchronous... #so I used a While loop with Start-Sleep to make sure the copy finishes before the script moves on... #logic is 'While the font to install does not exist in \Fonts, sleep the script for 1 second until the asynch copy finishes... ForEach ($i in $install) { #copy the font file to the \Fonts folder Copy-Item $i -Destination $destPath -Force #register the newly copied fonts in the registry New-ItemProperty -Path $regPath -Name $regName -Value $regName -Force | Out-Null; } #register the newly copied fonts in the registry New-ItemProperty -Path $regPath -Name $regName -Value $regName -Force | Out-Null } } #remove the Install folder from the lab PC. #Get-Item -Path $fontInstall.FullName | Remove-Item -Recurse -Force } } }