Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Add-Type -TypeDefinition @'
- using Microsoft.Win32.SafeHandles;
- using System;
- using System.IO;
- using System.Runtime.ConstrainedExecution;
- using System.Runtime.InteropServices;
- namespace FileIO
- {
- public class NativeHelpers
- {
- public enum GET_FILEEX_INFO_LEVELS
- {
- GetFileExInfoStandard,
- GetFileExMaxInfoLevel
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct FILETIME
- {
- internal UInt32 dwLowDateTime;
- internal UInt32 dwHighDateTime;
- public static implicit operator Int64(FILETIME v) { return ((Int64)v.dwHighDateTime << 32) + v.dwLowDateTime; }
- public static explicit operator DateTimeOffset(FILETIME v) { return DateTimeOffset.FromFileTime(v); }
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct WIN32_FILE_ATTRIBUTE_DATA
- {
- public FileAttributes dwFileAttributes;
- public FILETIME ftCreationTime;
- public FILETIME ftLastAccessTime;
- public FILETIME ftLastWriteTime;
- public UInt32 nFileSizeHigh;
- public UInt32 nFileSizeLow;
- }
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct WIN32_FIND_DATA
- {
- public FileAttributes dwFileAttributes;
- public FILETIME ftCreationTime;
- public FILETIME ftLastAccessTime;
- public FILETIME ftLastWriteTime;
- public UInt32 nFileSizeHigh;
- public UInt32 nFileSizeLow;
- public UInt32 dwReserved0;
- public UInt32 dwReserved1;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string cFileName;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public string cAlternateFileName;
- }
- }
- public class NativeMethods
- {
- [DllImport("Kernel32.dll", SetLastError = true)]
- public static extern bool DeleteFileW(
- [MarshalAs(UnmanagedType.LPWStr)] string lpFileName);
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool GetFileAttributesExW(
- [MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
- NativeHelpers.GET_FILEEX_INFO_LEVELS fInfoLevelId,
- out NativeHelpers.WIN32_FILE_ATTRIBUTE_DATA lpFileInformation);
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool FindClose(
- IntPtr hFindFile);
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern SafeFindHandle FindFirstFileW(
- [MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
- out NativeHelpers.WIN32_FIND_DATA lpFindFileData);
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool FindNextFileW(
- SafeFindHandle hFindFile,
- out NativeHelpers.WIN32_FIND_DATA lpFindFileData);
- [DllImport("Kernel32.dll", SetLastError = true)]
- public static extern bool RemoveDirectoryW(
- [MarshalAs(UnmanagedType.LPWStr)] string lpPathName);
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool SetFileAttributesW(
- [MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
- FileAttributes dwFileAttributes);
- }
- public class SafeFindHandle : SafeHandleMinusOneIsInvalid
- {
- public SafeFindHandle() : base(true) { }
- public SafeFindHandle(IntPtr handle) : base(true) { this.handle = handle; }
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
- protected override bool ReleaseHandle()
- {
- return NativeMethods.FindClose(handle);
- }
- }
- }
- '@
- Function Get-Win32ErrorMessage {
- Param (
- [Parameter(Mandatory=$true)]
- [Int32]
- $ErrorCode
- )
- $exp = New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $ErrorCode
- return ("{0} (Win32 Error Code {1} - 0x{1:X8})" -f $exp.Message, $ErrorCode)
- }
- Function Get-FileAttributes {
- Param (
- [Parameter(Mandatory=$true)]
- [String]
- $Path
- )
- $data = New-Object -TypeName FileIO.NativeHelpers+WIN32_FILE_ATTRIBUTE_DATA
- $res = [FileIO.NativeMethods]::GetFileAttributesExW(
- $Path,
- [FileIO.NativeHelpers+GET_FILEEX_INFO_LEVELS]::GetFileExInfoStandard,
- [Ref]$data
- )
- $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- if (-not $res) {
- if ($err -eq 32) { # ERROR_SHARING_VIOLATION
- # Special system files like pagefile.sys return this error. Use FindFirstFileW instead.
- $data = New-Object -TypeName FileIO.NativeHelpers+WIN32_FIND_DATA
- $find_handle = [FileIO.NativeMethods]::FindFirstFileW($Path, [Ref]$data)
- $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- if ($find_handle.IsInvalid) {
- throw "Failed to get file attributes for '$Path': $(Get-Win32ErrorMessage -ErrorCode $err)"
- }
- try {
- $attrs = $data.dwFileAttributes
- } finally {
- $find_handle.Dispose()
- }
- } else {
- throw "Failed to get file attributes for '$Path': $(Get-Win32ErrorMessage -ErrorCode $err)"
- }
- } else {
- $attrs = $data.dwFileAttributes
- }
- return $attrs
- }
- Function Remove-ReadOnlyAndHiddenAttribute {
- Param (
- [Parameter(Mandatory=$true)]
- [String]
- $Path
- )
- $attrs = Get-FileAttributes -Path $Path
- $changed = $false
- 'ReadOnly', 'Hidden' | ForEach-Object -Process {
- if ($attrs.HasFlag([System.IO.FileAttributes]$_)) {
- $attrs = $attrs -bxor [System.IO.FileAttributes]$_
- $changed = $true
- }
- }
- if ($changed) {
- $res = [FileIO.NativeMethods]::SetFileAttributesW($Path, $attrs)
- $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- if (-not $res) {
- throw "Failed to remove the ReadOnly or Hidden attribute for deletion on '$Path': $(Get-Win32ErrorMessage -ErrorCode $err)"
- }
- }
- }
- Function Remove-File {
- Param (
- [Parameter(Mandatory=$true)]
- [String]
- $Path
- )
- Remove-ReadOnlyAndHiddenAttribute -Path $Path
- $res = [FileIO.NativeMEthods]::DeleteFileW($Path)
- $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- if (-not $res) {
- throw "Failed to delete file '$Path': $(Get-Win32ErrorMessage -ErrorCode $err)"
- }
- }
- Function Remove-Directory {
- Param (
- [Parameter(Mandatory=$true)]
- [String]
- $Path,
- [Switch]
- $Recurse
- )
- if ($Recurse) {
- $find_path = [System.IO.Path]::Combine($Path, "*")
- $find_data = New-Object -TypeName FileIO.NativeHelpers+WIN32_FIND_DATA
- $find_handle = [FileIO.NativeMethods]::FindFirstFileW(
- $find_path, [ref]$find_data
- )
- $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- if ($find_handle.IsInvalid) {
- throw "Failed to enumerate directory with search pattern '$find_path': $(Get-Win32ErrorMessage -ErrorCode $err)"
- }
- try {
- do {
- if ($find_data.cFileName -in @('.', '..')) {
- continue
- }
- $file_path = [System.IO.Path]::Combine($Path, $find_data.cFileName)
- if ($find_data.dwFileAttributes.HasFlag([System.IO.FileAttributes]::Directory)) {
- $is_link = $find_data.dwFileAttributes.HasFlag([System.IO.FileAttributes]::ReparsePoint)
- Remove-Directory -Path $file_path -Recurse:(-not $is_link)
- } else {
- Remove-File -Path $file_path
- }
- } while ([FileIO.NativeMethods]::FindNextFileW($find_handle, [ref]$find_data))
- } finally {
- $find_handle.Dispose()
- }
- }
- Remove-ReadOnlyAndHiddenAttribute -Path $Path
- $res = [FileIO.NativeMethods]::RemoveDirectoryW($Path)
- $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- if (-not $res) {
- throw "Failed to delete directory '$Path': $(Get-Win32ErrorMessage -ErrorCode $err)"
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement