Can't remove Windows fonts using this powershell script - powershell

I'm totally noob in powershell scripting. Trying to remove some fonts that are installed on the system. I saved the fonts in the following folder "C:\Temp\fonts\fonts-to-be-installed". The script should find the font name in that folder and remove the matching fonts from registry and C:\Windows\Fonts folder. However, when I run this script it doesn't work. I don't get any error messages. Wondering whats's missing here. Any hints would be appreciated.
# Remove fonts
$Fontstoberemoved = Get-ChildItem -Path "C:\Temp\fonts\fonts-to-be-installed\" | Where-Object Name -Like "*.ttf"
foreach ($font in $Fontstoberemoved) {
Write-Output "Deleting item: 'C:\Windows\Fonts\$font.Name'"
Remove-Item -Path "C:\Windows\Fonts\$font.Name" -Force
Write-Output "Deleting item: 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts\$font.Name'"
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" -Name $font.Name -Force
}
I've just modified the script to remove the fonts from one more location as below:
**Remove-Item -Path "$env:LOCALAPPDATA\Microsoft\Windows\Fonts\$font" -Force**
Now I'm getting the following error message:
"Remove-Item : Cannot find path 'C:\Users\xxxx\AppData\Local\Microsoft\Windows\Fonts\Linotype - NHaasGroteskTXPro-56It.ttf' because it does not exist. At line:4 char:1
+ Remove-Item -Path "$env:LOCALAPPDATA\Microsoft\Windows\Fonts\$font" - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\xxxx...kTXPro-56It.ttf:String) [Remove-Item], ItemNotFoundEx ception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand"
The fonts are still in that folder. When I try to manually delete the fonts I get a warning message that the file is open in system. Wondering how to detect which process is using the fonts?

Related

Remove-Item command is not removing a folder and its contents

I have an application that will be un installed across our estate, so I am creating a PowerShell script to do this (it will be distributed through Intune). However after the uninstall a folder and 2 files remain. I added in Remove-Item but it will not remove the folder and content even with -Force and -Recurse included as it states it is in use, but I can manually delete the folder and contents without any issues.
My script is (I have changed sensitive information)
$FileName = "C:\Users\$env:USERNAME\AppData\Local\my_app\app1.exe"
if (Test-Path $FileName) {
Write-Host "File Exists"
}
else
{
Write-Host "File Doesn't Exists"
exit
}
cd "C:\Users\$env:USERNAME\AppData\Local\my_app"
.\Update.exe --uninstall
Remove-Item -Path C:\Users\$env:USERNAME\AppData\Local\my_app -Force -Recurse
The actual error states
Remove-Item : Cannot remove the item at 'C:\Users\superuser\AppData\Local\my_app' because it is in use
At line:21 char:1
+ Remove-Item -Path C:\Users\$env:USERNAME\AppData\Local\my_app - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Remove-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RemoveItemCommand
You change locations into the same directory you are trying to delete. You need to change out of that directory. You have a few options here:
The Obvious Solution (Once You Know the Issue)
Change out of the directory:
cd .. # any path that is not part of the directory tree you want to delete
But PowerShell has some more useful ways to traverse directories. Read on for more information.
Solution 2: Windows PowerShell - Use the Location Stack
Opt for using Push-Location and Pop-Location instead of cd (aliased to Set-Location).Push/Pop-Location use the location stack. Use Push-Location to change to new directories and Pop-Location to walk backwards. In your case, this would work:
Push-Location "C:\Users\$env:USERNAME\AppData\Local\my_app"
.\Update.exe --uninstall
Pop-Location # This will return to the previous directory
Remove-Item -Path C:\Users\$env:USERNAME\AppData\Local\my_app -Force -Recurse
Solution 3: PowerShell Core - Use cd -
If you can utilize PowerShell Core, the same concept applies but PowerShell Core supports the bash-like cd - and cd + since version 6.2. Similar to using Push/Pop-Location, you can walk backwards and forwards to the directories you've been to. In your case, cd - would work like so:
cd "C:\Users\$env:USERNAME\AppData\Local\my_app"
.\Update.exe --uninstall
cd - # This will return to the previous directory
Remove-Item -Path C:\Users\$env:USERNAME\AppData\Local\my_app -Force -Recurse
From the Set-Location documentation for PowerShell Core:
PowerShell 6.2 added support for - and + as a values for the Path parameter. PowerShell maintains a history of the last 20 locations that can be accessed with - and +. This list is independent from the location stack that is accessed using the StackName parameter.

Rename file before copy to certain folder

I´m a newbie still and learning to create PowerShell scripts to make Life in IT easier.
At present I´m trying to build a script, which runs a certain Microsoft tool, scanning defined network shares in a csv file and creating an JSON output file.
Now as the pattern of this file is always the same like "Report_Username_Hostname.vba.JSON", I would like to append either the scanned directory name or even a range of numbers, fe. "Report_Username_Hostname(100).vba.JSON" or "Report_Username_Hostname(sharename).vba.JSON"
This is neccessaray as after this renaming step, I upload this and other files within this folder to another folder on different server to upload them into a Database.
I planned to run this script in in many different locations on most automatic level and they all copy the their collected files to just one upload folder.
I already tried several options I found somewhere in the deep of the Internet, but I only came to the point where the file was renamed to 0 or similar, but not to expected result.
The Powershell script doing the work is this:
$PSpath = 'C:\temp\FileRemediation\Scripts\'
$Rpath = $PSpath +'..\Reports\1st'
$localshare = $PSpath +'..\temp\1st'
$csvinputs = Import-Csv $PSpath\fileremediation_1st.csv
$uploadshare = '\\PGC2EU-WFSFR01.eu1.1corp.org\upload\'
# This section checks if the folder for scan reports is availabe and if not will create necessary folder.
If(!(test-path $Rpath))
{
New-Item -ItemType Directory -Force -Path $Rpath
}
If(!(test-path $localshare))
{
New-Item -ItemType Directory -Force -Path $localshare
}
Set-Location $Rpath
# This section reads input from configuration file and starts Ms ReadinessReportCreator to scan shares in configuration file.
ForEach($csvinput in $csvinputs)
{
$uncshare = $csvinput.sharefolder
$Executeable = Start-Process "C:\Program Files (x86)\Microsoft xxx\xxx.exe" `
-Argumentlist "-p ""$uncshare""", "-r", "-t 10000", "-output ""$localshare"""`
-Wait
Get-ChildItem -Path $localshare -Filter '*.JSON' | Rename-Item -NewName {$_.FullName+$uncshare}
}
# This section copies the output *.JSON file of the xxx to the share, where I they will be uploaded to DB.
Get-ChildItem -Path $localshare -Filter '*.JSON' | Where {$_.Length -ge 3} | move-item -Destination '$uploadshare'
the fileremediation_1st.csv looks like
sharefolder
\\server\sharename
Can someone please help me on this, I don´t have a clue what I´m doing wrong.
Thank you!
Current error I get is
Rename-Item : Cannot rename the specified target, because it
represents a path or device name. At
C:\temp\FileRemediation\scripts\fileremediation_V2_1st.ps1:28 char:55
+ ... share -Filter '*.JSON' | Rename-Item -NewName {$_.FullName+$uncshare}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
As said before, I would also be fine with a dedicated range of numbers, which is append to the file name "Report_Username_Hostname(100).vba.JSON"
The perfect world would be if I could split the \server\sharename from csv file and append the sharename to my filename.
I think the issue is with:
Rename-Item -NewName {$_.FullName+$uncshare}
Your input file (Get-ChildItem) path is:
$PSpath = 'C:\temp\FileRemediation\Scripts\'
$localshare = $PSpath +'..\temp\1st'
The Rename-Item uses $_.FullName which resolves to something like this:
C:\temp\FileRemediation\Scripts\..\temp\1st\MyFile.JSON
The variables then contain:
$_.FullName = C:\temp\FileRemediation\Scripts\..\temp\1st\MyFile.JSON
$uncshare = "\\server\sharename"
So Your Rename-Item ... $_.FullName+$uncshare will try to rename it to:
C:\temp\FileRemediation\Scripts\..\temp\1st\MyFile.JSON\\server\sharename
Which is not a valid path.

Powershell Remove-Item Cmdlet error

I'm using powershell to remove a directory with the command:
Remove-Item $pathAsString -Recurse -Force
However, it gives me the following error:
Remove-Item : Cannot remove the item at 'C:\Path' because it is in use.
At line:1 char:1
+ Remove-Item "C:\Path" -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Remove-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RemoveItemCommand
I thought that was odd, because the directory shouldn't be in use. I can go into file explorer and delete the directory manually. I'm not really sure why this behavior is occurring. I'm fairly new to powershell, so don't understand exactly how it behaves.
My scripts interaction with the program includes:
Creating the folder
Downloading an MSI to the folder
Setting a variable to represent the MSI stored in the folder. Like so:
$MSIVariable = Get-ChildItem $Path | Where {&_.Name -eq "MSIName.msi"}
I'm assuming that something to do with the folder is within a stream of some sort, but don't know how I'd fix this issue.
EDIT:
Here is the code I use involving the folder:
Creating the Folder:
if(!(Test-Path $MSILocation))
{
New-Item $MSILocation -ItemType directory
}
Downloading the MSI:
$webClient = (New-Object System.Net.WebClient)
$downloadLocation = Join-Path $MSILocation $MSIName
$webClient.DownloadFile($downloadURL, $downloadLocation)

I need to remove folders by a specific name, if it exist

I have a file server where the users have their own diskspace. And I need to delete a certain folder on each users diskspace, but not all users have this folder. Also the users are divided into department, so the layout of the folders looks like this:
D:\users\departmentA\usernameA\foldertodelete
D:\users\departmentA\usernameB\foldertodelete
D:\users\departmentB\usernameC\foldertodelete
D:\users\departmentC\usernameD\foldertodelete
...
How can I make this happen? Im thinking of using Poweshell, and I have been reading about Test-Path, but I dont know how to work with this then the path is different for all the users.
This is fairly straightforward with PowerShell:
$TargetName = "foldertodelete"
$BaseDir = "D:\Users"
# Iterate over each department directory
foreach($Department in #(Get-ChildItem $BaseDir -Directory)){
# Within each department, iterate over each user directory
foreach($User in #(Get-ChildItem $Department -Directory)){
# Check if the undesirable folder exists
if([System.IO.Directory]::Exists(($TargetPath = Join-Path -Path $User -ChildPath $TargetName))){
# If so, remove the directory and all child items
Remove-Item $TargetPath -Recurse
}
}
}
The -Directory parameter on Get-ChildItem is available in PowerShell 3.0 and above. For PowerShell 2.0 you could use:
Get-ChildItem $BaseDir |Where {$_.PSIsContainer}
Thank you for your answer. I do have some problem making the script work. It looks like the script don't understand the BaseDir part. The department folder where the users have their folder is located on D:\Users. I copied the script to C:\skript. And the error message show that it is looking for the userfolder on my C drive. It should look on D:\users\AAL-users\username
Here is the error message:
PS C:\skript> .\RemoveFolder.ps1
Get-ChildItem : Cannot find path 'C:\skript\AAL-users' because it does not exist.
At C:\skript\RemoveFolder.ps1:7 char:22
+ foreach($User in #(Get-ChildItem $Department -Directory)){
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\skript\AAL-users:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
I did try to copy the script to my D:\users folder. This time I got no error messages, but the script did not delete any folders as it is suposed to.
Try the below...
Remove-Item -path D:\Users\* -Filter *specificnameof the folder* -WhatIf --(Whatif allows you to test a command before you run)
Remove whatif and execute the delete
Remove-Item -path C:\users\* -Filter *specificnameof the folder*
Here is the exact code I run now:
PS D:> Remove-Item -path "D:\DU Users*" -Filter notes85
PS D:>
No error messages, but also, the folder in question is not removed.

Delete broken link

I need to delete all the content of a folder which may include broken links among others. The folder path is provided by a variable. Problem is that PowerShell fails to remove the broken links.
$folderPath = "C:\folder\"
Attempt 1:
Remove-Item -Force -Recurse -Path $folderPath
Fails with error:
Remove-Item : Could not find a part of the path 'C:\folder\brokenLink'.
At line:1 char:1
+ Remove-Item -Force -Recurse -Path $folderPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\folder\brokenLink:String) [Remove-Item], DirectoryNot
FoundException
+ FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Attempt 2:
Start-Job { cmd /c rmdir $folderPath }
Fails because $folderPath gets passed as is instead of its value:
Start-Job { cmd /c rmdir $folderPath } | select command
Command
-------
cmd /c rmdir $folderPath
Any suggestion besides using the .NET framework?
EDIT
By broken link I'm referring to a folder which points to a previously mounted partition, that doesn't exist anymore. The folder is still available but when attempting to navigate into it this error occurs because the destination doesn't exist anymore:
Error:
C:\folder\brokenLink refers to a location that is unavailable. It
could be on a hard drive on this computer, or on a network. Check to
make sure that the disk is properly inserted, or that you are
connected to the Internet or your network, and then try again. If it
still cannot be located, the information might have been moved to a
different location.
This will work:
$folderPath = "C:\folderContaingBrokenSymlinks\";
$items = ls $folderPath -Recurse -ea 0;
foreach($item in $items){
if($item.Attributes.ToString().contains("ReparsePoint")){
cmd /c rmdir $item.PSPath.replace("Microsoft.PowerShell.Core\FileSystem::","");
}
else{
rm -Force -Recurse $item;
}
}