I have a C# project where I use the Process class to run R scripts:
public void RunRScriptFile(string file) {
StringBuilder eventLog = new StringBuilder();
StringBuilder errorLog = new StringBuilder();
var scriptRunProcess = new Process {
StartInfo = new ProcessStartInfo {
FileName = "Rscript",
Arguments = file,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = false
}
};
scriptRunProcess.Start();
while (!scriptRunProcess.StandardOutput.EndOfStream) {
eventLog.AppendLine(scriptRunProcess.StandardOutput.ReadLine());
}
while (!scriptRunProcess.StandardError.EndOfStream) {
errorLog.AppendLine(scriptRunProcess.StandardError.ReadLine());
}
Log.AddEvent(new List<String>() { "Info" }, eventLog.ToString());
if (errorLog.Length > 0) Log.AddEvent(new List<string>() { "Info", "Warning", "Critical" }, errorLog.ToString());
}
The R scripts I run use RODBC to connect to a database to get data. However whenever I run a query through my RODBC connection it prints the ODBC driver logging info (which has tracing set to 0) to the process StandardError. How can I either just make it log this to info or not log it at all? I want to be able to use Standard error to actually detect errors, but I can't with this happening as there is always an error stream.
RODBC is not doing the logging; this is caused by the ODBC connector (in this case, the Snowflake ODBC connector) trying to open a log file which is already opened by another script's ODBC connector, and instead logging to stderr without filtering.
You can see this by running two scripts at once that use the ODBC connector. Setting TRACE=1 as an environmental variable for the second will also give simba logs, which include a "cannot open file message" - using procmon will show that the file in question is the default log file.
Related
I am writing a code to execute some commands against wsl, parsing and reading the returned value is important.
Project is a .net core console app 3.1
wsl2 is enabled on the system
for example, listing all the available wsl images on my local machine i am using a snippet found in an answer provided in another "kind of related" SO post.
using (var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"cmd.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = true,
}
})
{
proc.Start();
proc.StandardInput.WriteLine("wsl --list");
System.Threading.Thread.Sleep(500);
proc.StandardInput.Flush();
proc.StandardInput.Close();
proc.WaitForExit(5000);
var c = proc.StandardOutput.ReadToEnd();
Console.WriteLine(c);
Console.ReadLine();
}
now the expected output should be
what i am getting is
if i inspect using breakpoint i get this in "var c"
Ideally i want to be able to have a list that contains the 2 dockers items inside C#, changing the wait time didn't help.
in the ProcessStartInfo you have to set
StandardOutputEncoding = Encoding.Unicode;
StandardErrorEncoding = Encoding.Unicode;
for direct call of wsl use additionally:
FileName = #"wsl.exe";
Arguments = #"-l -v";
I doing my final year project by implementing learning web application using ASP.NET Core
however, in some page i need the user to interact with some command line application where these commands need to be sent based on the given output from the command line application. I have no issue with sending on command, but when it comes to the second command i got several issues. here is the code
public static Process process = new Process()
{
StartInfo = new ProcessStartInfo
FileName = "cmd",
RedirectStandardOutput = true,
RedirectStandardInput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};
This is my definition for my process i have created outside the function because i do need to use the same process several time until the user leave the page.
For the process.Start(); I have putted with the function of viewing the page, so the process is started already and no issue with it.
public IActionResult acceptingInputFromUser(string input)
{
string result;
try
{
StreamWriter sw = process.StandardInput;
StreamReader rd = process.StandardOutput;
using (process.StandardInput)
{
sw.WriteLine(input);
sw.Flush();
sw.Close();
result = process.StandardOutput.ReadToEnd();
}
}catch (Exception ex)
{
result = ex.ToString();
}
return Json(result);
}
Here where is the issue, once the user submit any input the the first time will accept and give the result, however when he send another request it says
Cannot write to a closed TextWriter
I have tried several ways but so far i couldn't find solution. Can anyone help me with this error like how I can open the Textwriter again or if there is any other efficient way to where I can use CMD freely.
I want to allow users to create their own Python scripts that run on the server and give output to the users. Likely I'll be allowing users to use Selenium in their scripts, and to write to files in a specific folder. I'm new to Python however assume there are security risks. How would you suggest I protect the server from malicious user code? Below is the C# code I'm using at present to run Python.
public static string Run()
{
string fileName = #"C:\temp\text.py";
Process p = new Process();
p.StartInfo = new ProcessStartInfo(#"python", fileName)
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
return output;
}
Mostly just as a curiosity, I wrote a little app to start up Terminator shell on Windows, using Ubuntu/WSL and Xming window server.
Doing things manually from the shell, I can run Firefox, gedit, Terminator, etc on Windows, it's pretty cool.
So I checked the location of bash.exe using where bash and it returned...
C:\Windows\System32\bash.exe
However when I tried to run this code...
using (var xminProc = new Process())
{
xminProc.StartInfo.FileName = #"C:\Program Files (x86)\Xming\Xming.exe";
xminProc.StartInfo.Arguments = ":0 -clipboard -multiwindow";
xminProc.StartInfo.CreateNoWindow = true;
xminProc.Start();
}
using (var bashProc = new Process())
{
bashProc.StartInfo.FileName = #"C:\Windows\System32\bash.exe";
bashProc.StartInfo.Arguments = "-c \"export DISPLAY=:0; terminator; \"";
bashProc.StartInfo.CreateNoWindow = true;
bashProc.Start();
}
I get the error...
System.ComponentModel.Win32Exception: 'The system cannot find the file specified'
And checking my entire system for bash.exe reveals it really be in another place altogether...
I'm not sure if this location is one that I can rely on, I'm worried it's ephemeral and can change during a Windows Store update, although I may be wrong about that.
Why does the command prompt show bash.exe to be in System32 but it's really in another location altogether?
Can I get C# to also use the System32 location?
As #Biswapriyo stated first set the platafrom to x64 on your solution:
Then you may run on your ubuntu machine from c# as:
Console.WriteLine("Enter command to execute on your Ubuntu GNU/Linux");
var commandToExecute = Console.ReadLine();
// if command is null use 'ifconfig' for demo purposes
if (string.IsNullOrWhiteSpace(commandToExecute))
{
commandToExecute = "ifconfig";
}
// Execute wsl command:
using (var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"cmd.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = true,
}
})
{
proc.Start();
proc.StandardInput.WriteLine("wsl " + commandToExecute);
System.Threading.Thread.Sleep(500); // give some time for command to execute
proc.StandardInput.Flush();
proc.StandardInput.Close();
proc.WaitForExit(5000); // wait up to 5 seconds for command to execute
Console.WriteLine(proc.StandardOutput.ReadToEnd());
Console.ReadLine();
}
I have a native EXE that converts a file based on command line arguments. Provided, I know how to give full path names of the input and output files, can I run such an EXE from my app service when some button is pressed and wait till the output file is created? Converting to DLL is not an option.
As far as I know, we could run a native exe in the azure app service.
But we couldn't directly pass the parameter to the native exe.
You need write a web application or something else for the user to type in the input parameter.
Then you could use Process.Start method to run the exe.
About how to do it , you could refer to this code sample.
I use ASP.NET MVC to get the input parameter then send the parameter to the exe and get the result.
public ActionResult Index()
{
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = Server.MapPath("/exe/Sum.exe"),
//Arguments could be replaced
Arguments = "1 2",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
// do something with line
Response.Write( " The result is : " + line);
}
//await getResultAsync();
return View();
}
Result: