I have a web application where I want to send commands to a command line (commands are not known). This is the method I use
public static string ExecuteCommand(string command)
{
String result;
try
{
//Create a new ProcessStartInfo
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
//Settings
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
//Create new Process
System.Diagnostics.Process proc = new System.Diagnostics.Process();
//Set ProcessStartInfo
proc.StartInfo = procStartInfo;
//Start Process
proc.Start();
//Wait to exit
proc.WaitForExit();
//Get Result
result = proc.StandardOutput.ReadToEnd();
//Return
return result;
}
catch
{
}
return null;
}
The command works on a console application but not on a web application (null is returned)
public string test = "NOTHING";
protected void Page_Load(object sender, EventArgs e)
{
test = AppCommandHandler.ExecuteCommand("mkdir test2");
}
What am I doing wrong? Every tutorial I look at tells me to use ProcessStartInfo
Edit I keep getting this error:
{"StandardOut has not been redirected or the process hasn't started
yet."}
Does the web app's pool have enough permissions to execute this command?
You cannot do that like this but you've to do this with using java directly, just see the link:
Run a cmd command with asp dotnet app
Related
I have following Python script :
import time
for x in range(10):
print(x)
time.sleep(0.05)
I want to run this script and capture its output while it is running.
I used the following C# code but it does not print any number until it completely finishes loop.
private void DoScriptTest()
{
ProcessStartInfo start = new ProcessStartInfo();
string cmd = #"c:\flowers\count.py";
start.FileName = #"C:\Users\pubud\AppData\Local\Programs\Python\Python36\python.exe";
start.Arguments = string.Format("{0}", cmd);
start.UseShellExecute = false;// Do not use OS shell
start.CreateNoWindow = true; // We don't need new window
start.RedirectStandardOutput = true;// Any output, generated by application will be redirected back
start.RedirectStandardError = true; // Any error in standard output will be redirected back (for example exceptions)
Process process = new Process();
process.StartInfo = start;
process.EnableRaisingEvents = true;
process.OutputDataReceived += ProcessOutputHandler;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
}
private void ProcessOutputHandler(object sender, DataReceivedEventArgs e)
{
if (!String.IsNullOrEmpty(e.Data))
try {
TxtPrompt.Invoke((MethodInvoker)delegate {
TxtPrompt.AppendText(e.Data);
TxtPrompt.Refresh();
});
}
catch
{ }
}
I am not sure why ProcessOutputHandler is NOT called in while the script is running. How could I get that output ? (the numbers coming from Python script in real time)
I am trying to implement piping behavior in C#.NET using Process and ProcessStartInfo classes. My intention is to feed the output of previous command to next command so that that command will process the input and return result. have a look into following code -
private static string Out(string cmd, string args, string inputFromPrevious)
{
string RetVal = string.Empty;
try
{
ProcessStartInfo psi = String.IsNullOrEmpty(args) ? new ProcessStartInfo(cmd) : new ProcessStartInfo(cmd, args);
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
psi.RedirectStandardInput = string.IsNullOrEmpty(inputFromPrevious) ? false : true;
Process proc = new System.Diagnostics.Process();
proc.StartInfo = psi;
if (proc.Start())
{
if (!string.IsNullOrEmpty(inputFromPrevious))
{
proc.StandardInput.AutoFlush = true;
proc.StandardInput.WriteLine(inputFromPrevious); proc.StandardInput.WriteLine();
proc.StandardInput.Close();
}
using (var output = proc.StandardOutput)
{
Console.WriteLine("3. WAITING WAITING....."); < ---Code halts here.
RetVal = output.ReadToEnd();
}
}
proc.WaitForExit();
proc.Close();
}
catch (Exception Ex)
{
}
return RetVal; < ---This is "inputFromPrevious" to next call to same function
}
I am calling above code in loop for different commands and arguments. Is there any mistake in my code? I had looked similar as shown below but nothing worked for me as of now. Any help will be appreciated.
Piping in a file on the command-line using System.Diagnostics.Process
Why is Process.StandardInput.WriteLine not supplying input to my process?
Repeatably Feeding Input to a Process' Standard Input
I have a button that allows the user to browse a file and then stores the path + filename in a variable:
openFileDialog1.ShowDialog();
string filePath = openFileDialog1.FileName;
After browsing for the .exe, I want to install the service.
Currently we run a bat as admin using installutil. It can be done also with sc create, from an administrator command prompt.
What is the easiest way to install a service from the windows form?
Can I create a string like:
sc create "servicename" binpath="filepath"
and run it from the program?
The other option I was thinking about was to make the program create a bat and run it as admin?
You can use the following code to install a service:
Note: you will need to add a reference to System.ServiceProcess
public static void InstallService(string serviceName, Assembly assembly)
{
if (IsServiceInstalled(serviceName))
{
return;
}
using (AssemblyInstaller installer = GetInstaller(assembly))
{
IDictionary state = new Hashtable();
try
{
installer.Install(state);
installer.Commit(state);
}
catch
{
try
{
installer.Rollback(state);
}
catch { }
throw;
}
}
}
public static bool IsServiceInstalled(string serviceName)
{
using (ServiceController controller = new ServiceController(serviceName))
{
try
{
ServiceControllerStatus status = controller.Status;
}
catch
{
return false;
}
return true;
}
}
private static AssemblyInstaller GetInstaller(Assembly assembly)
{
AssemblyInstaller installer = new AssemblyInstaller(assembly, null);
installer.UseNewContext = true;
return installer;
}
You just need to call it like:
Assembly assembly = Assembly.LoadFrom(filePath);
InstallService("name", assembly);
You can use Process.Start:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = String.Format(#"sc create \"servicename\" \"{0}\"", filepath);
startInfo.Verb = "runas";
process.StartInfo = startInfo;
process.Start();
The line startInfo.Verb = "runas"; enables the process to start under administrator privileges.
I am having trouble with permissions on Windows 2008 server. i have a command line utility that I need to run to convert some standard files to CSV files. That are in turn used to import data to my SQL database. I am able to get the done to work fine on my 2003 server but my windows 2008 server is not allowing the code to run. Below is a watered down version of the code. Basically in this example I am just trying to run a simple command. But I keep getting the output access denied. How do I correct this?
public partial class _Bank : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btn_Click(object sender, EventArgs e)
{
ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe");
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardError = true;
Process process = Process.Start(processStartInfo);
if (process != null)
{
process.StandardInput.WriteLine("dir");
process.StandardInput.Close();
string outputString = process.StandardOutput.ReadToEnd();
Response.Write(outputString);
string error = process.StandardError.ReadToEnd();
Response.Write(error);
}
}
private string ProcessRunner()
{
ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe");
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.UseShellExecute = false;
Process process = Process.Start(processStartInfo);
if (process != null)
{
//process.StandardInput.WriteLine("This is a test line");
process.StandardInput.WriteLine("c:\\");
process.StandardInput.WriteLine("This is a test line");
process.StandardInput.Close(); // line added to stop process from hanging on ReadToEnd()
string outputString = process.StandardOutput.ReadToEnd();
Response.Write(outputString);
return outputString;
}
return string.Empty;
}
public static int ExecuteCommand(string Command, int Timeout)
{
int ExitCode;
ProcessStartInfo ProcessInfo;
Process Process;
ProcessInfo = new ProcessStartInfo("cmd.exe", "/C " + Command);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = false;
Process = Process.Start(ProcessInfo);
Process.WaitForExit(Timeout);
ExitCode = Process.ExitCode;
Process.Close();
return ExitCode;
}
}
This is running within an asp.net application with an App-Pool. The App-Pool has an identity (LocalSystem, Network Service etc) this process is executed.
Make sure that this user does have the necessary privileges on the folders you are planning to access.
IMHO: for security reasons starting another process within a web application is not best practice and should never be done on internet web applications.
EDIT:
Usualy the user is named ASPNET or IWAM_[Servername] (IWAM_... Built-in account for Internet Information Services to start out of process applications). Just give access to the folder to that user.
I am writing a InstallerClass using C# as a custom action for my installer, and I can successfully run an external exe (installation) using the InstallerClass, but when I try to use /quiet in the InstallerClass, it does not install the exe. But I can successfully install this in silent mode using /quiet in the command prompt.
Is there any reason for this or otherwise how to install in silent mode using C#?
Following is the code I use within the Commit method (overriden):
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = pathExternalInstaller;
p.StartInfo.Arguments = "/quiet";
p.Start();
Here is what I use to do a quiet Install and Uninstall:
public static bool RunInstallMSI(string sMSIPath)
{
try
{
Console.WriteLine("Starting to install application");
Process process = new Process();
process.StartInfo.FileName = "msiexec.exe";
process.StartInfo.Arguments = string.Format(" /qb /i \"{0}\" ALLUSERS=1", sMSIPath);
process.Start();
process.WaitForExit();
Console.WriteLine("Application installed successfully!");
return true; //Return True if process ended successfully
}
catch
{
Console.WriteLine("There was a problem installing the application!");
return false; //Return False if process ended unsuccessfully
}
}
public static bool RunUninstallMSI(string guid)
{
try
{
Console.WriteLine("Starting to uninstall application");
ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe", string.Format("/c start /MIN /wait msiexec.exe /x {0} /quiet", guid));
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process process = Process.Start(startInfo);
process.WaitForExit();
Console.WriteLine("Application uninstalled successfully!");
return true; //Return True if process ended successfully
}
catch
{
Console.WriteLine("There was a problem uninstalling the application!");
return false; //Return False if process ended unsuccessfully
}
}
This works for me.
Process process = new Process();
process.StartInfo.FileName = # "C:\PATH\Setup.exe";
process.StartInfo.Arguments = "/quiet";
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit();
Have you tried using the /Q or /QB parameter that is listed in the Installation parameters? It might look something like this:
p.StartInfo.Arguments = "/Q";
I got that out of this document: http://msdn.microsoft.com/en-us/library/ms144259(v=sql.100).aspx
Here is my logic to silent install an app for all users:
public void Install(string filePath)
{
try
{
Process process = new Process();
{
process.StartInfo.FileName = filePath;
process.StartInfo.Arguments = " /qb ALLUSERS=1";
process.EnableRaisingEvents = true;
process.Exited += process_Exited;
process.Start();
process.WaitForExit();
}
}
catch (InvalidOperationException iex)
{
Interaction.MsgBox(iex.Message, MsgBoxStyle.OkOnly, MethodBase.GetCurrentMethod().Name);
}
catch (Exception ex)
{
Interaction.MsgBox(ex.Message, MsgBoxStyle.OkOnly, MethodBase.GetCurrentMethod().Name);
}
}
private void process_Exited(object sender, EventArgs e)
{
var myProcess = (Process)sender;
if (myProcess.ExitCode == 0)
// do yours here...
}
string filePath = #"C:\Temp\Something.msi";
Process.Start(filePath, #"/quiet").WaitForExit();
It worked for me.