简体   繁体   中英

How to use powershell variable in PowerShell.AddParameter method in C#?

See my code below. The script creates the variable $backupFile. How can I use that variable in the next statement as value for the path parameter of the New-Item commend?

        using (var ps = PowerShell.Create())
        {
            ps.RunspacePool = _runspacePool;
            ps.AddScript("$backupFile = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(),'{0}.bak')".FormatInvariant(databaseName));
            ps.AddStatement();
            ps.AddCommand("New-Item")
                .AddParameter("Force")
                .AddParameter("ItemType", "File")
                .AddParameter("Path", /* How to use $backupFile?? */));
            ps.Invoke();
        }

The variable won't be available until you invoke the first script. Try this:

ps.AddScript("$backupFile = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(),'{0}.bak')".FormatInvariant(databaseName));
ps.Invoke();
ps.Commands.Clear();
var backupFile = ps.Runspace.SessionStateProxy.PSVariable.Get("backupFile");
ps.AddCommand("New-Item")
  .AddParameter("Force")
  .AddParameter("ItemType", "File")
  .AddParameter("Path", backupFile ));
ps.Invoke();

If you go this route though, I don't think you can use the RunspacePool because you're likely to get different runspaces between each Invoke() . In that case, the variable won't be available to the other runspace. Do you really need to use the RunspacePool in this scenario? If you do then why not just do the first bit in C#:

var backupFile = Path.Combine(Path.GetTempPath(), databaseName +'.bak');

I would try using a different Invoke. If you use PowerShell.Invoke Method (PSDataCollection, PSDataCollection, PSInvocationSettings) then you can drop the required information out of the end of the Pipeline and use the values from the PSDataCollection<T> Output in the rest of the script.

Although the answers of Keith and Eris were helpful, I thought it would be more helpful for other people reading this, to compose my own answer with my conclusions so far.

The answer on my initial question seems to be that it is not possible (at least we did not find a way for it so far).

So it seems that the use case for AddCommand (with AddArgument, AddParameter(s)) is to compose just one pipeline with one or more command and then get the result as the output of the Invoke method. Eventually you can add additional pipelines (separated by AddStatement) as long as the don't depend on each other. You will get multiple results in the output collection of the Invoke method.

When you want to execute 2 pipelines and the second depends on the result of the first (and it is not possible to pipe the result (as in my code example), I think there are two options: 1) Call Invoke for the first pipeline and use the output when composing the second pipeline. Or 2) Compose a script (eg with StringBuilder) and execute that with one Invoke.

When you are working with a remote connection, the latter option is perhaps preferable because that is only one call to the remote server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM