4

I am working on a C# project that that is supposed to grab a string variable (file path) and pass it to PowerShell script to have further commands done with it. I have been looking around online and through Stack and have not been able to find something that works for me...

Here is my C# code as it stands right now:

string script = System.IO.File.ReadAllText(@"C:\my\script\path\script.ps1");

using (Runspace runspace = RunspaceFactory.CreateRunspace())
{

    runspace.Open();
    PowerShell ps = PowerShell.Create();
    ps.Runspace = runspace;
    ps.AddScript(script);
    ps.Invoke();
    ps.AddCommand("LocalCopy");

    foreach (PSObject result in ps.Invoke())
    {
        Console.WriteLine(result);
    }
}                   

Here is my PowerShell script:

Function LocalCopy
{
    Get-ChildItem -path "C:\Users\file1\file2\file3\" -Filter *.tib -Recurse | 
    Copy-Item -Destination "C:\Users\file1\file2\local\"
}

What I want to do is have the first part of the the script: "C:\Users\file1\file2\file3\" replaced with (what i am assuming would be) a variable that I could pass from the C# code to the PowerShell script. I am very new to working with PowerShell and am not quite sure how I would go about doing something like this.

---EDIT---

I am still having issues with my code, but i am not getting any errors. I believe that it is because the variable is still not being passed through...

C# code:

string script = System.IO.File.ReadAllText(@"C:\my\script\path\script.ps1");

using (Runspace runspace = RunspaceFactory.CreateRunspace())
{

    runspace.Open();
    PowerShell ps = PowerShell.Create();
    ps.Runspace = runspace;
    ps.AddScript(script);
    ps.Invoke();
    ps.AddArgument(FilePathVariable);
    ps.AddCommand("LocalCopy");

    foreach (PSObject result in ps.Invoke())
    {
        Console.WriteLine(result);
    }
}

PowerShell code:

Function LocalCopy
{
    $path = $args[0]
    Get-ChildItem -path $path -Filter *.tib -Recurse | 
    Copy-Item -Destination "C:\Users\file1\file2\local\"
}

Any help would be much appreciated. Thanks!

2

2 Answers 2

6

I would go the route Anand has shown to pass a path into your script. But to answer the question posed by your title, here's how you pass variable from C#. Well this is really how you set the variable in the PowerShell engine.

ps.Runspace.SessionStateProxy.SetVariable("Path", @"C:\Users\file1\file2\file3\");

Note: in C# for file paths you really want to use verbatim @ strings.

Update: based on your comments, try this:

runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddScript(script, false); // Use false to tell PowerShell to run script in current 
                             // scope otherwise LocalCopy function won't be available
                             // later when we try to invoke it.
ps.Invoke();
ps.Commands.Clear();
ps.AddCommand("LocalCopy").AddArgument(FilePathVariable);
ps.Invoke();
Sign up to request clarification or add additional context in comments.

7 Comments

if i needed to pass the file path through as a variable would i just do it like so ps.Runspace.SessionStateProxy.SetVariable("Path", variablepath);?
If you needed to set a PowerShell variable called $Path that would then get used by your script, then yes. This is how you would do it. However, in your case, you could just pass the the path via a C# variable to your function invocation as @Anand has shown except that you can do this ps.AddArgument(someCSharpVariable). You will need to modify your function to use either a param($path) block or use $path = $args[0]. Then use that variable with the command: gci $path *.tib -r.
I have just updated my code to what i currently am working with. I do not really understand what is going on with the $path = $args[0], but i still feel that my error is coming through either the c# or powershell code where i have updated it. Do you have any ideas/explanations as to what i am doing?
You need to add the argument to the function invocation e.g. ps.AddCommand("LocalCopy").AddArgument(FilePathVariable). See the update to my answer as there is more to this to get it to work.
I actually just figured that out in between posts, but i just moved the powershell portion outside of the function instead of doing what you suggested. I might try what you did instead since it seems to look a little cleaner.
|
5
ps.AddArgument("C:\Users\file1\file2\file3\");

you can use args to fetch the argument in powershell.

$path = $args[0]

MSDN

2 Comments

So I am assuming that if I wanted to keep it as a variable on the C# side i could just do: ps.AddArgument(pathvaribale);?
The OP problem's was a little more fundamental than just adding an argument for the function. When ps.AddScript(script) executes, it executes the script in a new scope so that the defined function is not available after it is invoked. You have to pass false to get the script to run in the current scope so the function remains after the script is invoked e.g. ps.AddScript(script, false);

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.