Виконайте скрипт PowerShell з C # за допомогою аргументів командного рядка


101

Мені потрібно виконати сценарій PowerShell з C #. Сценарію потрібні аргументи командного рядка.

Ось що я робив досі:

RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();

Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();

RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);

Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.Add(scriptFile);

// Execute PowerShell script
results = pipeline.Invoke();

scriptFile містить щось на кшталт "C: \ Program Files \ MyProgram \ Wever.ps1".

Сценарій використовує аргумент командного рядка, такий як "-key Value", тоді як Value може бути чимось на зразок шляху, який також може містити пробіли.

Я не отримую цього на роботі. Хтось знає, як передавати аргументи командного рядка в скрипт PowerShell зсередини C # і переконатися, що пробіли не є проблемою?


1
Тільки для того, щоб пояснити майбутнім користувачам, прийнята відповідь вирішує проблему для людей, які мають проблеми з пробілами навіть без параметрів використання. Використовуючи:, Command myCommand = new Command(scriptfile);а потім pipeline.Commands.Add(myCommand);вирішіть проблему, що витікає.
scharette

Відповіді:


111

Спробуйте створити скрипт як окрему команду:

Command myCommand = new Command(scriptfile);

тоді ви можете додати параметри за допомогою

CommandParameter testParam = new CommandParameter("key","value");
myCommand.Parameters.Add(testParam);

і, нарешті

pipeline.Commands.Add(myCommand);

Ось повний відредагований код:

RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();

Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();

RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);

Pipeline pipeline = runspace.CreatePipeline();

//Here's how you add a new script with arguments
Command myCommand = new Command(scriptfile);
CommandParameter testParam = new CommandParameter("key","value");
myCommand.Parameters.Add(testParam);

pipeline.Commands.Add(myCommand);

// Execute PowerShell script
results = pipeline.Invoke();

У мене все ще є проблема, що якщо значення є чимось на зразок c: \ program files \ myprogram, ключ встановлюється на c: \ program. :(
Мефіштое

Не звертай уваги. Іноді це допомагає, коли ви знаєте, як правильно розділити рядки. ;-) Ще раз дякую, ваше рішення допомогло мені вирішити мою проблему!
Мефіштое

@Tronex - вам слід визначити ключ як параметр для вашого сценарію. PowerShell має кілька чудових вбудованих інструментів для роботи зі шляхами. Можливо, задайте інше питання з цього приводу. @ Kosi2801 має правильну відповідь для додавання параметрів.
Стівен Муравський

Введення моєї відповіді перекриває вашу .. Я радий, що ви її вирішили!
Стівен Муравський

1
Змінна scriptInvoker не використовується.
niaher

33

У мене є інше рішення. Я просто хочу перевірити, чи вдале виконання сценарію PowerShell, тому що, можливо, хтось може змінити політику. В якості аргументу я просто вказую шлях виконання сценарію.

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = @"powershell.exe";
startInfo.Arguments = @"& 'c:\Scripts\test.ps1'";
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();

string output = process.StandardOutput.ReadToEnd();
Assert.IsTrue(output.Contains("StringToBeVerifiedInAUnitTest"));

string errors = process.StandardError.ReadToEnd();
Assert.IsTrue(string.IsNullOrEmpty(errors));

Вміст сценарію:

$someVariable = "StringToBeVerifiedInAUnitTest"
$someVariable

1
Привіт. Чи маєте ви якесь уявлення, чому запуск в повному обсязі так, як ви описали та виконання всіх команд, процес (у нашому випадку) не виходить?
Eugeniu Torica

Яку бібліотеку ви використовуєте
SoftwareSavant

11

У мене виникли проблеми з передачею параметрів методу Commands.AddScript.

C:\Foo1.PS1 Hello World Hunger
C:\Foo2.PS1 Hello World

scriptFile = "C:\Foo1.PS1"

parameters = "parm1 parm2 parm3" ... variable length of params

Я вирішив це, передавши nullяк ім'я та парам як значення в колекціюCommandParameters

Ось моя функція:

private static void RunPowershellScript(string scriptFile, string scriptParameters)
{
    RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
    Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
    runspace.Open();
    RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
    Pipeline pipeline = runspace.CreatePipeline();
    Command scriptCommand = new Command(scriptFile);
    Collection<CommandParameter> commandParameters = new Collection<CommandParameter>();
    foreach (string scriptParameter in scriptParameters.Split(' '))
    {
        CommandParameter commandParm = new CommandParameter(null, scriptParameter);
        commandParameters.Add(commandParm);
        scriptCommand.Parameters.Add(commandParm);
    }
    pipeline.Commands.Add(scriptCommand);
    Collection<PSObject> psObjects;
    psObjects = pipeline.Invoke();
}

Щойно додано:using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))...using (Pipeline pipeline = runspace.CreatePipeline())
Червоний

Коли я передаю декілька параметрів, виникає ця помилка: У системі System.Management.Automation.dll
Мухаммед Номан

5

Ви також можете просто використовувати конвеєр методом AddScript:

string cmdArg = ".\script.ps1 -foo bar"            
Collection<PSObject> psresults;
using (Pipeline pipeline = _runspace.CreatePipeline())
            {
                pipeline.Commands.AddScript(cmdArg);
                pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
                psresults = pipeline.Invoke();
            }
return psresults;

Це займе рядок і за якими б параметрами ви не передавали його.


4

Шахта трохи менша і простіша:

/// <summary>
/// Runs a PowerShell script taking it's path and parameters.
/// </summary>
/// <param name="scriptFullPath">The full file path for the .ps1 file.</param>
/// <param name="parameters">The parameters for the script, can be null.</param>
/// <returns>The output from the PowerShell execution.</returns>
public static ICollection<PSObject> RunScript(string scriptFullPath, ICollection<CommandParameter> parameters = null)
{
    var runspace = RunspaceFactory.CreateRunspace();
    runspace.Open();
    var pipeline = runspace.CreatePipeline();
    var cmd = new Command(scriptFullPath);
    if (parameters != null)
    {
        foreach (var p in parameters)
        {
            cmd.Parameters.Add(p);
        }
    }
    pipeline.Commands.Add(cmd);
    var results = pipeline.Invoke();
    pipeline.Dispose();
    runspace.Dispose();
    return results;
}

3

Ось спосіб додати Параметри до сценарію, якщо ви використовували

pipeline.Commands.AddScript(Script);

Це з використанням параметра HashMap в якості параметра, ключовим словом є ім'я змінної в сценарії, а значення - значення змінної.

pipeline.Commands.AddScript(script));
FillVariables(pipeline, scriptParameter);
Collection<PSObject> results = pipeline.Invoke();

І метод змінної заливки:

private static void FillVariables(Pipeline pipeline, Hashtable scriptParameters)
{
  // Add additional variables to PowerShell
  if (scriptParameters != null)
  {
    foreach (DictionaryEntry entry in scriptParameters)
    {
      CommandParameter Param = new CommandParameter(entry.Key as String, entry.Value);
      pipeline.Commands[0].Parameters.Add(Param);
    }
  }
}

таким чином ви можете легко додати декілька параметрів до сценарію. Я також помітив, що якщо ви хочете отримати значення зі змінної у вашому сценарії, так:

Object resultcollection = runspace.SessionStateProxy.GetVariable("results");

// результати є назвою v

вам доведеться робити це так, як я показав, тому що чомусь, якщо ви робите це так, як Kosi2801 пропонує перелік змінних скриптів не заповнюється вашими власними змінними.


3

Для мене був найбільш гнучким способом запуску сценарію PowerShell з C # PowerShell.Create().AddScript()

Фрагмент коду є

string scriptDirectory = Path.GetDirectoryName(
    ConfigurationManager.AppSettings["PathToTechOpsTooling"]);

var script =    
    "Set-Location " + scriptDirectory + Environment.NewLine +
    "Import-Module .\\script.psd1" + Environment.NewLine +
    "$data = Import-Csv -Path " + tempCsvFile + " -Encoding UTF8" + 
        Environment.NewLine +
    "New-Registration -server " + dbServer + " -DBName " + dbName + 
       " -Username \"" + user.Username + "\" + -Users $userData";

_powershell = PowerShell.Create().AddScript(script);
_powershell.Invoke<User>();
foreach (var errorRecord in _powershell.Streams.Error)
    Console.WriteLine(errorRecord);

Ви можете перевірити, чи є помилка, перевіривши Streams.Error. Перевірити колекцію було дуже зручно. Користувач - тип об'єкта, який повертає скрипт PowerShell.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.