Foo.cmd won't output lines in process (on website)
I found the answer myself and will post a solution for anyone interested.
The source of the issue is fairly hard to debug, because the problem originated in how IIS handles users and processes.
As I thought, there was nothing wrong with the code itself.
Answer
In IIS, a website is running in a AppPool. An AppPool is assigned an user identity. The default identity is a virtual built-in account named ApplicationPoolIdentity. This user does not have the privilege to call any (as far as I know) external batch/command scripts.
Providing a username, password and domain for a administrative user when starting a new process, didn't solve anything for me - It might be that I'm just misunderstanding the whole concept.
Using <identity impersonate="true" userName="domain\user" password="pass" />
in the webconfig didn't solve anything either. This is apparently because the assigned AppPool user is still the author of all processes.
What really bugged me out, was that I could execute .exe files, but not .cmd or .bat files.
The solution for me, was to create a new user with privileges to execute batch scripts and select that user as the AppPool user in IIS.
Edit: As I have mentioned in the comments, the user I'm working with is created on an Active Directory server as this particular file server is on a network share. The user is part of the local server group IIS_IUSRS on my webserver and has read/write/execute privileges in the folder where the executable programs are stored.
Edit2: The solution works for local user accounts as well as long as the user is part of the local server group IIS_IUSRS and has read/write/execute privileges in the folder where the executable programs are stored.
Why does execution of arduino-cli via cmd with file names with spaces in path not work?
The issue was that the path was too long, and it needed a "" around the path. This is what the code looks like now -
ProcessStartInfo cmd = new ProcessStartInfo();
cmd.FileName = "cmd.exe";
cmd.WindowStyle = ProcessWindowStyle.Normal;
string name = GenerateName(8);
hexFile = Path.GetDirectoryName(Path.GetDirectoryName(System.IO.Directory.GetCurrentDirectory())) + "\\cache/" + name;
cmd.Arguments = "/k cd " + Path.GetDirectoryName(Path.GetDirectoryName(System.IO.Directory.GetCurrentDirectory())) + "\\avr-g++\\arduino-cli\\bin"
+ " & arduino-cli compile -b arduino:avr:uno " + "\"" + @inFile + "\"" + " --build-path " + "\"" + @hexFile + "\"";
file = Path.GetDirectoryName(Path.GetDirectoryName(System.IO.Directory.GetCurrentDirectory())) + "\\cache\\" + name + "\\" + Path.GetFileName(inFile) + ".hex";
Process.Start(cmd);
Thread.Sleep(3000);
``
How to prevent Rust's std::process:Command from inserting .exe's relative path into arguments?
I do not have a Windows machine nearby but I'm quite sure that the problem is in the quote characters "
.
Escape rules in CMD.exe are quite weird: sometimes you need quotes, sometimes you do not, and sometime you must not use them.
In your case, the log file, for example is chosen with the following option (removing Rust escapes): /LOG:"C:\Test\Test3\logfile.log"
. This is a file name that starts and ends with a quote. And since it does not start with a drive letter or a \
, the OS thinks: surely it is a relative path, let's look for C:\...\"C:\Test..."
!
The solution is easy: just remove all those quote.
What I don't understand is why are you calling cmd.exe /c
instead of just calling robocopy
directly. Quotes in the command line are used to guide the command line parser and properly manage filenames with spaces and so on. But if you do Command::new()
of robocopy
directly, then there is no need for quoting because the arguments are already passed separatedly.
C# execute, wait, read command's output
The following snippet will work
public static string GetSystemInfo()
{
var command = "/c systeminfo";
var cmdsi = new ProcessStartInfo("cmd.exe");
cmdsi.Arguments = command;
cmdsi.RedirectStandardOutput = true;
cmdsi.UseShellExecute = false;
var cmd = Process.Start(cmdsi);
var output = cmd.StandardOutput.ReadToEnd();
cmd.WaitForExit();
return output;
}
You should set RedirectStandardOutput
to true
and read output before calling WaitForExit
, otherwise you can get a deadlock, per MSDN
The example avoids a deadlock condition by calling
p.StandardOutput.ReadToEnd
beforep.WaitForExit
. A deadlock condition
can result if the parent process callsp.WaitForExit
before
p.StandardOutput.ReadToEnd
and the child process writes enough text to
fill the redirected stream. The parent process would wait indefinitely
for the child process to exit.
/c
means terminating command line after execution
Related Topics
How to Handle Forms Authentication Timeout Exceptions in ASP.NET
When Is Using the C# Ref Keyword Ever a Good Idea
How to Calculate Divide and Modulo for Integers in C#
Deserializing JSON Array into Strongly Typed .Net Object
Local Database, I Need Some Examples
Opening a "Known File Type" into Running Instance of Custom App - .Net
How to Sort Databound Datagridview Column
Wpf Textblock Memory Leak When Using Font
How to Cast a Generic Enum to Int
Topmost Form, Clicking "Through" Possible
How to Print a Text File on Thermal Printer Using Printdocument
Wpf Controls Needed to Build Chess Application
Is There an Entity Framework 7 Database-First Poco Generator
Setting the Initial Directory of an Savefiledialog
Is the Sorting Algorithm Used by .Net's 'Array.Sort()' Method a Stable Algorithm