I have the following code for a button click event. This event should open the command window and execute the application:
private void start_Click(object sender, EventArgs e)
{
if (textBox1.Text == " " || textBox2.Text == " ")
{
MessageBox.Show("Header File or Executable Missing");
}
else
{
Process.Start(textBox1.Text);
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = textBox1.Text;
string filename = textBox1.Text;
int found = filename.LastIndexOf("\\");
int end = filename.Length;
string temp = filename.Substring(found);
startInfo.Arguments = temp + textBox2.Text;
Process.Start(startInfo);
}
}
The problem that I'm facing out here is that when I click the button, the command window does not persist and I don't know whether the command window displays an error message or not because it opens & closes in a flash. Can anybody tell me what is going wrong here and give me a few hints how to go about solving the issue?
If you want to start a new console application from your Windows Forms application you need to either pass in the path to such an application or to cmd.exe + the run command for that application. Make sure the code in your console application halts by asking for a Console.ReadKey(true) or similar.
Related
I am trying to make a log using a C# windows form application. The goal here is to press a button to start a batch file (below) and get the text/data written to the command prompt, as it is written if possible, then send it to a listbox on my application. Think of it as a program for a server (which its not, its a discord bot.), my goal is just to have the "logs" sent to the application in real time.
Question: How can I create my own console inside my windows form application, example would be: If an echo said "Hello" I want it to display "Hello" in my listbox in realtime.
CMD File being Ran
#echo off
cd "C:\Users\gunzb\Desktop\Tarkov Bot\"
:loop
py bot.py
SET /A time=3
:timer
timeout /t 1 /nobreak>nul
echo Restarting in %time%
SET /A time-=1
IF %time% EQU 0 (goto skiploop) ELSE (goto timer)
:skiploop
goto loop
I have no idea where to start as when I search for this topic I get other languages or other methods that dont seem to either do it in real time or doesnt work at all. Thank you for any help given.
EDIT: The python script makes the writelines but I believe these can also be taken from the CMD process itself, not sure though.
EDIT:
public void StartBotBtn_Click(object sender, EventArgs e)
{
Process proc = new Process();
ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo();
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.OutputDataReceived += ProcessOutputHandler;
proc.StartInfo.FileName = "C:\\Users\\gunzb\\Desktop\\Tarkov Bot\\start.bat";
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
processid = proc.Id;
}
private void StopBotBtn_Click(object sender, EventArgs e)
{
Array.ForEach(Process.GetProcessesByName("py"), x => x.Kill());
Array.ForEach(Process.GetProcessesByName("cmd"), x => x.Kill());
}
private void ProcessOutputHandler(object sender, DataReceivedEventArgs e)
{
this.listBox1.Items.Add(e.Data); //This is where I get confused.
}
Here is what I am attempting to make. It's a C# ASP page.
User picks a date
User hits "Import"
An Exe stored in /AppData/ runs
A status message of "Running" shows on the page <-- Issue here
When the exe closes, the status message says "Done"
Here is my code for the import button:
Process[] pDTExport = Process.GetProcessesByName("DTImport");
if (pDTExport.Length != 0)
{
prgStatus.Visible = false;
txtStatus.Text = "Unable to import data: another import process is already running. Please wait for it to finish before trying again.";
txtStatus.ForeColor = Color.Red;
}
else
{
txtStatus.Text = "The import process is running..."; <-- Issue here
LaunchExe();
}
And how I am launching the exe:
private void LaunchExe()
{
string exePath = Server.MapPath("~/App_Data/DTImport.exe");
if (File.Exists(exePath))
{
Process pImport = new Process();
pImport.StartInfo.FileName = exePath;
pImport.StartInfo.Arguments = "-d " + txtDate.Text;
pImport.Start();
pImport.WaitForExit();
txtStatus.Text = "Done!";
txtStatus.ForeColor = Color.Green;
prgStatus.Visible = false;
}
else
{
txtStatus.Text = "DTImport.exe was not found in /AppData/"
txtStatus.ForeColor = Color.Red;
prgStatus.Visible = false;
}
}
The issue I am having is updating the front end before I launch the exe. I want it to do this: Click button -> Show running message -> Launch exe.
Currently, when I click on the button, the exe runs, but I never see the "Import process is running" message, just the "Done!" line after it finishes.
I know it's because the line
pImport.WaitForExit();
is blocking the main thread. I tried storing/reading a ViewState variable in the Page_Load event, to try and launch the exe on the postback causes by the button, but it didn't work. Any ideas how on how I can update the UI before the exe runs?
You can register an event Handler to the pImport.Exit event. This allows you to avoid waitForExit. In the registered method you can manage the update to import done.
I am trying to open Active Directory using a button on my application. I don't want to get or set information from or in AD, just open it. The code below gives the error: Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll, which isn't very helpful. Any ideas?
private void btnAD_Click(object sender, EventArgs e)
{
try
{
Process procAD = new Process();
procAD.StartInfo.FileName = "C:\\Windows\\System32\\dsa.msc";
procAD.Start();
}
catch
{
Console.WriteLine("Didn't open...");
}
}
There's a few ways. I would suggest that you actually start the mmc.exe executable and give it the msc file as an argument. For example:
Process procAD = new Process();
procAD.StartInfo.FileName = "C:\\Windows\\System32\\mmc.exe";
procAD.StartInfo.Arguments = "C:\\Windows\\System32\\dsa.msc";
procAD.Start();
You should also be able to do this, which is the same a double-clicking the file:
System.Diagnostics.Process.Start("C:\\Windows\\System32\\dsa.msc");
I want to create an auto restarter for my server. I have added a checkbox and made all required checks but I don't have any idea how to make that process restart upon crash.
Here is my code:
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
string world = textBox1.Text;
string auth = textBox2.Text;
if (checkBox1.Checked == true)
{
if (textBox1.Text.Trim().Length == 0 || textBox2.Text.Trim().Length == 0)
{
MessageBox.Show("Please check if you selected the path for worldserver and authserver");
}
else
{
//here i need something to restart those 2 processes after crash/close
}
}
}
The simplest way to start a process is to use the Start static method of the Process class:
Process.Start("yourapp.exe");
For access to more specific options, you can set up a ProcessStartInfo object instead:
var startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "yourapp.exe";
startInfo.Arguments = "-arg1 val1";
var exeProcess = Process.Start(startInfo);
exeProcess.Start();
To check whether the process in question is still running, you can use this:
var matchingProcesses = Process.GetProcessesByName("yourapp");
var isRunning = matchingProcesses.Length > 0;
And you can put that in a method and poll every few seconds or milliseconds (depending on how fast you want to respond):
var aTimer = new Timer();
aTimer.Elapsed += new ElapsedEventHandler(YourMethod);
aTimer.Interval = 1000;
aTimer.Enabled = true;
These classes are found in the System.Diagnostics and System.Timers namespaces, respectively.
Though it's not C# (but better, it works with almost any program), you can do an auto restarter in batch (or in bash, but I won't put the code here), and it will be enough for most cases:
#echo off
:start
myprogram.exe %*
if exist myprogam.lock goto start
inside your program:
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if(checkBox1.Checked)
{
using (System.IO.File.Create("myprogam.lock"));
}
else
{
System.IO.File.Delete("myprogam.lock")
}
}
you should also create the file in your main or init code.
bonus: you can delete the file if your program exits cleanly (or on some errors), and it won't restart.
to use, just put the first code in a .bat file you put in your program folder, and use this to start the program.
When I start a new process, it automatically gets the focus. how can I prevent it from getting the focus or instead get back the focus to my application?
here is the code I'm using:
string path = #"c:\temp\myprocess.exe";
ProcessStartInfo info = new ProcessStartInfo(path);
info.WorkingDirectory = path;
Process p = Process.Start(info);
I just need the executed process not to get the focus.
Thank you very much,
Adi Barda
Maybe setting the WindowStyle property to Minimized can help.
If you don't need to show the process at all, try this:
string path = #"c:\temp\myprocess.exe";
ProcessStartInfo info = new ProcessStartInfo(path);
info.WorkingDirectory = path;
info.WindowStyle = ProcessWindowStyle.Hidden;
Or set WindowStyle to ProcessWindowStyle.Minimized if you want it visible but minimized, as Uwe Keim said.
can you do
myForm.Focus();
where myForm is the form on your main application
What i´ve done was to wait a little delay until the other application was succesfully loaded, then focus my application window.
//Test window
const string strCmdText = "/C cd C:\\sqlcipher";
Process.Start("CMD.exe", strCmdText);
//Delay
int liMilliseconds = 50;
Thread.Sleep(liMilliseconds);
//Code to bring window to front
this.WindowState = FormWindowState.Minimized;
this.Show();
this.WindowState = FormWindowState.Normal;