Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New-Item ignore's Path param if Name param is specified #5228

Closed
affieuk opened this issue Oct 25, 2017 · 12 comments · Fixed by #6600 or #6774

Comments

@affieuk
Copy link

@affieuk affieuk commented Oct 25, 2017

Steps to reproduce

Set-Location ~
New-Item -Path C:\ -Name Test -ItemType Directory -Verbose

Expected behavior

Test folder created in Root C:\

Actual behavior

Folder created in current path
PS C:\Users\Aftab> New-Item -Path C:\ -Name Test -ItemType Directory -Verbose
VERBOSE: Performing the operation "Create Directory" on target "Destination: C:\Users\Aftab\Test".


    Directory: C:\Users\Aftab


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       25/10/2017     13:51                Test


PS C:\Users\Aftab> Get-Item C:\Test
Get-Item : Cannot find path 'C:\Test' because it does not exist.
At line:1 char:1
+ Get-Item C:\Test
+ ~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Test:String) [Get-Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand

PS C:\Users\Aftab> Get-Item ~\Test


    Directory: C:\Users\Aftab


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       25/10/2017     13:51                Test

Environment data

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      6.0.0-beta.8
PSEdition                      Core
GitCommitId                    v6.0.0-beta.8
OS                             Microsoft Windows 10.0.15063
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
@affieuk

This comment has been minimized.

Copy link
Author

@affieuk affieuk commented Oct 25, 2017

This also occurs in a mounted a vhdx.

PS E:\Users> New-Item -Path E:\ -Name Test -ItemType Directory -Verbose
VERBOSE: Performing the operation "Create Directory" on target "Destination: E:\Users\Test".


    Directory: E:\Users


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       25/10/2017     14:09                Test


PS E:\Users> Get-Item E:\Test
Get-Item : Cannot find path 'E:\Test' because it does not exist.
At line:1 char:1
+ Get-Item E:\Test
+ ~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (E:\Test:String) [Get-Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand

PS E:\Users> Get-Item Test


    Directory: E:\Users


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       25/10/2017     14:09                Test
@iSazonov

This comment has been minimized.

Copy link
Collaborator

@iSazonov iSazonov commented Oct 25, 2017

@affieuk Thanks for your report!

I can confirm that new directory is created in current folder not in Path.

@mcbobke

This comment has been minimized.

Copy link
Contributor

@mcbobke mcbobke commented Apr 4, 2018

I ran into this issue last night while testing some scripts on PSCore and I've been trying to dig through the code here: https://github.com/PowerShell/PowerShell/blob/master/src/System.Management.Automation/namespaces/FileSystemProvider.cs

This is my first time working through a project as big as Powershell and maybe someone has some direction that I could follow. New-Item with the Name parameter specified works if a UNC path is passed to the Path parameter:

PS C:\Users\mbobke> New-Item -Path "\\$env:COMPUTERNAME\c$" -Name "psenv" -ItemType "Directory"


    Directory: \\MBOBKE-INT\c$


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         4/3/2018   5:27 PM                psenv

New-Item also works with the Name parameter specified if the root of a drive is not specified as the Path, and the Path is not a UNC path:

PS C:\Users\mbobke> New-Item -Path "C:\temp" -Name "psenv" -ItemType "Directory"


    Directory: C:\temp


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         4/3/2018   5:32 PM                psenv

I can't seem to track down where the Path parameter is being ignored or otherwise replaced with $pwd. I'll keep digging.

@iSazonov

This comment has been minimized.

Copy link
Collaborator

@iSazonov iSazonov commented Apr 4, 2018

@mcbobke Thanks for your investigation!
It can be tricky - there is some code levels - cmdlet, globbing, provider and some abstractions layers. I suggest you to debug starting with New-Item cmdlet code and compare code paths in your samples.

@mcbobke

This comment has been minimized.

Copy link
Contributor

@mcbobke mcbobke commented Apr 4, 2018

I spent some time tonight "debugging" really just trying to figure out how to use the built-in debugger in VSCode for the first time. Running the ".NET Core Launch" task in the debugger window seems like it's supposed to build Powershell and run it in a debugging context, but it just sits....and sits....and sits on the build. I ended up using the ".NET Core Attach" task to attach the debugger to the pwsh process, and I could step through the code.

@iSazonov

This comment has been minimized.

Copy link
Collaborator

@iSazonov iSazonov commented Apr 4, 2018

@mcbobke Do you use latest VS Code version?

@mcbobke

This comment has been minimized.

Copy link
Contributor

@mcbobke mcbobke commented Apr 4, 2018

I thought that I had updated Code on my home machine, but the ".Net Core Launch" task functions on my work machine so that might be the issue. Thanks!

Upon further investigation, the item being created is always created at the last-known current working directory of the drive specified in the path, even if you have changed to a different PSDrive with Set-Location.

Example:

PS C:\Users\mbobke\Documents> New-Item -Path "C:\" -Name "psenv" -ItemType "Directory" -Whatif
What if: Performing the operation "Create Directory" on target "Destination: C:\Users\mbobke\Documents\psenv".
PS C:\Users\mbobke\Documents> Set-Location -Path "HKLM:"
PS HKLM:\> New-Item -Path "C:\" -Name "psenv" -ItemType "Directory" -Whatif
What if: Performing the operation "Create Directory" on target "Destination: C:\Users\mbobke\Documents\psenv".

This also applies to providers other than the FileSystem, such as Registry:

PS HKLM:\SOFTWARE\> New-Item -Path "HKLM:\" -Name "TEST" -WhatIf
What if: Performing the operation "New Item" on target "Item: HKEY_LOCAL_MACHINE\SOFTWARE\TEST".
PS HKLM:\SOFTWARE\> Set-Location -Path "C:\"
PS C:\> New-Item -Path "HKLM:\" -Name "TEST" -WhatIf
What if: Performing the operation "New Item" on target "Item: HKEY_LOCAL_MACHINE\SOFTWARE\TEST".

In src\System.Management.Automation\namespaces\LocationGlobber.cs line 2114 appears to be attempting to find the relative path to the location in question that the item should be created, by using the drive identified by the path. In my case, I believe this should return an empty string since the relative path to the root of the drive is empty, but it's returning the relative path to the last-known current working directory of the drive.

Digging through method GenerateRelativePath, I found this at line 2280:

    if (String.IsNullOrEmpty(path))
    {
        // Just fall-through
    }

I don't know if we should really be falling through here - an empty Path argument in this method appears to imply that nothing beyond the root of the drive was provided as the Path in New-Item. If we don't return at this point, the driveRootRelativeWorkingPath is set to the last-known current working directory of the drive.

After updating this if-statement to the following:

    if (String.IsNullOrEmpty(path))
    {
        // Just fall-through - or maybe not
        return path;
    }

New-Item seems to be working as intended when creating items at the root of a drive:

PS C:\Users\mbobke\Documents\GitKraken\PowerShell> New-Item -Path "C:\" -Name "psenv" -ItemType "Directory" -Whatif
What if: Performing the operation "Create Directory" on target "Destination: C:\psenv".
PS C:\Users\mbobke\Documents\GitKraken\PowerShell> Set-Location -Path "HKLM:"
PS HKLM:\> New-Item -Path "C:\" -Name "psenv" -ItemType "Directory" -Whatif
What if: Performing the operation "Create Directory" on target "Destination: C:\psenv".

PS HKLM:\SOFTWARE\> New-Item -Path "HKLM:\" -Name "TEST" -WhatIf
What if: Performing the operation "New Item" on target "Item: HKEY_LOCAL_MACHINE\TEST".
PS HKLM:\SOFTWARE\> Set-Location -Path "C:\"
PS C:\> New-Item -Path "HKLM:\" -Name "TEST" -WhatIf
What if: Performing the operation "New Item" on target "Item: HKEY_LOCAL_MACHINE\TEST".

All tests are also passing (though I haven't written any to test this scenario specifically):

PS C:\Users\mbobke\Documents\GitKraken\PowerShell> & (Get-PSOutput) -noprofile
PS C:\Users\mbobke\Documents\GitKraken\PowerShell> Import-Module .\build.psm1
PS C:\Users\mbobke\Documents\GitKraken\PowerShell> Start-PSPester -Path .\test\powershell\Modules\Microsoft.PowerShell.Management\New-Item.Tests.ps1
VERBOSE: Running pester tests at '.\test\powershell\Modules\Microsoft.PowerShell.Management\New-Item.Tests.ps1' with tag 'CI', 'Feature' and ExcludeTag 'Slow'
Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 30.98 ms for C:\Users\mbobke\Documents\GitKraken\PowerShell\test\tools\TestExe\TestExe.csproj.
  TestExe -> C:\Users\mbobke\Documents\GitKraken\PowerShell\test\tools\TestExe\bin\Debug\netcoreapp2.0\win7-x64\testexe.dll
  TestExe -> C:\Users\mbobke\Documents\GitKraken\PowerShell\test\tools\TestExe\bin\
Microsoft (R) Build Engine version 15.5.180.51428 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 106.52 ms for C:\Users\mbobke\Documents\GitKraken\PowerShell\test\tools\WebListener\WebListener.csproj.
  Restore completed in 173.73 ms for C:\Users\mbobke\Documents\GitKraken\PowerShell\test\tools\WebListener\WebListener.csproj.
  WebListener -> C:\Users\mbobke\Documents\GitKraken\PowerShell\test\tools\WebListener\bin\Debug\netcoreapp2.0\win7-x64\WebListener.dll
  WebListener -> C:\Users\mbobke\Documents\GitKraken\PowerShell\test\tools\WebListener\bin\
Executing all tests in '.\test\powershell\Modules\Microsoft.PowerShell.Management\New-Item.Tests.ps1' with Tags CI', 'Feature

Executing script .\test\powershell\Modules\Microsoft.PowerShell.Management\New-Item.Tests.ps1

  Describing New-Item
    [+] should call the function without error 728ms
    [+] Should create a file without error 144ms
    [+] Should create a folder without an error 20ms
    [+] Should create a file using the ni alias 21ms
    [+] Should create a file using the Type alias instead of ItemType 22ms
    [+] Should create a file with sample text inside the file using the Value switch 85ms
    [+] Should not create a file when the Name switch is not used and only a directory specified 26ms
    [+] Should create a file when the Name switch is not used but a fully qualified path is specified 23ms
    [+] Should be able to create a multiple items in different directories 25ms
What if: Performing the operation "Create File" on target "Destination: C:\Users\mbobke\AppData\Local\Temp\0e1d9964-807b-40af-8bed-b910716ce872\testfile.txt".
    [+] Should be able to call the whatif switch without error 19ms
What if: Performing the operation "Create File" on target "Destination: C:\Users\mbobke\AppData\Local\Temp\0e1d9964-807b-40af-8bed-b910716ce872\testfile.txt".
    [+] Should not create a new file when the whatif switch is used 15ms
    [+] Should create a hard link of a file without error 57ms

  Describing New-Item with links
    [+] Should create a symbolic link of a file without error 184ms
    [+] Should create a symbolic link to a non-existing file without error 40ms
    [+] Should create a symbolic link to directory without error 57ms
    [!] Should error correctly when failing to create a symbolic link 14ms
    [+] New-Item -ItemType SymbolicLink should understand directory path ending with slash 27ms
Tests completed in 1.52s
Tests Passed: 16, Failed: 0, Skipped: 1, Pending: 0, Inconclusive: 0
@iSazonov

This comment has been minimized.

Copy link
Collaborator

@iSazonov iSazonov commented Apr 5, 2018

@mcbobke Every provider keep own current directory. In FileSystem provider case the currect directory differ from .Net current directory.

@mcbobke

This comment has been minimized.

Copy link
Contributor

@mcbobke mcbobke commented Apr 5, 2018

@iSazonov I should have clarified, I realized that once I started stepping through the code. That's normal behavior, but creating directories at the current directory instead of the given path is not. I'm going to work on some tests to see if I can ensure this resolves the issue.

@iSazonov

This comment has been minimized.

Copy link
Collaborator

@iSazonov iSazonov commented Apr 9, 2018

Should we consider other providers too?

/cc @mklement0

mcbobke added a commit to mcbobke/PowerShell that referenced this issue Apr 24, 2018
…rShell#5228)

[Feature] Checks to see if the root of a PSDrive was given as the Path argument to a parameter that supports it. If so, returns the current context's Drive's Root.
@rjmholt

This comment has been minimized.

Copy link
Member

@rjmholt rjmholt commented Apr 27, 2018

It looks like the fix for this in #6600 broke some Set-Location behaviour. Fixing this will need to account for Set-Location wanting to restore the path and New-Item wanting to use the path as given. It may be that C: should use the restored path and C:\ should not?

@rjmholt rjmholt reopened this Apr 27, 2018
@mklement0

This comment has been minimized.

Copy link
Contributor

@mklement0 mklement0 commented Apr 27, 2018

@rjmholt:

Not really having followed all of this, I'd say you're correct: c: should refer to whatever location is current in that drive, whereas c:\ should refer to the drive's root directory.

That's how it works in cmd.exe too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.