1

我正在尝试使用 C# asp.net 网页在我的服务器上执行 .ps1 PowerShell 文件。该脚本采用一个参数,并且我已通过使用服务器上的命令提示符验证它是否有效。运行后,我需要在网页上显示结果。

目前,我正在使用:

protected void btnClickCmdLine(object sender, EventArgs e)
{
    lblResults.Text = "Please wait...";
    try
    {
        string tempGETCMD = null;
        Process CMDprocess = new Process();
        System.Diagnostics.ProcessStartInfo StartInfo = new System.Diagnostics.ProcessStartInfo();
        StartInfo.FileName = "cmd"; //starts cmd window
        StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        StartInfo.CreateNoWindow = true;
        StartInfo.RedirectStandardInput = true;
        StartInfo.RedirectStandardOutput = true;
        StartInfo.UseShellExecute = false; //required to redirect
        CMDprocess.StartInfo = StartInfo;
        CMDprocess.Start();
        lblResults.Text = "Starting....";
        System.IO.StreamReader SR = CMDprocess.StandardOutput;
        System.IO.StreamWriter SW = CMDprocess.StandardInput;
        SW.WriteLine("@echo on");

        SW.WriteLine("cd C:\\Tools\\PowerShell\\");

       SW.WriteLine("powershell .\\poweron.ps1 **parameter**");

        SW.WriteLine("exit"); //exits command prompt window
        tempGETCMD = SR.ReadToEnd(); //returns results of the command window
        lblResults.Text = tempGETCMD;
        SW.Close();
        SR.Close();
    }
    catch (Exception ex)
    {
        lblErrorMEssage.Text = ex.ToString();
        showError();
    }
}

但是,如果我包含调用 powershell 的行,它甚至不会显示初始的“请稍候..”。它最终会超时,即使我增加了 ScriptManager 上的 AsyncPostBackTimeout。谁能告诉我我做错了什么?谢谢

4

3 回答 3

5

有点过时了;但是,对于那些寻找类似解决方案的人来说,我不会创建一个 cmd 并将 powershell 传递给它,而是利用System.Management.Automation命名空间并在没有 cmd 中间人的情况下创建一个 PowerShell 控制台对象服务器端。您可以将命令或 .ps1 文件传递​​给AddScript()函数(两者都带有参数)以供执行。比必须调用 powershell.exe 的单独 shell 要干净得多。

确保应用程序池具有适当的身份,并且该主体具有执行 PowerShell 命令和/或脚本所需的适当权限级别。此外,请确保您已通过Set-ExecutionPolicy将执行策略配置为适当的级别(不受限制/或远程签名,除非您正在签名),以防您仍然要执行 .ps1 文件服务器端。

下面是一些启动代码,它们正在执行由 TextBox Web 表单提交的命令,就好像它是使用这些对象的 PowerShell 控制台一样 - 应该说明该方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Management.Automation;
using System.Text;

namespace PowerShellExecution
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void ExecuteCode_Click(object sender, EventArgs e)
        {
            // Clean the Result TextBox
            ResultBox.Text = string.Empty;

            // Initialize PowerShell engine
            var shell = PowerShell.Create();

            // Add the script to the PowerShell object
            shell.Commands.AddScript(Input.Text);

            // Execute the script
            var results = shell.Invoke();

            // display results, with BaseObject converted to string
            // Note : use |out-string for console-like output
            if (results.Count > 0)
            {
                // We use a string builder ton create our result text
                var builder = new StringBuilder();

                foreach (var psObject in results)
                {
                    // Convert the Base Object to a string and append it to the string builder.
                    // Add \r\n for line breaks
                    builder.Append(psObject.BaseObject.ToString() + "\r\n");
                }

                // Encode the string in HTML (prevent security issue with 'dangerous' caracters like < >
                ResultBox.Text = Server.HtmlEncode(builder.ToString());
            }
        }
    }
}

这是为您撰写的一篇文章,涵盖了如何使用 Visual Studio 从头到尾创建页面并完成此操作,http ://grokgarble.com/blog/?p=142 。

于 2014-09-22T13:25:10.660 回答
0

我认为您不能像这样直接从 aspx 页面运行 powershell 脚本,因为它可能与安全原因有关。为了运行和捕获输出:

  1. 创建一个远程运行空间: http ://social.msdn.microsoft.com/Forums/hu/sharepointgeneralprevious/thread/88b11fe3-c218-49a3-ac4b-d1a04939980c http://msdn.microsoft.com/en-us/library/ windows/桌面/ee706560%28v=vs.85%29.aspx

  2. PSHost: 在 Pipeline.Invoke 抛出后在 C# 中捕获 Powershell 输出

1对我来说效果很好。

顺便说一句,标签没有更新,因为事件没有完成。您可能需要在等待 powershell 时使用 ajax 来显示标签。

于 2012-10-26T21:01:59.300 回答
0

当我尝试这个时,我发现标准输入需要刷新或关闭SR.ReadToEnd()才能完成。尝试这个:

    lblResults.Text = "Please wait...";
    try
    {
        string tempGETCMD = null;
        Process CMDprocess = new Process();
        System.Diagnostics.ProcessStartInfo StartInfo = new System.Diagnostics.ProcessStartInfo();
        StartInfo.FileName = "cmd"; //starts cmd window
        StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        StartInfo.CreateNoWindow = true;
        StartInfo.RedirectStandardInput = true;
        StartInfo.RedirectStandardOutput = true;
        StartInfo.UseShellExecute = false; //required to redirect
        CMDprocess.StartInfo = StartInfo;
        CMDprocess.Start();
        lblResults.Text = "Starting....";
        using (System.IO.StreamReader SR = CMDprocess.StandardOutput)
        {
            using (System.IO.StreamWriter SW = CMDprocess.StandardInput)
            {
                SW.WriteLine("@echo on");
                SW.WriteLine("cd C:\\Tools\\PowerShell\\");
                SW.WriteLine("powershell .\\poweron.ps1 **parameter**");
                SW.WriteLine("exit"); //exits command prompt window
            }
            tempGETCMD = SR.ReadToEnd(); //returns results of the command window
        }
        lblResults.Text = tempGETCMD;
    }
    catch (Exception ex)
    {
        lblErrorMessage.Text = ex.ToString();
        showError();
    }
}
于 2012-10-26T21:13:37.060 回答