2

I have a custom cmdlet that can be called like this:

Get-Info ".\somefile.txt"

My commandlet code looks something like this:

[Parameter(Mandatory = true, Position = 0)]
public string FilePath { get; set; }

protected override void ProcessRecord()
{
    using (var stream = File.Open(FilePath))
    {
        // Do work
    }
}

However when I run the command, I get this error:

Could not find file 'C:\Users\Philip\somefile.txt'

I'm not executing this cmdlet from C:\Users\Philip. For some reason my cmdlet doesn't detect the working directory so local files like this don't work. In C#, what is the recommended way of detecting the correct filepath when a local ".\" filepath is provided?

Phil
  • 6,561
  • 4
  • 44
  • 69
  • Have you tried: [Environment.CurrentDirectory](http://msdn.microsoft.com/en-us/library/system.environment.currentdirectory.aspx) – M.Babcock Mar 28 '12 at 19:18
  • Yes I have, the result is 'C:\Users\Philip\' – Phil Mar 28 '12 at 19:26
  • This is apparently by design: http://www.windowsitpro.com/article/windows-powershell/why-the-powershell-working-directory-and-the-powershell-location-aren-t-one-in-the-same. `Inside PowerShell, your location is C:\tmp. However, your working directory is still going to be C:\Users\JaneUser` – mellamokb Mar 28 '12 at 19:30
  • 1
    possible duplicate of [How do I deal with Paths when writing a PowerShell Cmdlet?](http://stackoverflow.com/questions/8505294/how-do-i-deal-with-paths-when-writing-a-powershell-cmdlet) – Phil Mar 28 '12 at 19:34
  • Do not use [environment]::CurrentDirectory. It doesn't track your current dir in PowerShell. – Keith Hill Mar 29 '12 at 07:28

6 Answers6

1

Look at the Path property of the SessionState property. It has some utility functions commonly used to resolve a relative path. The choices vary depending on whether you want to support wildcards. This forum post might be useful.

Keith Hill
  • 194,368
  • 42
  • 353
  • 369
1

For now I am using GetUnresolvedProviderPathFromPsPath. However I could design my cmdlet a little more according to Microsoft guidelines with the help of this stackoverflow question, which is exactly what I am looking for. The answer there is extremely comprehensive. I don't want to delete this quesion, but I have voted to close it as this question is an exact duplicate and the answer there is better.

Community
  • 1
  • 1
Phil
  • 6,561
  • 4
  • 44
  • 69
0
    /// <summary>
    /// The member variable m_fname is populated by input parameter
    /// and accepts either absolute or relative path.
    /// This method will determine if the supplied parameter was fully qualified, 
    /// and if not then qualify it.
    /// </summary>
    protected override void InternalProcessRecord()
    {
        base.InternalProcessRecord();

        string fname = null;
        if (Path.IsPathRooted(m_fname))
            fname = m_fname;
        else
            fname = Path.Combine(this.SessionState.Path.CurrentLocation.ToString(), m_fname);

        // If the file doesn't exist
        if (!File.Exists(fname))
            throw new FileNotFoundException("File does not exist.", fname);
    }
0

This is how I approached resolving a relative path and I think it is platform independent.

using System.Management.Automation;

namespace ProofOfConcept {

    [Cmdlet(VerbsDiagnostic.Test, "PathNormalization")]
    [OutputType(typeof(string))]
    public class TestPathNormalization : PSCmdlet {

        private string pathParameter = String.Empty;

        [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true)]
        public String Path {
            get { return this.pathParameter; }
            set { this.pathParameter = value; }
        }

        protected override void ProcessRecord() {
            base.ProcessRecord();

            WriteDebug(this.pathParameter);

            string normalizedPath = this.SessionState.Path.NormalizeRelativePath(this.pathParameter, String.Empty);

            WriteDebug(normalizedPath);

            WriteObject(normalizedPath);
        }
    }
}
0

Have you tried:

File.Open(Path.GetFullPath(FilePath))
Ta01
  • 31,040
  • 13
  • 70
  • 99
0

You should be able to use something like:

var currentDirectory = ((PathInfo)GetVariableValue("pwd")).Path;

If you inherit from PSCmdlet instead of Cmdlet. Source

Alternatively, something like:

this.SessionState.Path

might work.

M.Babcock
  • 18,753
  • 6
  • 54
  • 84