2011-11-10 79 views
1

我製作了一個頁面,允許用戶查看服務器上的批處理文件列表並運行它們。遠程運行批處理文件,向用戶顯示結果並允許用戶提供輸入

問題是批處理文件需要輸入如「按任意鍵繼續」或「如果您確定要繼續按Y」。目前我的代碼提供輸入預設情況:

if (outputLine.Contains("Y or N")) 
    inputLine = "Y"; 
if (outputLine.Contains("pause")) 
    inputLine = "X"; 

但我現在想給用戶提供的輸入,而不是我的代碼的能力。

我已經花了大部分時間研究如何做到這一點,並沒有提出任何建議。

這裏是我的代碼:

private void RunScript(int scriptId) 
{ 
    ScriptData data = new ScriptData(); 
    Script script = data.GetScript(scriptId); 

    ProcessStartInfo psi = new ProcessStartInfo() 
    { 
     FileName = script.Path, 
     RedirectStandardOutput = true, 
     RedirectStandardInput = true, 
     UseShellExecute = false, 
     CreateNoWindow = false 
    }; 

    Process proc = new Process(); 
    proc.StartInfo = psi; 

    proc.Start(); 

    StreamReader reader = proc.StandardOutput; 
    StreamWriter writer = proc.StandardInput; 

    string outputLine; 
    string inputLine = string.Empty; 
    string display = string.Empty; 

    while (!reader.EndOfStream) 
    { 
     outputLine = reader.ReadLine(); 
     display += outputLine + "\r\n"; 

     if (inputLine != string.Empty) 
      display += inputLine + "\r\n"; 

     inputLine = string.Empty; 
     if (outputLine.Contains("Y or N")) 
      inputLine = "Y"; 
     if (outputLine.Contains("pause")) 
      inputLine = "X"; 

     if (inputLine != string.Empty) 
      writer.WriteLine(inputLine); 
    } 

    display = Server.HtmlEncode(display); 
    display = display.Replace("\r\n", "<br />"); 
    litOutput.Text = display; 
} 

回答

0

終於解決了這個問題,我現在得到當我運行一個腳本是非常接近的命令提示符窗口。

下面是它的工作原理很基本的總結:

我開始運行一個批處理文件的新方法。同時,我開始一個新的線程,不斷循環詢問進程的更多輸出,並將該輸出存儲到隊列中。我的.NET計時器不斷檢查隊列中的文本,並將其輸出到我的ajax面板。我使用文本框和ajax將文本輸入到流程輸入和我的ajax面板中。還需要大量的JavaScript,我不得不使用會話變量使其運行順利。

// ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ======// 

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" 
    CodeBehind="Scripts.aspx.cs" Inherits="MITool.Scripts" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server"> 
</asp:Content> 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
    <script type="text/javascript" language="javascript"> 
     var script = ''; 

     function ShowScriptModal() { 
      $('#overlay').css({ width: $(document).width(), height: $(document).height(), 'display': 'block' }).animate({ opacity: 0.85 }, 0, function() { $('#scriptModal').show(); }); 
     } 

     function ScriptInputKeypress(e) { 
      if (e.keyCode == 13) { 
       ScriptInput(); 
      } 
     } 

     function ScriptInput() { 
      var txtInput = document.getElementById("txtInput"); 
      var input = txtInput.value; 
      var hiddenInput = document.getElementById("hiddenInput"); 

      if (input == '') 
       return; 

      hiddenInput.value = input; 

      txtInput.value = ''; 
     } 

     function CheckForNewOutput() { 
      var outputUpdatePanel = document.getElementById("OutputUpdatePanel"); 
      var pageScript = outputUpdatePanel.innerHTML; 
      if (script != pageScript) { 
       script = pageScript; 
       ScrollToBottom(); 
      } 
      setTimeout("CheckForNewOutput()", 100); 
     } 

     function ScrollToBottom() { 
      $('#OutputPanel').scrollTop($('#OutputUpdatePanel').height()); 
     } 
    </script> 
    <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" EnablePartialRendering="true" LoadScriptsBeforeUI="true" /> 
    <div id="scriptModal"> 
     <div id="ScriptInputOutput"> 
      <asp:Panel ID="OutputPanel" runat="server" Width="700" Height="250" ScrollBars="Vertical" 
       Style="margin: 10px auto; border: 1px solid #CCC; padding: 5px;" ClientIDMode="Static"> 
       <controls:ScriptOutput ID="ScriptOutputControl" runat="server" /> 
      </asp:Panel> 
      <asp:Panel ID="InputPanel" runat="server" DefaultButton="btnScriptInput" > 
       <asp:TextBox ID="txtInput" runat="server" ClientIDMode="Static" onkeypress="ScriptInputKeypress(event)" /> 
       <asp:HiddenField ID="hiddenInput" runat="server" ClientIDMode="Static" /> 
       <asp:Button ID="btnScriptInput" runat="server" Text="Script Input" ClientIDMode="Static" OnClick="btnScriptInput_Click" style="display:none" />   
       <asp:Button ID="btnExit" runat="server" CssClass="floatRight" Text="Exit" OnClick="btnExit_Click" /> 
      </asp:Panel> 
     </div> 
    </div> 
    <asp:Literal ID="litScript" runat="server" /> 
    <ul id="breadcrumb"> 
     <li><a href="/dashboard.aspx">Main page</a> &gt;</li> 
     <li class="current">Scripts</li> 
    </ul> 
    <div class="content"> 
     <h2> 
      <asp:Label ID="lblHeader" runat="server" Text="Scripts" /></h2> 
     <div class="clear"> 
     </div> 
     <div class="table-content"> 
      <asp:Label ID="lblMessage" runat="server" CssClass="redMessage" /> 
      <asp:Repeater ID="rptScripts" runat="server" OnItemCommand="rptScripts_ItemCommand"> 
       <HeaderTemplate> 
        <table class="table" cellpadding="0" cellspacing="0"> 
         <tr> 
          <th> 
           ID 
          </th> 
          <th> 
           Name 
          </th> 
          <th> 
           Location 
          </th> 
          <th> 
          </th> 
         </tr> 
       </HeaderTemplate> 
       <ItemTemplate> 
        <tr> 
         <td> 
          <%# Eval("ScriptId") %> 
         </td> 
         <td> 
          <%# Eval("Name") %> 
         </td> 
         <td> 
          <%# Eval("Path") %> 
         </td> 
         <td> 
          <asp:LinkButton ID="btnRunScript" runat="server" Text="Run" CommandName="Run" CommandArgument='<%# Eval("ScriptId") %>' /> 
         </td> 
        </tr> 
       </ItemTemplate> 
       <FooterTemplate> 
        </table> 
       </FooterTemplate> 
      </asp:Repeater> 
      <div> 
      </div> 
     </div> 
    </div> 
    <script type="text/javascript" language="javascript"> 
     CheckForNewOutput(); 
    </script> 
</asp:Content> 

// ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ======// 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using MITool.Data.ScriptManager; 
using System.Diagnostics; 
using System.IO; 
using System.Web.Security; 
using System.Web.Services; 
using System.Collections.Concurrent; 
using System.Threading; 

namespace MITool 
{ 
    public partial class Scripts : System.Web.UI.Page 
    { 
     ConcurrentQueue<char> ScriptOutputQueue 
     { 
      get 
      { 
       return (ConcurrentQueue<char>)Session["ScriptOutputQueue"]; 
      } 
      set 
      { 
       Session["ScriptOutputQueue"] = value; 
      } 
     } 
     Process CurrentProcess 
     { 
      get 
      { 
       return (Process)Session["CurrentProcess"]; 
      } 
      set 
      { 
       Session["CurrentProcess"] = value; 
      } 
     } 
     bool ScriptRunning 
     { 
      get 
      { 
       if (CurrentProcess == null) 
        return false; 
       if (!CurrentProcess.HasExited || !CurrentProcess.StandardOutput.EndOfStream) 
        return true; 
       return false; 
      } 
     } 
     bool OutputProcessing 
     { 
      get 
      { 
       if (ScriptOutputQueue != null && ScriptOutputQueue.Count != 0) 
        return true; 
       return false; 
      } 
     } 

     Thread OutputThread; 

     void Reset() 
     { 
      ScriptOutputControl.SetTimerEnabled(false); 
      ScriptOutputControl.ClearOutputText(); 
      if (CurrentProcess != null && !CurrentProcess.HasExited) 
       CurrentProcess.Kill(); 
      if (OutputThread != null && OutputThread.IsAlive) 
       OutputThread.Abort(); 
      ScriptOutputQueue = new ConcurrentQueue<char>(); 

      litScript.Text = string.Empty; 
      txtInput.Text = string.Empty; 
     } 

     void Page_Load(object sender, EventArgs e) 
     { 
      if (IsPostBack) return; 

      Reset(); 

      FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; 
      string role = id.Ticket.UserData; 

      ScriptData data = new ScriptData(); 
      List<Script> scripts = data.GetScriptsByRole(role); 
      rptScripts.DataSource = scripts; 
      rptScripts.DataBind(); 
     } 

     protected void rptScripts_ItemCommand(object source, RepeaterCommandEventArgs e) 
     { 
      switch (e.CommandName) 
      { 
       case "Run": StartScript(Int32.Parse(e.CommandArgument.ToString())); 
        break; 
      } 
     } 

     void StartScript(int id) 
     { 
      if (ScriptRunning || OutputProcessing) 
       return; 

      Reset(); 

      ScriptData data = new ScriptData(); 
      History history = new History() 
      { 
       UserName = HttpContext.Current.User.Identity.Name, 
       BatchFileId = id, 
       DateRun = DateTime.Now 
      }; 
      data.CreateHistory(history);    

      Script script = data.GetScript(id); 

      ProcessStartInfo psi = new ProcessStartInfo() 
      { 
       FileName = script.Path, 
       RedirectStandardOutput = true, 
       RedirectStandardInput = true, 
       UseShellExecute = false, 
       CreateNoWindow = true 
      }; 

      CurrentProcess = new Process(); 
      CurrentProcess.StartInfo = psi; 

      OutputThread = new Thread(Output); 

      CurrentProcess.Start(); 
      OutputThread.Start(); 

      ScriptOutputControl.SetTimerEnabled(true); 

      litScript.Text = "<script type=\"text/javascript\" language=\"javascript\">ShowScriptModal();</script>"; 

      SetFocus("txtInput"); 
     } 

     void Output() 
     { 
      while (ScriptRunning) 
      { 
       var x = CurrentProcess.StandardOutput.Read(); 
       if (x != -1) 
        ScriptOutputQueue.Enqueue((char)x); 
      } 
     } 

     public void btnScriptInput_Click(object sender, EventArgs e) 
     { 
      string input = hiddenInput.Value.ToString(); 

      ScriptOutputControl.Input(input); 

      foreach (char x in input.ToArray()) 
      { 
       if (CurrentProcess != null && !CurrentProcess.HasExited) 
       { 
        CurrentProcess.StandardInput.Write(x); 
       } 
       Thread.Sleep(1); 
      } 
     } 

     protected void btnExit_Click(object sender, EventArgs e) 
     { 
      Reset(); 
     } 
    } 
} 

// ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ======// 

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ScriptOutput.ascx.cs" 
    Inherits="MITool.Controls.ScriptOutput" %> 
<asp:Label ID="lblStats" runat="server" Style="color: Red" /> 
<br /> 
<asp:UpdatePanel ID="OutputUpdatePanel" runat="server" ClientIDMode="Static"> 
    <Triggers> 
     <asp:AsyncPostBackTrigger ControlID="UpdateTimer" EventName="Tick" /> 
     <asp:AsyncPostBackTrigger ControlID="btnScriptInput" EventName="Click" /> 
    </Triggers> 
    <ContentTemplate> 
     <asp:Literal ID="litOutput" runat="server" /> 
    </ContentTemplate> 
</asp:UpdatePanel> 
<asp:Timer ID="UpdateTimer" Interval="100" runat="server" OnTick="UpdateTimer_Tick" Enabled="false" /> 

// ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ======// 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Collections.Concurrent; 
using System.Diagnostics; 

namespace MITool.Controls 
{ 
    public partial class ScriptOutput : System.Web.UI.UserControl 
    { 
     string Output 
     { 
      get 
      { 
       if (Session["Output"] != null) 
        return Session["Output"].ToString(); 
       return string.Empty; 
      } 
      set 
      { 
       Session["Output"] = value; 
      } 
     } 

     ConcurrentQueue<char> ScriptOutputQueue 
     { 
      get 
      { 
       return (ConcurrentQueue<char>)Session["ScriptOutputQueue"]; 
      } 
      set 
      { 
       Session["ScriptOutputQueue"] = value; 
      } 
     } 
     Process CurrentProcess 
     { 
      get 
      { 
       return (Process)Session["CurrentProcess"]; 
      } 
      set 
      { 
       Session["CurrentProcess"] = value; 
      } 
     } 
     bool ScriptRunning 
     { 
      get 
      { 
       if (CurrentProcess == null) 
        return false; 
       if (!CurrentProcess.HasExited || CurrentProcess.StandardOutput.Peek() != -1) 
        return true; 
       return false; 
      } 
     } 
     bool OutputProcessing 
     { 
      get 
      { 
       if (ScriptOutputQueue != null && ScriptOutputQueue.Count != 0) 
        return true; 
       return false; 
      } 
     } 

     public void SetTimerEnabled(bool enabled) 
     { 
      UpdateTimer.Enabled = enabled; 
     } 
     public void ClearOutputText() 
     { 
      Output = string.Empty; 
      litOutput.Text = Output; 
     } 

     protected void UpdateTimer_Tick(object sender, EventArgs e) 
     { 
      ProcessOutput(); 

      if (!ScriptRunning && !OutputProcessing) 
      { 
       UpdateTimer.Enabled = false; 

       Output += "<br />// SCRIPT END //<br />"; 
       litOutput.Text = Output; 
      } 
     } 

     public void Input(string s) 
     { 
      Output += "<br />// " + s + "<br />"; 
     } 

     void ProcessOutput() 
     { 
      string s = string.Empty; 

      while (ScriptOutputQueue != null && ScriptOutputQueue.Any()) 
      { 
       char x; 
       if (ScriptOutputQueue.TryDequeue(out x)) 
       { 
        s += x; 
       } 
      } 

      if (s != string.Empty) 
      { 
       s = Server.HtmlEncode(s); 
       s = s.Replace("\r\n", "<br />"); 

       Output += s; 
      } 

      litOutput.Text = Output; 
     } 
    } 
} 

// ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ======/ 
相關問題