Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the start dir when calling Powershell from .NET?

Tags:

c#

powershell

I'm using the System.Management.Automation API to call PowerShell scripts a C# WPF app. In the following example, how would you change the start directory ($PWD) so it executes foo.ps1 from C:\scripts\ instead of the location of the .exe it was called from?

using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
    runspace.Open();
    using (Pipeline pipeline = runspace.CreatePipeline())
    {
        pipeline.Commands.Add(@"C:\scripts\foo.ps1");
        pipeline.Invoke();
    }
    runspace.Close();
}
like image 630
Richard Dingwall Avatar asked May 22 '09 04:05

Richard Dingwall


3 Answers

You don't need to change the System.Environment.CurrentDirectory to change the working path for your PowerShell scripts. It can be quite dangerous to do this because this may have unintentional side effects if you're running other code that is sensitive to your current directory.

Since you're providing a Runspace, all you need to do is set the Path properties on the SessionStateProxy:

using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
    runspace.Open();
    runspace.SessionStateProxy.Path.SetLocation(directory);
    using (Pipeline pipeline = runspace.CreatePipeline())
    {
        pipeline.Commands.Add(@"C:\scripts\foo.ps1");
        pipeline.Invoke();
    }
    runspace.Close();
}
like image 93
Mike Bailey Avatar answered Nov 15 '22 23:11

Mike Bailey


Setting System.Environment.CurrentDirectory ahead of time will do what you want.

Rather than adding Set-Location to your scrip, you should set System.Environment.CurrentDirectory any time before opening the Runspace. It will inherit whatever the CurrentDirectory is when it's opened:

using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
    System.Environment.CurrentDirectory = "C:\\scripts";
    runspace.Open();
    using (Pipeline pipeline = runspace.CreatePipeline())
    {
        pipeline.Commands.Add(@".\foo.ps1");
        pipeline.Invoke();
    }
    runspace.Close();
}

And remember, Set-Location doesn't set the .net framework's CurrentDirectory so if you're calling .Net methods which work on the "current" location, you need to set it yourself.

like image 25
Jaykul Avatar answered Nov 16 '22 00:11

Jaykul


Anything wrong with doing:

pipeline.Commands.AddScript(@"set-location c:\scripts;.\foo.ps1")

?

-Oisin

like image 34
x0n Avatar answered Nov 16 '22 01:11

x0n