-
Notifications
You must be signed in to change notification settings - Fork 29
/
Remove-LockyFile.ps1
63 lines (58 loc) · 1.91 KB
/
Remove-LockyFile.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<#
.SYNOPSIS
Removes a file that may be prone to locking.
.INPUTS
System.String containing the path of a file to delete (or rename if deleting fails).
.FUNCTIONALITY
Files
.EXAMPLE
Remove-LockyFile.ps1 InUse.dll
(Tries to remove file, renames it if unable to, tries deleting at reboot as a last resort.)
#>
#Requires -Version 3
[CmdletBinding()][OutputType([void])] Param(
<#
Specifies a path to the items being removed. Wildcards are permitted.
The parameter name ("-Path") is optional.
#>
[Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ValueFromRemainingArguments=$true)]
[string]$Path
)
Begin
{
try{[void][RebootFileAction]}catch{Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
public class RebootFileAction
{
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
private static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
const int MOVEFILE_DELAY_UNTIL_REBOOT = 0x4;
static public void Delete(string filename)
{
if(!MoveFileEx(filename,"",MOVEFILE_DELAY_UNTIL_REBOOT))
{ throw new InvalidOperationException(String.Format("Unable to mark {0} for deletion at reboot.",filename)); }
}
}
'@}
}
Process
{
try { Remove-Item $Path -Force -ErrorAction Stop }
catch
{
$NewPath = "$Path~$([guid]::NewGuid().Guid)"
try
{
Move-Item $Path $NewPath -Force -ErrorAction Stop
$Path = Resolve-Path $NewPath
try { Remove-Item $Path -Force -ErrorAction Stop }
catch { Write-Warning "Renamed file, but unable to remove $Path"; throw }
}
catch
{
[RebootFileAction]::Delete((Resolve-Path $Path))
Write-Warning "File $Path has been marked for deletion at reboot."
}
}
}