diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 9499bf9528..be53fc75d6 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -51,15 +51,6 @@ namespace Microsoft.PowerShell.Commands ISecurityDescriptorCmdletProvider, ICmdletProviderSupportsHelp { -#if UNIX - // This is the errno returned by the rename() syscall - // when an item is attempted to be renamed across filesystem mount boundaries. - private const int MOVE_FAILED_ERROR = 18; -#else - // 0x80070005 ACCESS_DENIED is returned when trying to move files across volumes like DFS - private const int MOVE_FAILED_ERROR = -2147024891; -#endif - // 4MB gives the best results without spiking the resources on the remote connection for file transfers between pssessions. // NOTE: The script used to copy file data from session (PSCopyFromSessionHelper) has a // maximum fragment size value for security. If FILETRANSFERSIZE changes make sure the @@ -6078,12 +6069,12 @@ namespace Microsoft.PowerShell.Commands { if (InternalTestHooks.ThrowExdevErrorOnMoveDirectory) { - throw new IOException("Invalid cross-device link", hresult: MOVE_FAILED_ERROR); + throw new IOException("Invalid cross-device link"); } directory.MoveTo(destinationPath); } - catch (IOException e) when (e.HResult == MOVE_FAILED_ERROR) + catch (IOException) { // Rather than try to ascertain whether we can rename a directory ahead of time, // it's both faster and more correct to try to rename it and fall back to copy/deleting it diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 index a9d35d7f78..f1b352a16b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 @@ -154,7 +154,7 @@ Describe "Basic FileSystem Provider Tests" -Tags "CI" { } It "Verify Move-Item will not move to an existing file" { - { Move-Item -Path $testDir -Destination $testFile -ErrorAction Stop } | Should -Throw -ErrorId "MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand" + { Move-Item -Path $testDir -Destination $testFile -ErrorAction Stop } | Should -Throw -ErrorId 'DirectoryExist,Microsoft.PowerShell.Commands.MoveItemCommand' $error[0].Exception | Should -BeOfType System.IO.IOException $testDir | Should -Exist } @@ -1500,3 +1500,32 @@ Describe "Verify sub-directory creation under root" -Tag 'CI','RequireSudoOnUnix $dirPath | Should -Exist } } + +Describe "Windows admin tests" -Tag 'RequireAdminOnWindows' { + It "Verify Move-Item for directory across drives on Windows" -Skip:(!$IsWindows) { + try { + # find first available drive letter, unfortunately need to use both function: and Win32_LogicalDisk to cover + # both subst drives and bitlocker drives + $drive = Get-ChildItem function:[h-z]: -Name | Where-Object { !(Test-Path -Path $_) -and !(Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='$_'") } | Select-Object -First 1 + if ($null -eq $drive) { + throw "Test cannot continue as no drive letter available" + } + + $dest = (Resolve-Path -Path $TestDrive).ProviderPath + $null = New-Item -ItemType Directory -Path $dest -Name test + $out = subst $drive $dest 2>&1 + if ($LASTEXITCODE -ne 0) { + throw "subst failed with exit code ${LASTEXITCODE} for drive '$drive': $out" + } + + $testdir = New-Item -ItemType Directory -Path $drive -Name testmovedir -Force + 1 > $testdir\test.txt + Move-Item $drive\testmovedir $dest\test + "$drive\testmovedir" | Should -Not -Exist + "$dest\test\testmovedir\test.txt" | Should -FileContentMatchExactly 1 + } + finally { + subst $drive /d + } + } +}