3

为什么直接从 PowerShell 执行脚本的性能比从 System.Management.Automation.PowerShell 类执行脚本时快得多?当我直接在 PS 中执行我的脚本时,它需要不到一秒钟,但是当我通过下面的代码执行它时,调用需要几分钟。

public bool Execute(string filename, out string result)
{
    StringBuilder sb = new StringBuilder();

    using (PowerShell ps = PowerShell.Create())
    {
        ps.Runspace.SessionStateProxy.SetVariable("filename", filename);
        ps.AddScript(this.script);
        Collection<PSObject> psOutput = ps.Invoke();

        foreach (PSObject item in psOutput)
        {
            Console.WriteLine(item);
        }

        PSDataCollection<ErrorRecord> errors = ps.Streams.Error;
        foreach (ErrorRecord err in errors)
        {
            Console.WriteLine(err);
        }

        result = sb.ToString();
        return errors.Count == 0;
    }
}

脚本文本

[regex]$r = "\$\%\$@@(.+)\$\%\$@@";

(Get-Content $filename) | 
    Foreach-Object {
        $line = $_;
        $find = $r.matches($line);

        if ($find[0].Success) {
            foreach ($match in $find) {
                $found = $match.value           
                $replace = $found -replace "[^A-Za-z0-9\s]", "";            
                $line.Replace($found, $replace);
            }       
        }
        else 
        {
            $line;
        }
    } |
Set-Content $filename

我在c#中针对这个方法测试了脚本的执行,这个方法执行脚本的时间不到2秒。

public bool Execute(string filename, out string result)
{
    StringBuilder standardOutput = new StringBuilder();
    string currentPath = Path.GetDirectoryName(filename);
    string psFile = Path.Combine(currentPath, Path.GetFileNameWithoutExtension(Path.GetRandomFileName()) + ".ps1");

    this.script = this.script.Replace("$filename", "\"" + filename + "\"");
    File.WriteAllText(psFile, this.script);

    using (Process process = new Process())
    {
        process.StartInfo = new ProcessStartInfo("powershell.exe", String.Format("-executionpolicy unrestricted \"{0}\"", psFile))
        {
            WindowStyle = ProcessWindowStyle.Hidden,
            UseShellExecute = false,
            RedirectStandardOutput = true
        };

        process.Start();

        var output = process.StandardOutput.ReadToEnd();
        while (!process.HasExited)
        {
            standardOutput.Append(process.StandardOutput.ReadToEnd());
        }

        process.WaitForExit();
        standardOutput.Append(process.StandardOutput.ReadToEnd());

        result = standardOutput.ToString();
        return process.ExitCode == 0;
    }
}
4

0 回答 0