I have ASP.NET core MVC application deployed in azure app service on linux. And when I try to run /bin/bash and execute some scripts like: dotnet run test.dll or javac Test.java and when I try to get some info about the exited process like MemotyUsed and TimeUsed I get the following error: "Unable to retrieve the specified information about the process or thread. It may have exited or may be privileged"
When I run the app on windows everything is ok. I also try to run the app in docker on linux os because I think the problem comes from azure app service. However the same error was thrown again in docker container. So I think that problem comes from linux os.
ProcessExecutionResult processExecutionResult = new ProcessExecutionResult();
using (Process process = new Process())
{
process.StartInfo.FileName = "/bin/bash";
process.StartInfo.Arguments = arguments;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.Start();
if (!string.IsNullOrEmpty(input))
{
await process.StandardInput.WriteLineAsync(input);
await process.StandardInput.FlushAsync();
process.StandardInput.Close();
}
bool exited = process.WaitForExit(ProcessMaxRunningTime);
if (!exited)
{
process.Kill();
processExecutionResult.Type = ProcessExecutionResultType.TimeLimit;
}
string output = await process.StandardOutput.ReadToEndAsync();
string errors = await process.StandardError.ReadToEndAsync();
processExecutionResult.ErrorOutput = errors;
processExecutionResult.ReceivedOutput = output;
processExecutionResult.ExitCode = process.ExitCode;
processExecutionResult.TimeWorked = process.ExitTime - process.StartTime;
processExecutionResult.PrivilegedProcessorTime = process.PrivilegedProcessorTime;
processExecutionResult.UserProcessorTime = process.UserProcessorTime;
}
When I try to access process.ExitTime, process.StartTime or some other information about the process the error: Unable to retrieve the specified information about the process or thread. It may have exited or may be privileged is thrown.
In a Windows application I need to run another one application that's tetpdflib. That tetpdflib runs in command prompt only. When I drag and drop exe to the command prompt it will execute. Here is my code:
Process tetmlProcess = new Process();
tetmlProcess.StartInfo.CreateNoWindow = true;
tetmlProcess.StartInfo.UseShellExecute = false;
tetmlProcess.StartInfo.RedirectStandardError = true;
tetmlProcess.StartInfo.RedirectStandardInput = true;
tetmlProcess.StartInfo.WorkingDirectory = #"C:\Users\sw_chn\Documents\PDFlib\TET 5.0 32-bit\bin";
tetmlProcess.StartInfo.FileName = #"C:\Users\sw_chn\Documents\PDFlib\TET 5.0 32-bit\bin\tet.exe";
string args1 = #"tet -m wordplus D:\DailyWork\March\JOURNAL-ISSUE_6_3924-3930.pdf";
tetmlProcess.StartInfo.Arguments = args1;
tetmlProcess.Start();
StreamReader news = tetmlProcess.StandardError;
string err = news.ReadToEnd();
Console.WriteLine(err);
Console.ReadLine();
I had following error:
could not open PDF file 'tet' for reading
How to recover from this?
Your Start Arguments contains the Program Name again which leads to this error.
Simply change your code
Process tetmlProcess = new Process();
// ...
tetmlProcess.StartInfo.WorkingDirectory = #"C:\Users\sw_chn\Documents\PDFlib\TET 5.0 32-bit\bin";
tetmlProcess.StartInfo.FileName = #"C:\Users\sw_chn\Documents\PDFlib\TET 5.0 32-bit\bin\tet.exe";
// removing "tet" in Arguments
string args1 = #"-m wordplus D:\DailyWork\March\JOURNAL-ISSUE_6_3924-3930.pdf";
tetmlProcess.StartInfo.Arguments = args1;
tetmlProcess.Start();
// ...
Conclusion
The manual contains example like this
tet --format utf16 --outfile file.utf16 file.pdf
Here is tet mapped as environment variable in the system and stands for the full path of the application.
I try to start ilasm from C# using class ProcessInfo
string arguments = string.Format("\"{0}\" /exe /output:\"{1}\" /debug=IMPL", ilFullFileName, exeFileFullName);
ProcessStartInfo processStartInfo = new ProcessStartInfo(CILCompiler, arguments);
processStartInfo.UseShellExecute = false;
processStartInfo.CreateNoWindow = false;
processStartInfo.WorkingDirectory = #"c:\Windows\Microsoft.NET\Framework\v4.0.30319\";
using (Process process = Process.Start(processStartInfo))
{
process.WaitForExit();
}
the arguments are:
"path_to_il.il" /exe /output:"path_to_exe.exe" /debug=IMPL
and then it gives me the error:
The application was unable to start correctly (0xc0000007b). Click Ok to close the application.
The odd part of that is, when I do exactly the same actions manually using bat file
"c:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe" "path_to_il.il" /exe /output:"path_to_exe.exe" /debug=IMPL
pause
it does work.
What did I miss?
I think you need to set the file name as well:
processStartInfo.FileName = "ilasm.exe";
i have 1 c# console appln,it executes any script file by using Process.Start() method. i provide script file path to Process1.StartInfo.FileName.My script file can be of any type (.vbs ,ps1 etc) . I m also passing String to script by using instruction p.StartInfo.Arguments. When script file executed it should retrun string back to c# application. This returned string can be read by setting Process1.StartInfo.RedirectStandardOutput = true,But for using this instruction i need to set Process1.StartInfo.UseShellExecute = false.
When i run this i m getting error as "The specified executable is not a valid Win32 application".
i think this may be because of, when i set Process1.StartInfo.UseShellExecute = false, my appln dont know which .exe to be used to execute script file.
on the other hand if i provide exe path to StartInfo.FileName and script file path to StartInfo.Argument then i m not getting error.
For Example:i want to execute powershell script and i set following properties as P1.StartInfo.FileName = "location of powershell.exe" and p1.startInfo.Argument =".ps1 script file path", in this case i m not getting error.
problem is i dont know in advance,which type of script i m going to execute.also cant find out locations of .exe file for executing script file on different diffrent m/c. So is it possible to execute diffrent type of script files from same common c# appln and also read output returned by scripts?
here is my code
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Collections;
namespace process_csharp
{
class Program
{
static void Main(string[] args)
{
String path = null;
//this will read script file path
path = Console.ReadLine();
//this string is passed as argument to script
string s = "xyz";
Process p = new Process();
p.StartInfo.FileName= path;
p.StartInfo.Arguments = s;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
p.BeginOutputReadLine();
Console.WriteLine(p.StandardOutput.ReadToEnd());
}
}
}
You can check for the script type and read output from their own engine;
static void Main(string[] args)
{
string path = Console.ReadLine();
string parameter = Console.ReadLine();
string enginePath;
switch (Path.GetExtension(path).ToLowerInvariant())
{
case ".ps1":
enginePath = "powershell.exe";
break;
case ".vbs":
enginePath = "cscript.exe";
break;
default:
throw new ApplicationException("Unknown script type");
}
string scriptPath = path;
Process process = new Process();
process.StartInfo.FileName = enginePath;
process.StartInfo.Arguments = string.Format("{0} {1}", scriptPath, parameter);
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
Console.WriteLine(process.StandardOutput.ReadToEnd());
Console.ReadKey();
}
Try this code instead:
string path = #"C:\mypsscript.bat";
Process p = new Process();
p.StartInfo.FileName = path;
p.StartInfo.Arguments = "xyz";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
Console.WriteLine(p.StandardOutput.ReadToEnd());
Console.ReadKey();
For the sakes of debugging I have created a batch file with the code:
echo %1
When I run the above code I get:
xyz
So that seems to work fine. Try using a batch file like this and see if it works, if it does it may be an association with powershell scripts that isn't working, which we can fix later.
I'm trying to run a batch file, as another user, from my web app. For some reason, the batch file hangs! I can see "cmd.exe" running in the task manager, but it just sits there forever, unable to be killed, and the batch file is not running. Here's my code:
SecureString password = new SecureString();
foreach (char c in "mypassword".ToCharArray())
password.AppendChar(c);
ProcessStartInfo psi = new ProcessStartInfo();
psi.WorkingDirectory = #"c:\build";
psi.FileName = Environment.SystemDirectory + #"\cmd.exe";
psi.Arguments = "/q /c build.cmd";
psi.UseShellExecute = false;
psi.UserName = "builder";
psi.Password = password;
Process.Start(psi);
If you didn't guess, this batch file builds my application (a different application than the one that is executing this command).
The Process.Start(psi); line returns immediately, as it should, but the batch file just seems to hang, without executing. Any ideas?
EDIT: See my answer below for the contents of the batch file.
The output.txt never gets created.
I added these lines:
psi.RedirectStandardOutput = true;
Process p = Process.Start(psi);
String outp = p.StandardOutput.ReadLine();
and stepped through them in debug mode. The code hangs on the ReadLine(). I'm stumped!
I believe I've found the answer. It seems that Microsoft, in all their infinite wisdom, has blocked batch files from being executed by IIS in Windows Server 2003. Brenden Tompkins has a work-around here:
http://codebetter.com/blogs/brendan.tompkins/archive/2004/05/13/13484.aspx
That won't work for me, because my batch file uses IF and GOTO, but it would definitely work for simple batch files.
Why not just do all the work in C# instead of using batch files?
I was bored so i wrote this real quick, it's just an outline of how I would do it since I don't know what the command line switches do or the file paths.
using System;
using System.IO;
using System.Text;
using System.Security;
using System.Diagnostics;
namespace asdf
{
class StackoverflowQuestion
{
private const string MSBUILD = #"path\to\msbuild.exe";
private const string BMAIL = #"path\to\bmail.exe";
private const string WORKING_DIR = #"path\to\working_directory";
private string stdout;
private Process p;
public void DoWork()
{
// build project
StartProcess(MSBUILD, "myproject.csproj /t:Build", true);
}
public void StartProcess(string file, string args, bool redirectStdout)
{
SecureString password = new SecureString();
foreach (char c in "mypassword".ToCharArray())
password.AppendChar(c);
ProcessStartInfo psi = new ProcessStartInfo();
p = new Process();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.WorkingDirectory = WORKING_DIR;
psi.FileName = file;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = redirectStdout;
psi.UserName = "builder";
psi.Password = password;
p.StartInfo = psi;
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(p_Exited);
p.Start();
if (redirectStdout)
{
stdout = p.StandardOutput.ReadToEnd();
}
}
void p_Exited(object sender, EventArgs e)
{
if (p.ExitCode != 0)
{
// failed
StringBuilder args = new StringBuilder();
args.Append("-s k2smtpout.secureserver.net ");
args.Append("-f build#example.com ");
args.Append("-t josh#example.com ");
args.Append("-a \"Build failed.\" ");
args.AppendFormat("-m {0} -h", stdout);
// send email
StartProcess(BMAIL, args.ToString(), false);
}
}
}
}
Without seeing the build.cmd it's hard to tell what is going on, however, you should build the path using Path.Combine(arg1, arg2); It's the correct way to build a path.
Path.Combine( Environment.SystemDirectory, "cmd.exe" );
I don't remember now but don't you have to set UseShellExecute = true ?
Another possibility to "debug" it is to use standardoutput and then read from it:
psi.RedirectStandardOutput = True;
Process proc = Process.Start(psi);
String whatever = proc.StandardOutput.ReadLine();
In order to "see" what's going on, I'd suggest you transform the process into something more interactive (turn off Echo off) and put some "prints" to see if anything is actually happening. What is in the output.txt file after you run this?
Does the bmail actually executes?
Put some prints after/before to see what's going on.
Also add "#" to the arguments, just in case:
psi.Arguments = #"/q /c build.cmd";
It has to be something very simple :)
My guess would be that the build.cmd is waiting for some sort of user-interaction/reply. If you log the output of the command with the "> logfile.txt" operator at the end, it might help you find the problem.
Here's the contents of build.cmd:
#echo off
set path=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;%path%
msbuild myproject.csproj /t:Build > output.txt
IF NOT ERRORLEVEL 1 goto :end
:error
bmail -s k2smtpout.secureserver.net -f build#example.com -t josh#example.com -a "Build failed." -m output.txt -h
:end
del output.txt
As you can see, I'm careful not to output anything. It all goes to a file that gets emailed to me if the build happens to fail. I've actually been running this file as a scheduled task nightly for quite a while now. I'm trying to build a web app that allows me to run it on demand.
Thanks for everyone's help so far! The Path.Combine tip was particularly useful.
I think cmd.exe hangs if the parameters are incorrect.
If the batch executes correctly then I would just shell execute it like this instead.
ProcessStartInfo psi = new ProcessStartInfo();
Process p = new Process();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.WorkingDirectory = #"c:\build";
psi.FileName = #"C:\build\build.cmd";
psi.UseShellExecute = true;
psi.UserName = "builder";
psi.Password = password;
p.StartInfo = psi;
p.Start();
Also it could be that cmd.exe just can't find build.cmd so why not give the full path to the file?
What are the endlines of you batch? If the code hangs on ReadLine, then the problem might be that it's unable to read the batch fileā¦