Редактировать: обо всем по порядку
Смысл vbscript в том, чтобы действовать как среда REPL или командной строки / bash, она упрощена просто для повторной печати пользовательского ввода
Таким образом, другими словами, процесс cscript должен оставаться в живых, и пользовательский ввод для каждого прохода должен отправляться только этому процессу.
А также это означает, что внутреннее состояние скрипта должно сохраняться для каждогоpass ( One pass = каждый раз, когда нажимается кнопка «Отправить» в winform C # , или в контексте vbscript, One pass = каждый раз, когда ^ Z вводится ).
Например, если скрипт vbscript необходимо изменить для демонстрации поведения с сохранением состояния, вы можете сделать следующие моды:
- В строке
dim wsh,stmt,l...
добавить его с помощью : dim passcnt : passcnt=1
- В строке
wsh.Echo("Enter lines of strings, press ctrl-z...
, заменить последнюю закрывающую скобку на & " (pass #" & passcnt & ")")
- В строке
wsh.Echo("End output")
добавить код : passcnt = passcnt + 1
Запустив vbscript, консоль покажет номер проходаmented на каждом проходе.
- Winform C # может быть изменен любым способом, пока вышеупомянутое условие все еще выполняется.
- Попробуйте посмотреть, что делает скрипт
cscript ask_SO.vbs
, это должно прояснить ситуацию
Я думаю, это самое ясное, что я могу сделать.
Я хотел бы использовать перенаправление stdout / stdin System.Diagnostics.Process для подачи входных текстов в следующий VBScript.
Что делает vbscript, так это то, что он позволяет пользователювведите несколько строк строк в консоль, и когда будет введен символ ^ z, скрипт просто выведет все данные в консоль:
Пример вывода
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.
Enter lines of strings, press ctrl-z when you are done (ctrl-c to quit):
I come with no wrapping or pretty pink bows.
got line
I am who I am, from my head to my toes.
got line
I tend to get loud when speaking my mind.
got line
Even a little crazy some of the time.
got line
I'm not a size 5 and don't care to be.
got line
You can be you and I can be me.
got line
got line
Source: https://www.familyfriendpoems.com/poem/be-proud-of-who-you-are
got line
^Z
=====================================
You have entered:
I come with no wrapping or pretty pink bows.
I am who I am, from my head to my toes.
I tend to get loud when speaking my mind.
Even a little crazy some of the time.
I'm not a size 5 and don't care to be.
You can be you and I can be me.
Source: https://www.familyfriendpoems.com/poem/be-proud-of-who-you-are
End output
Enter lines of strings, press ctrl-z when you are done (ctrl-c to quit):
После этогопользователь может ввести другой фрагмент текста и повторить процесс.
Это код сценария:
ask_SO.vbs
dim wsh,stmt,l : set wsh = WScript
do
wsh.Echo("Enter lines of strings, press ctrl-z when you are done (ctrl-c to quit):")
'stmt=wsh.StdIn.ReadAll()
do
l=wsh.StdIn.ReadLine()
wsh.echo("got line")
stmt = stmt & l & vbcrlf
loop while (not wsh.StdIn.AtEndOfStream)
wsh.Echo("=====================================")
wsh.Echo("You have entered:")
wsh.Echo(stmt)
wsh.Echo("End output")
loop
Это способ вызова сценария.:
cscript ask_SO.vbs
Я получил следующий код C # (тип проекта установлен на Консольное приложение вместо Windows Forms ):
frmPostSample
public class frmPostSample : Form
{
Process proc_cscr;
StreamWriter sw;
public frmPostSample()
{
InitializeComponent2();
}
#region Copied from generated code
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent2()
{
this.txt_lines = new System.Windows.Forms.TextBox();
this.Btn_Send = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// txt_lines2
//
this.txt_lines.Location = new System.Drawing.Point(41, 75);
this.txt_lines.Multiline = true;
this.txt_lines.Name = "txt_lines2";
this.txt_lines.Size = new System.Drawing.Size(689, 298);
this.txt_lines.TabIndex = 0;
//
// Btn_Send2
//
this.Btn_Send.Location = new System.Drawing.Point(695, 410);
this.Btn_Send.Name = "Btn_Send2";
this.Btn_Send.Size = new System.Drawing.Size(75, 23);
this.Btn_Send.TabIndex = 1;
this.Btn_Send.Text = "&Send";
this.Btn_Send.UseVisualStyleBackColor = true;
this.Btn_Send.Click += new System.EventHandler(this.Btn_Send_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.Btn_Send);
this.Controls.Add(this.txt_lines);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.TextBox txt_lines;
private System.Windows.Forms.Button Btn_Send;
#endregion
private void Btn_Send_Click(object sender, EventArgs e)
{
if (proc_cscr == null)
{
if (!File.Exists("ask_SO.vbs"))
{
MessageBox.Show("Script file not exist");
return;
}
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cscript";
startInfo.Arguments = "//nologo ask_SO.vbs";
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
proc_cscr = new Process();
proc_cscr.StartInfo = startInfo;
proc_cscr.Start();
sw = proc_cscr.StandardInput;
}
OutPrint();
foreach (var vbsline in txt_lines.Lines)
{
sw.WriteLine(vbsline); // <-------- SW WRITELINE
sw.Flush();
OutPrint();
}
//sw.Flush();
sw.Close();
while (true)
{
var s2 = proc_cscr.StandardOutput.ReadLineAsync();
s2.Wait();
Console.WriteLine(s2.Result);
if (proc_cscr.StandardOutput.Peek() == -1) break;
}
}
private void OutPrint()
{
string l;
while (proc_cscr.StandardOutput.Peek() != -1)
{
l = proc_cscr.StandardOutput.ReadLine();
Console.WriteLine(l);
}
}
}
Запустите программу, и если вы правильно установили тип проекта «Консольное приложение», должны появиться окно консоли и окно графического интерфейса пользователя.Вы просто вставляете текст в область ввода текста и нажимаете кнопку отправки, и наблюдаете результат в окне консоли.
Однако поведение формы C # отличается от прямого запуска сценария cscript ask_SO.vbs
:
- Скрипт может принять только один проход ввода - второй проход выдает ошибку «Невозможно записать в закрытый TextWriter» в строке с комментарием
SW WRITELINE
- Я знаю, что это потому, что я закрылпоток stdin, но в противном случае я не могу заставить сценарий двигаться вперед - Кроме того, у меня отображается сообщение об ошибке:
...\ask_SO.vbs(8, 9) Microsoft VBScript runtime error: Input past end of file
. - Эхо "got line" не отображаетсясразу после кода c # напишите строку ввода в stdin (опять же, в строке с комментарием
SW WRITELINE
).
Я искал в Интернете, чтобы найти решение, но большинство материалов толькопоказывает ввод без использования символа ^ z, или, другими словами, принимает только однопроходный ввод.
Вы можете загрузить решение C # visual studio здесь (vbscript включен - вы просто загружаетерешение в визуальномStudio 2019 и нажмите F5 для запуска).
Примечание
Кодировка, полученная из proc_cscr.StandardOutput.CurrentEncoding.BodyName
и proc_cscr.StandardInput.Encoding.BodyName
, равна big5
, это DBCSCodePageEncoding, используемая для кодирования китайских символов.
Я осознал, что мне нужно упомянуть об этом, когда я попробовал предложение, упомянутое в ответе, написать (char) 26 в поток stdin.Поскольку Encoding.GetEncoding("big5").GetBytes(new char[]{(char)26})
возвращает только один байт (два байта для Unicode: {byte[2]} [0]: 26 [1]: 0
), я сделал sw.Write((char)26);
и добавил также sw.flush()
.Это все еще не сработало.