用于运行 PowerShell cmdlet(函数?)的代码,该 cmdlet 位于 cmdlet(函数?)的 .ps1

本文关键字:cmdlet 函数 位于 ps1 代码 用于 PowerShell 运行 | 更新日期: 2023-09-27 18:36:33

我有代码可以从包含大量PowerShell cmdlet的.ps1文件运行PowerShell cmdlet...当我执行它时,我得到这个异常:

术语"New-BuildCVFromSql"不被识别为名称 cmdlet、函数、脚本文件或可操作程序。检查拼写 的名称,或者如果包含路径,请验证该路径是否为 更正并重试。

private void RunPowerShellCommandToBuildCV()
{
    string BigWindow = "";
    string FileNamePopup = "";
    TestPopup(ref BigWindow, ref FileNamePopup);
    string psScriptPath = @"D:'Project Files'CIS3G'Webapp'_Powershell'JcdcCv.psm1";
    string psScript = string.Empty;
    if(File.Exists(psScriptPath))
        psScript = File.ReadAllText(psScriptPath);
    else
        throw new FileNotFoundException("Wrong path for the script file");
    // Init the PowerShell runspace and pipeline - EWB
    Runspace runSpace = RunspaceFactory.CreateRunspace();
    runSpace.Open();
    // Set execution policy - EWB
    RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runSpace);
    runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
    Pipeline pipeline = runSpace.CreatePipeline();
    // I tried loading it both of the ways below and had no joy load the script from the string - EWB
    //pipeline.Commands.AddScript(psScript);
    // Load as file - EWB
    pipeline.Commands.AddScript(psScriptPath, false);
    // Add the outstring command to the pipeline.
    pipeline.Commands.Add("Out-String");
    Command myCommand = new System.Management.Automation.Runspaces.Command("New-BuildCVFromSql");
    CommandParameter SqlOrExcelFile                          = new CommandParameter("SqlOrExcelFile", @"C:'Documents and Settings'Brown.Ericw'My Documents'tempeval.sql");
    CommandParameter Js                                      = new CommandParameter("Js", "JCDC");
    CommandParameter FileName                                = new CommandParameter("FileName", @"Evaluation'EvaluationFormPartialListVM");
    myCommand.Parameters.Add(SqlOrExcelFile);
    myCommand.Parameters.Add(Js);
    myCommand.Parameters.Add(FileName);
    pipeline.Commands.Add(myCommand);
    Collection<PSObject> output = pipeline.Invoke();
    //foreach (PSObject psObject in output)
    //{
    //System.Diagnostics.Debug.WriteLine ("Object name: " + psObject.);
    //}
}

所以显然我没有正确加载这个脚本文件。在PowerShell ISE/IDE中,我必须先运行脚本,然后才能执行任何命令。这就是我做错了吗?

我只是想在别人写的一堆PowerShell脚本上放一个界面,所以我不能真正改变他/她的脚本文件,因为它们正在其他地方被其他人使用......

在 .ps1 文件中,我尝试调用的 cmdlet 定义如下:

# Create CV Method #
function New-BuildCVFromSql {
  param([Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]$SqlFile,
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]$js,
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]$FileName)
 ...

附录:根据这篇文章,我还尝试使用PowerShell而不是管道:

从 c# 调用电源外壳函数时出现问题

像这样,但我得到了同样的例外:

private void RunPowerShellCommandToBuildCV()
{
    string BigWindow = "";
    string FileNamePopup = "";
    TestPopup(ref BigWindow, ref FileNamePopup);
    string psScriptPath = @"D:'Project Files'CIS3G'Webapp'_Powershell'JcdcCv.psm1";
    string psScript = string.Empty;
    if (File.Exists(psScriptPath))
        psScript = File.ReadAllText(psScriptPath);
    else
        throw new FileNotFoundException("Wrong path for the script file");
    // Init the PowerShell runspace and pipeline - EWB
    using (Runspace runSpace = RunspaceFactory.CreateRunspace())
    {
        runSpace.Open();
        // Set execution policy - EWB
        RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runSpace);
        runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
        //Pipeline pipeline = runSpace.CreatePipeline();
        PowerShell ps = PowerShell.Create();
        ps.Runspace = runSpace;
        // Load as file - EWB
        ps.AddScript(psScriptPath);
        ps.AddCommand("New-BuildCVFromSql").AddParameters(new Dictionary<string, string>()
         {
             {"SqlOrExcelFile", @"C:'tempeval.sql"},
             {"Js", "JCDC"},
             {"FileName", @"Evaluation'EvaluationFormPartialListCV"}
         });
        foreach (PSObject result in ps.Invoke())
        {
            Debug.WriteLine ("Object : " + result);
        }
    }

增编2:

删除所有命令内容(因为它们仅适用于内置的 CmdLets,不适用于用户定义的函数)并执行此操作似乎是在调用代码,尽管运行时没有加载任何依赖项......我仍在调查这个问题。

ps.AddScript( @"New-BuildCVFromSql 'C:'Documents and Settings'Brown.Ericw'My Documents'tempeval.sql' JCDC 'Evaluation'EvaluationFormPartialListCV'" );

它似乎正在调用代码,尽管运行时没有加载任何依赖项......我仍在调查这个问题。但是,如果它从ISE运行,它可以工作...

用于运行 PowerShell cmdlet(函数?)的代码,该 cmdlet 位于 cmdlet(函数?)的 .ps1

在添加脚本后RunPowerShellCommandToBuildCV()的第二个版本中缺少一个ps.invoke()

    //load as file - EWB
    ps.AddScript( psScriptPath );
    ps.Invoke(); //<--------- !!!!
    ps.AddCommand( "New-BuildCVFromSql" ).AddParameters(new Dictionary<string, string>()
     {
         { "SqlOrExcelFile", @"C:'tempeval.sql" },
         { "Js", "JCDC" },
         { "FileName", @"Evaluation'EvaluationFormPartialListCV" }
     });

Invoke()之后,runspace知道有一个名为New-BuildCVFromSql的函数

这就是我的做法,它是一种享受:

private static void Test()
{
    dynamic parameters = new ExpandoObject();
    parameters.test= "myImage";
    parameters.arg2= 2;
    var results = RunPowerShellFunction("My-Function", parameters);
    var obj = results[0];
    var str = results[1];
}
private static dynamic RunPowerShellFunction(string functionName, dynamic parameters)
{
    dynamic rv = null;
    try
    {
        InitialSessionState iss = InitialSessionState.CreateDefault();
        using (Runspace runspace = RunspaceFactory.CreateRunspace(iss))
        {
            runspace.Name = typeof(DockerManager).Name;
            runspace.Open();
            RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runspace);
            runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
            using (var mainPowerShell = System.Management.Automation.PowerShell.Create())
            {
                mainPowerShell.Runspace = runspace;
                mainPowerShell.AddScript(LoadedScriptText, false);
                mainPowerShell.Invoke();
                var cmd = mainPowerShell.AddCommand(functionName);
                if (parameters != null)
                {
                    foreach (var parameter in parameters)
                    {
                        cmd.AddParameter(parameter.Key, parameter.Value);
                    }
                }
                rv = cmd.Invoke();
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }
    return rv;
}