Process.Start with Word running fails to wait for exit - c#

I have a method that allows a word document to be opened in word and waits for word to exit before completing.
If word is not already running all works well.
If word is running the process exits immediately so I can;t wait for exit.
Any ideas how I can wait for the document to close if word is already running?
This is on Windows 8.1
public void ShowExternalReference(string externalRef, bool waitForCompletion)
{
if (externalRef.NotEmpty())
{
var pInfo = new ProcessStartInfo {FileName = externalRef};
// Start the process.
Process p = Process.Start(pInfo);
if (waitForCompletion)
{
// Wait for the window to finish loading.
p.WaitForInputIdle();
// Wait for the process to end.
p.WaitForExit();
}
}
}

you can get the current running Word Process and attach to the events
I got some info here
Here is an example for attaching and putting text into the doc...
Hope this helps.
using Word = Microsoft.Office.Interop.Word;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load_1(object sender, EventArgs e)
{
}
public void ShowExternalReference(string externalRef, bool waitForCompletion)
{
if (externalRef.Length > 0)
{
var pInfo = new ProcessStartInfo { FileName = externalRef };
bool isrunning = false;
Process [] pList = Process.GetProcesses();
foreach(Process x in pList)
{
if( x.ProcessName.Contains("WINWORD"))
{
isrunning = true;
Word.Application myWordApp =
System.Runtime.InteropServices.Marshal.GetActiveObject(
"Word.Application") as Word.Application;
if(myWordApp.ActiveDocument.FullName.Contains(externalRef))
// do something
myWordApp.ActiveDocument.Content.Text = " already open";
}
}
if(!isrunning)
{
// Start the process.
Process p = Process.Start(pInfo);
if (waitForCompletion)
{
// Wait for the window to finish loading.
p.WaitForInputIdle();
// Wait for the process to end.
p.WaitForExit();
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
string myWordFile = #"C:\Temp\test.docx";
ShowExternalReference(myWordFile, true);
}
private void listView1_ItemChecked(object sender, ItemCheckEventArgs e)
{
listView1.Items[e.Index].Group = listView1.Groups[e.NewValue == CheckState.Checked ? 0 : 1];
}

Process[] pname = Process.GetProcessesByName("winword.exe");
if(pname.Length == 0)
{
//not running..
}
you could loop this through a background thread perhaps to continually test if Word is running, and fire an event back when it isn't

Related

How can i Scan if a process is Opened in another Thread?

Basically I have a WPF application Where the user Write A process Name ,
Then a new Thread start where it keeps scanning if the process is Opened yet or not , The Thread will be Alive untill the process is Found .. So i can Get the handle and write The Memory !
private void scanBtn_Click (object sender, RoutedEventArgs e)
{
Thread s = new Thread(( ) => {
this.Dispatcher.Invoke((Action)(( ) =>
{
scanner(pName.Text);
}));
});
try
{
if (pName.Text != string.Empty)
{
InfoTxt.Text = "[ WAITING FOR PROCESS TO OPEN ]";
s.Start();
pName.IsEnabled = false;
if (!s.IsAlive)
{
pName.IsEnabled = true;
InfoTxt.Text = "[ FOUND ]";
Process p = Process.GetProcessesByName(pName.Text)[0];
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private static void scanner ( string procName)
{
while (true)
{
Process s = SeekProcName(procName);
if (s != null) break;
}
}
private static Process SeekProcName(string pName)
{
Process[] procs = Process.GetProcesses().Where(p => p.MainWindowHandle != (IntPtr)0).ToArray();
Process f = null;
foreach (var item in procs)
{
if (item.ProcessName.ToLower() == pName.ToLower())
{
f = item;
break;
}
}
return f;
}
The s thread is trying to run a delegate on the UI thread, which means it's no different than calling SeekProcName(procName) in the event handler directly.
It would be better to use Task.Run and async/await to run the check in a background thread. When await returns, execution resumes in the UI thread which means the UI can be updated without requiring Invoke or BeginInvoke
private async void scanBtn_Click (object sender, RoutedEventArgs e)
{
InfoTxt.Text = "[ WAITING FOR PROCESS TO OPEN ]";
//Read the textbox contets *before* starting the task
var name=pName.Text;
var p=await Task.Run(()=>SeekProcName(name));
if (p!=null)
{
InfoTxt.Text = "[ FOUND ]";
}
}
This can be called in a loop, with a small delay between iterations, without blocking the UI thread :
private async void scanBtn_Click (object sender, RoutedEventArgs e)
{
while(someCondition)
{
InfoTxt.Text = "[ WAITING FOR PROCESS TO OPEN ]";
var name=pName.Text;
var p=await Task.Run(()=>SeekProcName(name));
if (p!=null)
{
InfoTxt.Text = "[ FOUND ]";
}
await Task.Delay(1000);
}
}

Launching application from server creates Open File for lifetime of application

I launch a program located on one of my file servers. After launching the program it shows as an Open file in Computer Management.
Is there a way I can close this open file while my program runs so it doesn't show up in Computer Management?
My code is below. I'd be happy to take suggestions on improving my program, but I'm really just looking for a solution to stop all these Open Files from appearing.
Program.cs -- starts the program, handles logic to launch my application
using System;
using System.Windows.Forms;
using System.Diagnostics;
namespace IT_TaskbarApp
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
string programName = "TEG System Helper";
//Process[] proc = Process.GetProcessesByName(programName);
if (Process.GetProcessesByName(programName).Length == 1)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Primary());
}
else
{
foreach (Process p in Process.GetProcessesByName(programName))
{
if (Process.GetCurrentProcess().Id != p.Id)
{
p.CloseMainWindow();
p.Close();
p.Kill();
p.Dispose();
}
}
Main();
}
}
}
}
Primary.cs -- creates an icon in the system icons which I can use to send notifications and easily access utilities within our organization
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
namespace IT_TaskbarApp
{
public partial class Primary : Form
{
private NotifyIcon notifyIcon;
private ContextMenu contextMenu;
private MenuItem[] menuItem = new MenuItem[8];
private IContainer components;
//private Boolean SendNotices = true;
private DateTime startTime = DateTime.Now;
private DateTime currentTime;
private Icon tegroupIcon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("IT_TaskbarApp.Src.tegroup.ico"));
private string prevNotification = "";
private bool isRunning = true;
private BackgroundWorker bgNotify = new BackgroundWorker();
private const string programName = "TEG System Helper";
public Primary()
{
this.FormClosing += Primary_FormClosing; //remove ghost icon in taskbar
ForeColor = Color.Blue;
BackColor = Color.Green;
components = new Container();
contextMenu = new ContextMenu();
for (int i = 0; i < menuItem.Length; i++)
{
menuItem[i] = new MenuItem();
menuItem[i].Index = i;
menuItem[i].Click += new EventHandler(LoadProcess);
}
menuItem[0].Text = programName;
menuItem[1].Text = "Knowledge Base";
menuItem[2].Text = "Policies";
menuItem[3].Text = "Feedback";
menuItem[4].Text = "Global Shop Search";
menuItem[5].Text = "-";
menuItem[6].Text = "Submit Ticket";
menuItem[7].Text = "Send Email";
//initialize contextMenu
contextMenu.MenuItems.AddRange(menuItem);
// Create the NotifyIcon.
notifyIcon = new NotifyIcon(components)
{
Icon = tegroupIcon,
BalloonTipIcon = new ToolTipIcon(),
ContextMenu = contextMenu, //the menu when right clicked
Text = programName,
Visible = true,
BalloonTipTitle = programName,
};
notifyIcon.DoubleClick += new EventHandler(Icon_DoubleClick);
InitializeComponent();
bgNotify.WorkerSupportsCancellation = true;
bgNotify.WorkerReportsProgress = true;
bgNotify.DoWork += NotifyUser;
bgNotify.ProgressChanged += SendNotice;
//bgNotify.RunWorkerCompleted += BgNotify_RunWorkerCompleted; //enable this to perform an action when the thread dies
bgNotify.RunWorkerAsync();
//Thread tNotify = new Thread();
}
#region SupportedFunctions
private void NotifyUser(object Sender, EventArgs e)
{
Console.WriteLine("enter");
while (isRunning)
{
currentTime = DateTime.Now;
#region DisplayCurrentTime
if (currentTime.Hour < 10 || currentTime.Minute < 10)
{
if (currentTime.Hour < 10)
{
if (currentTime.Minute < 10)
{
Console.WriteLine("0{0}:0{1}", currentTime.Hour, currentTime.Minute);
}
else
{
Console.WriteLine("0{0}:{1}", currentTime.Hour, currentTime.Minute);
}
}
else
{
if (currentTime.Minute < 10)
{
Console.WriteLine("{0}:0{1}", currentTime.Hour, currentTime.Minute);
}
}
}
else
{
Console.WriteLine("{0}:{1}", currentTime.Hour, currentTime.Minute);
}
#endregion
FileStream fs = new FileStream("\\\\te-admin\\public\\TaskbarNotices.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs);
string noticeText = sr.ReadToEnd();
sr.Close();
fs.Close();
if (noticeText != "" && noticeText != prevNotification)
{
prevNotification = noticeText;
bgNotify.ReportProgress(1);
}
else
{
bgNotify.ReportProgress(2);
}
Console.WriteLine("Inner Text: {0} TOF: {1}", noticeText, noticeText != "");
Thread.Sleep(10000);
}
}
private void SendNotice(object Sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 1)
{
Console.WriteLine("notification sent");
this.notifyIcon.BalloonTipText = prevNotification;
this.notifyIcon.ShowBalloonTip(1500);
}
}
private void LoadProcess(object Sender, EventArgs e)
{
if (Sender is MenuItem)
{
MenuItem tempMenu = Sender as MenuItem;
string ProgramTag = "http://";
switch (tempMenu.Index)
{
case 0: //home page
ProgramTag += "teg";
break;
case 1: //docviewer
ProgramTag += "teg/docViewer";
break;
case 2: //policies
ProgramTag += "teg/Policies";
break;
case 3: //feedback
ProgramTag += "teg/Feedback";
break;
case 4: //inventory search
ProgramTag = "http://searchglobalshop/inventory/index.aspx";
break;
case 6: //submit ticket
ProgramTag = "https://timberlandgroup.on.spiceworks.com/portal/tickets";
break;
case 7: //send email
string sendto = "admin#tewinch.com";
string emailSubject = "Assistance Request";
string emailBody = "";
string mailto = string.Format("mailto:{0}?Subject={1}&Body={2}", sendto, emailSubject, emailBody);
ProgramTag = Uri.EscapeUriString(mailto);
break;
}
/*
Try to launch the choice the user made with the default processing method.
Should the default method fail we try to control how the process is run.
We open internet explorer and then we show them what to do otherwise.
*/
#region LaunchSelectedProcess
try
{
if (ProgramTag != "" && ProgramTag != "http://")
Process.Start(ProgramTag);
}
catch (System.ComponentModel.Win32Exception)
{
try
{
if (ProgramTag.StartsWith("http://") || ProgramTag.StartsWith("https://"))
Process.Start("iexplore.exe", ProgramTag);
}
catch (System.ComponentModel.Win32Exception)
{
Process.Start("control.exe", "/name Microsoft.DefaultPrograms");
string message = "";
if (tempMenu.Index <= 6)
{
message = "You must have a default browser set\n\tClick [Set Default Program]\n";
if (Environment.OSVersion.ToString().Contains("NT 10.")) //windows 10
{
message += "\tUnder [Web Browser] Edge is currently set as default\n\tClick on Microsoft Edge\n\tSelect the browser you use";
}
else //windows 7 -- "NT 6.1")
{
message += "Select the browser you use\n\tClick [Set this program as default]";
}
}
else
{
if (Environment.OSVersion.ToString().Contains("NT 10.")) //windows 10
{
message += "Please setup a default email application";
}
}
message += "\n\nIf this issue persists please contact your Administrator.\nPhone: 519-537-6262\nEmail: admin#tewinch.com";
MessageBox.Show(message, "Application Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
//if ( == DialogResult.OK)
}
}
#endregion
}
}
private void Icon_DoubleClick(object Sender, EventArgs e)
{
Process.Start("http://teg");
}
#endregion
#region BuiltFunctions
private void Primary_FormClosing(object sender, FormClosingEventArgs e)
{
notifyIcon.Icon = null;
notifyIcon.Dispose();
isRunning = false;
Dispose(true);
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// Primary
//
this.Icon = tegroupIcon;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.CausesValidation = false;
this.ClientSize = new System.Drawing.Size(120, 23);
this.ControlBox = false;
this.Enabled = false;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Primary";
this.Opacity = 0D;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
this.ResumeLayout(false);
}
protected override void Dispose(bool disposing)
{
// Clean up any components being used.
if (disposing)
if (components != null)
components.Dispose();
base.Dispose(disposing);
}
#endregion
}
}
Instead of cancelling the program on start up, I kill the other running instances of the program. The idea is that if any issues arise with the program I just launch another instance and resolve the issues. Right now not much can go wrong but we will be developing this program to complete many more tasks in the future.
The only area I can see which would keep a file open is when I pull an Embedded Resource tegroup.ico I was looking to see if I missed something while opening this, but I couldn't see a way to close the ManifestResourceStream after reading it in.
Any tips/suggestions would be wonderful but again, I really just want to know if there's a way I can close these Open Files
Example below
Open File after app launch
I might be trying to solve something which is a known result of using Application.Run() if this is the case then please suggest alternatives I can use. My other ideas would be loading the program into memory and launching it locally, using the .exe on the server as a starting point for this method though.
I believe that Windows doesn't load an entire executable into ram. It isn't just about files from the resource section of a PE file. Portions of the exe are only loaded when referenced and even after loading everything there is to load, Windows will maintain an open file handle until the process closes. Trying to close that handle yourself is a bad idea.
c/c++ allow a "SWAPFILE" flag to be specified that tells windows to put the whole thing into the page file but I don't know how you would do that with c# and I don't know if that would even stop windows from keeping the handle open anyways (I doubt it).
If this is truly important, iffin' I were your exe... I would:
Check a mutex for an existing running instance, exit if exist
Check where I was running from.
If running from temp, set a mutex that I am running and just run.
If not running from temp, copy myself to %temp%, start that copy, and exit.
Good luck.

How to Efficiently Read From a Pipe Stream when using IPC C#

I wrote the simplified version of my program below. Process A launches a child process (Process B). I use an anonymous pipe to write information about the progress of a method running on process B. Meanwhile I have a function in process A that continually reads from a stream to see if there is a new update coming in from the pipe. If there is, the form on process A is updated to reflect the progress. This works as expected, however I am wondering if there is a better way to accomplish this without having to continually check the stream to see if there are any new updates to the progress.
/////////////////
///Process A ////
/////////////////
public void LaunchProcessB()
{
using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.In,
HandleInheritability.Inheritable))
{
var _Process = new Process();
_Process.StartInfo.FileName = exeString;
_Process.StartInfo.Arguments = pipeServer.GetClientHandleAsString()
_Process.StartInfo.RedirectStandardOutput = true;
_Process.StartInfo.RedirectStandardInput = true;
_Process.StartInfo.CreateNoWindow = true;
_Process.StartInfo.UseShellExecute = false;
_Process.Start(); //launches process B
pipeServer.DisposeLocalCopyOfClientHandle();
using (StreamReader sr = new StreamReader(pipeServer))
{
try
{
while (true)
{
string temp = sr.ReadLine();
if (temp == null) break;
int result;
if (Int32.TryParse(temp, out result))
ShowDocumentProgress(result);
else ShowProgress(temp);
}
}
catch (Exception)
{
//error occured when reading from stream.
}
}
if (!_Process.Responding && !_Process.HasExited)
{
_Process.Kill();
return;
}
_Process.WaitForExit(10000);
}
}
private void ShowProgressPercent(int percentage)
{
if (percentage > currentPercentage)
{
progressBar.Value = percentage;
}
}
private void ShowProgress(string progressString)
{
labelMessage.Text = progressString;
}
/////////////////
///Process B ////
/////////////////
private StreamWriter _progressWriter;
private PipeStream _progressPipe;
static int Main(string[] args)
{
using (progressPipe = new AnonymousPipeClientStream(PipeDirection.Out, args[0]))
using (_progressWriter = new StreamWriter(_progressPipe))
{
RunLongProcess()
}
}
private void RunLongProcess()
{
//attaches events to PercentProgress and StageProgress methods.
}
private void PercentProgress(int percentage)
{
_progressWriter.WriteLine(percentage.ToString());
_progressPipe.WaitForPipeDrain();
}
private void StageProgress(string stage)
{
_progressWriter.WriteLine(stage);
_progressPipe.WaitForPipeDrain();
}
The while condition is not necessary. Simply read until temp is null. That's the end signal of the stream.
Make this a while(true) loop.
I think you also need to add exception handling to catch the process terminating and severing the pipe. !_Process.HasExited && pipeServer.IsConnected is not enough because it might be true but immediately switch to false after the test.
I also would add a WaitForExit at the end to make sure the system is quiesced before you continue.

restart program if winform is not responding

Think We have this part in our program:
private void button1_Click(object sender, EventArgs e)
{
while (true) ;
}
If we run the program it will crash and say "Not Responding". How to prevent this. I want the program check itself and if it dose not respond, restart itself.
Note:
We can use BackgroundWorker class. like this:
private readonly BackgroundWorker worker;
public Form1()
{
InitializeComponent();
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += Form1_Load;
worker.ProgressChanged += button1_Click;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
}
But there is no method or property or event in that class to understand not responding.
Any help will be appreciate.
Edit 3:
I used BackgroundWorker with ThredTimer and checked if process is "Not Responding". This dose not close the program but start a new one.
Certainly this is not a clean code, but it is a way. I'm still looking for how to use BeginInvoke as #micky said Or other way to make this beautiful. Thanks to all of you
private readonly BackgroundWorker _Worker;
public Form1()
{
InitializeComponent();
_Worker = new BackgroundWorker();
_Worker.DoWork += new DoWorkEventHandler(_Worker_DoWork);
_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_Worker_RunWorkerCompleted);
_Worker.WorkerReportsProgress = true;
_Worker.WorkerSupportsCancellation = true;
}
// BCW starts here.
private void button1_Click(object sender, EventArgs e)
{
_Worker.RunWorkerAsync();
while (true) ;
}
// ThreadTimer will run here.
void _Worker_DoWork(object sender, DoWorkEventArgs e)
{
if (_Worker.IsBusy == true)
{
if (_Worker.CancellationPending)
{
e.Cancel = true;
}
TimerCallback tmrCallBack = new TimerCallback(CheckStatusThreadHealth);
System.Threading.Timer tmr = new System.Threading.Timer(tmrCallBack, null, 10000, 10000);
}
}
// This will call by ThreadTimer and check processes for not responding
public void CheckStatusThreadHealth(object IsBusy)
{
Process application = null;
foreach (var process in Process.GetProcesses())
{
if (process.ProcessName == "WindowsFormsApplication1")
{
application = process;
break;
}
}
if (!application.Responding)
{
// This should end BCW and go to _Worker_RunWorkerCompleted. But it didn't
_Worker.CancelAsync();
// This Restart program but did not close the last one.
Application.Restart();
}
}
// this should run when BCW has error or cancel, But never this happen
void _Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Application.Restart();
return;
}
}
The Answer: Thanks to Jason Williams
I used a watch dog program as a solution and Communicate between two program by this link The code Changed to this:
In Main Program
public partial class Form1 : Form
{
// Use SendMessage API
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam);
// define a message
private const int RF_TESTMESSAGE = 0xA123;
// The timer will begin with the form
public Form1()
{
InitializeComponent();
var timer = new Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 10000; //10 seconds
timer.Start();
}
//Timer look for a Watch Dog Program and send message to it
void timer_Tick(object sender, EventArgs e)
{
try
{
Process WatchDogProccess = Process.GetProcessesByName("Watch Dog")[0];
SendMessage(WatchDogProccess.MainWindowHandle, RF_TESTMESSAGE, IntPtr.Zero, IntPtr.Zero);
}
catch
{
//if Watch Dog is not running, will reach here
}
}
// if we click this button we will got "Not Responding"
private void button1_Click(object sender, EventArgs e)
{
while (true) ;
}
}
In Watch Dog Program
public partial class Form2 : Form
{
//the message that have been define in main program
private const int RF_TESTMESSAGE = 0xA123;
//Recive the message
protected override void WndProc(ref Message message)
{
if (message.Msg == RF_TESTMESSAGE)
{
// this mean the mian program run perfectly
}
else
{
//the main program is not responding
//Main program's name and address
string FileAddress = #"C:\Users\...\MainProgram.exe";
string FileName = "MainProgram";
// This will restart the main program
RestartProgram(FileAddress, FileName);
}
base.WndProc(ref message);
}
// This will restart the main program
public void RestartProgram(string FileAddress, string FileName)
{
//Find the Process
Process[] prs = Process.GetProcessesByName(FileName);
foreach (Process pr in prs)
{
if (!pr.Responding)
{
try
{
pr.Kill();
//then to restart-
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = FileAddress
}
};
process.Start();
}
catch { }
}
}
}
public Form2()
{
InitializeComponent();
}
}
}
You could solve this with a background thread that somehow detects that the ui thread is not responding. But how would this thread reset/restart your ui thread? This could be very difficult to do cleanly, as you would somehow have to reset all the state throughout your app to a known good condition.
So the conventional approach is instead to have a separate "watch dog" process. This can detect that your app is dead, kill its process and then run a new instance.
So how to detect that it is dead? There are many clever ways you can do this, but the simplest and most reliable is to just send a message from your app to the watch dog periodically (e.g. once per second) using a Windows forms timer - if your ui thread is busy it will not process the timer event and so the message won't be sent, and after a few seconds your watch dog will be confident that it is unresponsive, and be able to restart it.

ASP.NET/C# display output in runtime

I'm trying to start a process ("cmd.exe") and then launching another programs (from cmd.exe) and being able to get the output or send inputs in a textbox.
So i created a new Thread to not freeze the UI and then read the standard output and display it in the textbox.
But it seems that as soon as the process start, the link between my UI and the process is broken.
Here is my code :
public partial class exec2 : System.Web.UI.Page
{
public delegate void Worker();
private static Thread worker;
protected void Page_Load(object sender, EventArgs e)
{
}
public void setTextBox(string s)
{
TextBox1.Text = TextBox1.Text + s;
}
protected void RunEXE()
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardError = true;
psi.CreateNoWindow = true;
proc.StartInfo = psi;
setTextBox("Setting the process\n");
// Start the process
proc.Start();
setTextBox("Process started\n");
// Attach the output for reading
System.IO.StreamReader sOut = proc.StandardOutput;
// Attach the in for writing
System.IO.StreamWriter sIn = proc.StandardInput;
// Exit CMD.EXE
sIn.WriteLine("EXIT");
// Close the process
proc.Close();
setTextBox("Process closed");
string results = "";
while (!sOut.EndOfStream)
{
results = results + sOut.ReadLine().Trim() + "\n";
setTextBox(results.Replace(System.Environment.NewLine, "\n"));
}
// Close the io Streams;
sIn.Close();
sOut.Close();
}
protected void Button1_Click(object sender, EventArgs e)
{
Init(Work);
}
protected void Button2_Click(object sender, EventArgs e)
{
setTextBox("TEST\n");
}
public static void Init(Worker work)
{
worker = new Thread(new ThreadStart(work));
worker.Start();
}
public void Work()
{
RunEXE();
}
}
But only "setting the process" is displayed.
I think there is something I don't understand in the UI / process managment.
You are starting a worker thread and a process on the server; the UI render pipe doesn't sit there and wait for them - why would it? (your code just does new Thread(...).Start()). Frankly, you're lucky that you even see "Setting the process" - I would not expect that to keep working in the general case. An http response is disconnected; you won't see updates as other things happen. If you want to update a UI that has been sent to the client, you will need something like polling (ajax) or web-sockets.

Categories