PowerShell: Remove-Item fails on FAT32 drive when encountering some Unicode characters

Prerequisites

Steps to reproduce

Consider the data in RADWIMPS.zip (note: this is copyrighted material I rip-ped from a CD I legally own; please don’t redistribute).

When this is found on a FAT32 drive, you cannot delete the file tree using Remove-Item:

image

This repro’s both in 7.2.1 and 7.3.0-preview.1.

CMD.EXE has no problem with the same data:

image

Expected behavior

`Remove-Item` should remove the entire directory tree.

Actual behavior

`Remove-Item` fails with `Remove-Item: No mapping for the Unicode character exists in the target multi-byte code page.`

Error details

Exception             :
    Type            : System.ComponentModel.Win32Exception
    NativeErrorCode : 1113
    ErrorCode       : -2147467259
    TargetSite      :
        Name          : IsReparsePointLikeSymlink
        DeclaringType : Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods
        MemberType    : Method
        Module        : System.Management.Automation.dll
    Message         : No mapping for the Unicode character exists in the target multi-byte code page.
    Source          : System.Management.Automation
    HResult         : -2147467259
    StackTrace      :
   at
Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(FileSystemInfo
fileInfo)
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveDirectoryInfoItem(DirectoryInfo directory,
Boolean recurse, Boolean force, Boolean rootOfRemoval)
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveDirectoryInfoItem(DirectoryInfo directory,
Boolean recurse, Boolean force, Boolean rootOfRemoval)
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveItem(String path, Boolean recurse)
   at System.Management.Automation.SessionStateInternal.RemoveItem(CmdletProvider providerInstance, String
path, Boolean recurse, CmdletProviderContext context)
CategoryInfo          : NotSpecified: (:) [Remove-Item], Win32Exception
FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.RemoveItemCommand
InvocationInfo        :
    MyCommand        : Remove-Item
    ScriptLineNumber : 1
    OffsetInLine     : 1
    HistoryId        : 78
    Line             : Remove-Item -Recurse -Force -LiteralPath J:\RADWIMPS -Verbose
    PositionMessage  : At line:1 char:1
                       + Remove-Item -Recurse -Force -LiteralPath J:\RADWIMPS -Verbose
                       + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    InvocationName   : Remove-Item
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1

Environment data

Name                           Value
----                           -----
PSVersion                      7.3.0-preview.1
PSEdition                      Core
GitCommitId                    7.3.0-preview.1
OS                             Microsoft Windows 10.0.19044
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 21 (8 by maintainers)

Most upvoted comments

What about this?

#requires -RunAsAdministrator

$testdrive = 'c:\tmp'

# create a virtual FAT32 drive and mount it
$vhdx = Join-Path -Path $TestDrive -ChildPath 'PS16804.vhdx'

if (Test-Path -Path $vhdx) {
    Remove-item -Path $vhdx -Force -Verbose
}

Dismount-DiskImage -ImagePath $vhdx -ErrorAction SilentlyContinue

$create_vhdx = Join-Path -Path $TestDrive -ChildPath 'create_vhdx.txt'

Set-Content -Path $create_vhdx -Force -Value @"
    create vdisk file="$vhdx" maximum=100 type=fixed
    select vdisk file="$vhdx"
    attach vdisk
    convert mbr
    create partition primary
    format fs=fat32
    assign letter="T"
    detach vdisk
"@

diskpart.exe /s $create_vhdx
Mount-DiskImage -ImagePath $vhdx > $null

$driveroot = 't:\'

if (Test-Path -LiteralPath $driveroot)
{

# repro the issue
$parentfoldername = 'PS16804'
$foldername = '天気の子'
$filename = '01 - 「天気の子」のテーマ.mp3'

$parentfolder_abspath = Join-Path -Path $driveroot -ChildPath $parentfoldername
$folder_abspath = Join-Path -Path $driveroot -ChildPath ("{0}\{1}" -f $parentfoldername, $foldername)

# start from a clean slate
if (Test-Path -LiteralPath $parentfolder_abspath)
{
    # use CMD since Remove-Item will not work
    cmd /c "rd /s /q $parentfolder_abspath"
}

if (Test-Path -LiteralPath $parentfolder_abspath)
{
    Write-Host -ForegroundColor Red ("Failed to remove '{0}'" -f $parentfolder_abspath)
    Exit(1)
}

New-Item -Path $folder_abspath -ItemType Directory -Force | Out-Null
if (!(Test-Path -LiteralPath $folder_abspath))
{
    Write-Host -ForegroundColor Red ("Failed to create '{0}'" -f $folder_abspath)
    Exit(1)
}

$filepath_abs = Join-Path -Path $folder_abspath -ChildPath $filename
"" | Out-File -LiteralPath $filepath_abs

Write-Host -ForegroundColor Yellow ("Attempting to remove '{0}' using Remove-Item -Recurse -Force" -f $parentfolder_abspath)
Remove-Item -Force -Recurse -Verbose -LiteralPath $parentfolder_abspath
if (Test-Path -LiteralPath $parentfolder_abspath)
{
    Write-Host -ForegroundColor Red ("Failed to remove '{0}'" -f $parentfolder_abspath)
}
else {
    Write-Host -ForegroundColor Green ("Removal of '{0}' succeeded" -f $parentfolder_abspath)
}

Write-Host -ForegroundColor Yellow ("Attempting to remove '{0}' using CMD /C RD /S /Q" -f $parentfolder_abspath)
cmd /c "rd /s /q $parentfolder_abspath"
if (Test-Path -LiteralPath $parentfolder_abspath)
{
    Write-Host -ForegroundColor Red ("Failed to remove '{0}'" -f $parentfolder_abspath)
}
else {
    Write-Host -ForegroundColor Green ("Removal of '{0}' succeeded" -f $parentfolder_abspath)
}
}
Dismount-DiskImage -ImagePath $vhdx > $null
Remove-item -Path $vhdx -Force
Remove-item -Path $create_vhdx -Force


PS16804.zip

Output:

image