0

I have a powershell script to install a very large application (15gb source media) from a location its been delivered to on the C drive.

At the end of the script, to ensure that the software is installed I perform a test-path of the HKLM Microsoft Windows CurrentVersion Uninstall path for the GUID, and if successful, clear the source media from the C drive.

If (Test-Path("HKLM:pathname")) { Remove-Item $path -force -recurse }

The problem I have is that the above command works via Powershell ISE when run individually. It knows the key exists so should perform Remove-Item. When run as a script, or via a deployment mechanism, it will not remove the folder.

I have even gone further and used:

GCI $Path -Recurse | Remove-Item -force -recurse

... to no avail.

Prior to introducing the Test-Path, I only had the Remove-Item $Path -force -recurse and this worked!!

So despite Test-Path correctly judging, it appears to prevent Remove-Item from doing anything. (I wrote to a log file to check the If routing)

Any thoughts? Sorry for any typos, I did not copy / paste any part of the script.

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • 1
    Shouldn't it be `If (Test-Path $path) { Remove-Item $path -force -recurse }`? – Mathias R. Jessen Aug 23 '21 at 15:28
  • As an aside: The PowerShell ISE is [no longer actively developed](https://docs.microsoft.com/en-us/powershell/scripting/components/ise/introducing-the-windows-powershell-ise#support) and [there are reasons not to use it](https://stackoverflow.com/a/57134096/45375) (bottom section), notably not being able to run PowerShell (Core) 6+. The actively developed, cross-platform editor that offers the best PowerShell development experience is [Visual Studio Code](https://code.visualstudio.com/) with its [PowerShell extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell). – mklement0 Aug 23 '21 at 15:36
  • If something works in the ISE, it is sometimes an unwitting side effect of all code running in the same scope, so that during repeated runs earlier runs can have side effects on later runs. One obvious question is: is `$Path` guaranteed to have a value? – mklement0 Aug 23 '21 at 15:37
  • Also, @Mathias's comment implicitly shows that the proper syntax for every PowerShell command (as opposed to a .NET _method_) is to whitespace-separate arguments, and to not use `(...)` around the list of argument - with a single, positional argument your pseudo method syntax (`Test-Path('...')`) _happens_ to work, but it falls apart with multiple arguments and is best avoided altogether. – mklement0 Aug 23 '21 at 15:41
  • Sidenote1: you're missing `SOFTWARE` after ``HKLM:\``. Then _"When run as a script, or via a deployment mechanism, it will not remove the folder."_ Is the user running the script permitted to delete subkeys from the HKEY_LOCAL_MACHINE path? Sidenote2: a registry **Key** is not a **Folder** – Theo Aug 23 '21 at 15:54

1 Answers1

0

If you can't delete the key immediately after, that probably means it has a write lock that's been applied by the Test-Path cmdlet.

Try finding out if a lock exist using Sysinternals Handle command and then release it using the handle.exe -c argument, referencing the hexadecimal number.
Make sure the format used in $path matches the format used by handle.exe

$lock = & handle.exe -nobanner -a -p ($PID) ($path)
if (-not ($lock -like '*No matching handles found*')){
    & handle.exe -nobanner -p ($PID) -c ($lock[0].split(':')[0].Trim(' ')) -y
}

This will only work if you have the permission to close handles.

Dennis
  • 871
  • 9
  • 29