Richard Dingwall
Richard Dingwall

Reputation: 2742

Setting the start dir when calling Powershell from .NET?

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();
}

Upvotes: 19

Views: 11496

Answers (5)

Luc VdV
Luc VdV

Reputation: 1198

Instead of letting the application handle it, you can include this at the start of your script,

Set-Location $PSScriptRoot

It would execute the rest of the script in its installation directory.

But beware, the PowerShell 'current location' is NOT the same as the working directory of your application, they're just initialized the same when you launch powershell.

Set-Location may play tricks on you if you launch executables that depend on the current directory, or if your script contains framework API calls like this example:

PS C:\Users\luc> Set-Location C:\
PS C:\> [System.IO.Directory]::GetCurrentDirectory()
C:\Users\luc

That being said, I would often prefer Mike Bailey's answer. I just wanted to give a solution that has its merits if the script isn't always installed in the same directory (different path on a development machine than in production, as is usually the case).

Upvotes: 0

Mike Bailey
Mike Bailey

Reputation: 12817

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();
}

Upvotes: 17

Jaykul
Jaykul

Reputation: 15824

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.

Upvotes: 8

Binoj Antony
Binoj Antony

Reputation: 16196

You can set the working directory in powershell with the following command

set-location c:\mydirectory

You can also try your PowerShell startup script ($profile). C:....\MyDocs\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 But only if this directory is fixed and does not change

Upvotes: 1

x0n
x0n

Reputation: 52430

Anything wrong with doing:

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

?

-Oisin

Upvotes: 4

Related Questions