But I’m a novice in about batching, command line & arguments
I make my first batch file “ForestRunFortran.bat”
And if I double click it, runs the application perfectly!
But if I make it run via Unity by using:
it does not run I think it launches but it closes itself without working.
Any idea why?
My final gold, if it is possible, is to run it in a separate thread and render this prompt embedded in a texrender inside my game. Or run inside my game the CMD prop but that is not important now.
Inside the fortran.bat file, there is this argument Fortran.exe <Input.txt >output.txt
Inside Input.txt has the command line for executing inside Fortran.exe
Fortran.exe can be run via CMD and control via command line.
A batch file is a piece of text that by convention the CMD.EXE command processor will open for you, then interpret the instructions inside and try to do them according to its syntax rules.
In your case, CMD.EXE will launch Forest.exe and take stdin from Input.txt and send stdout to output.txt
When you launch it from within Unity, CMD.EXE (or COMMAND.COM on older windows systems) isn’t involved.
You can try specifying CMD.EXE FORESTRUN.BAT but that will only work if CMD.EXE is in the path that Unity searches, which I’m not sure what it is. There are probably other workaround ways but in general I don’t think this approach is going to result in reliable software: the moment you install on a system that doesn’t have CMD.EXE available, or in the path, your batch file won’t run.
As for threading and interprocess communication (a separate program/process communicating with your Unity project), let me just say that is a HUGE undertaking and will require a lot of research into various mechanisms, pretty much all of which will be platform dependent, i.e., Windows or Mac, etc.
Ok, that is a lot of info thank!
For simplicity in this post, I will change the word Forest to Fortran
Multi-Threading aside, I wish not to convert this Fortran exe to C#. I need to launch it if is possible. So I will use this game only for Windows standalone, for now(no other platforms). Also, the instructions inside that I need to pass to the Fortran exe are always the same. So Is simple to control.
I just need to run this bat or execute “Fortran.exe <Input.txt >output.txt”
Here is the best example a friend found for my case: https://github.com/chfenger/xfoil_call/blob/master/Xfoil_call/main_form.cs
The main code is in the main_form.cs file. Although all the messages are in Korean, it seems that the program generates for each run a command file named “call.bat”.
It passes the input command to xfoil.exe placing the special command file on its standard input:
xfoil.exe <command.dat
The command.dat file is built “on the fly” by this program.
In the main_form.cs at line 468 this program calls this “call.bat” command.
In the next line (p.WaitForExit(12000)) it waits for the xfoil Fortuna results, but no longer than 12s
And Changing strategy?
As second option I’m able to open CMD using process variable :
And pass the arguments that run the common line?
I’m honestly don’t know well how to do it
But I understand from you that is not possible.
To control it using arguments, these lines are always the same.
as for example:
Fortuna.exe that will be in Application.dataPath + “/StreamingAssets/Fortuna.exe”
command1 (enter)
command2 (enter)
quit (enter)
I don’t but there must be some google-worthy stuff out there. The main difference to note is that those “< input.txt” and “> output.txt” parts are NOT arguments in the strictest sense. They are directives to the shell (CMD or whatever) to redirect file handles prior to launching the process in question. The underlying process you launch will never see those as arguments.
That makes sense; because as for example this line is not running. Process.Start(Application.dataPath + "/StreamingAssets/Fortrun.exe", " <Input.txt");
It’s for escape sequences, such as ‘\t’ = tab, ‘\n’ = newline, ‘\’ = single '', ‘"’ single quotation, etc…
If the character following the blackslash isn’t a recognized escape sequence, you get an error.
So, you can write:
string s = @"C:\Whatever";
// or
string s = "C:\\Whatever"; // same thing.
Ok, so here: link
are using /r: and /out: inside the argument
any idea what is for /r (i presume return or reference) and where to find the explanation or a list?
If you’re still looking to get this working, I fumbled around trying to make something similar work.
I opened a program, and redirect both its stdin and stdout.
I used Streams (StreamReader/Writer) to read in the text, write it… snippet to explain my horrible words.
StreamWriter sw = process.StandardInput; // 'process' was my Process type variable.. as you probably guessed.
StreamReader sr = process.StandardOutput;
sw.Write(File.ReadAllText("test.txt"));
string s = sr.ReadToEnd();
using (StreamWriter sw2 = new StreamWriter("test2.txt")) sw2.Write(s);
Now, I’m sure that’s far from perfect
I’m not sure what’s good practice, tbh, as I’ve never used this (maybe once I tried it before).
Yes, I’m still there googling and experimenting.
I take out the Output side. I’m trying to run it!
when I run it, the cmd prompt opens and closes immediately.
I was able to see that there is a “0” zero.
That probably blocks the code. I do not know where is coming from or how to take it out.
Can “0” be the space between Fortran.exe and <Input.txt at line 13?
Probably Windows is blocking as Kurt mention in his first answer.
I will try to understand and experiment with your code. Thanks!
Okay, couple of small differences. I didn’t use a .bat file to launch.
Also, I didn’t directly use the arguments from the command line.
So my test simulation … it used Console.Readline.
I’m not sure if that’s helpful extra info, but thought I’d be thorough as you’re trying to work it out.
This is the entire code. Complete with a bad/lazy example of having the program call itself, so I didn’t have to make 2 programs. Sigh…
namespace Test_Code
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Process process = new Process();
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = "Test Code.exe";
process.StartInfo.Arguments = "test";
process.Start();
StreamWriter sw = process.StandardInput;
StreamReader sr = process.StandardOutput;
sw.Write(File.ReadAllText("test.txt"));
string s = sr.ReadToEnd();
using (StreamWriter sw2 = new StreamWriter("test2.txt")) sw2.Write(s);
process.WaitForExit();
Console.ReadLine();
}
if (args.Length > 0)
{
string str = "";
// Note, there was "end" on the last line of the file. Not necessary, but just what I used.
while ((str = Console.ReadLine()) != "end")
{
Console.WriteLine(str);
}
}
}
static void print(string msg)
{
Console.WriteLine(msg);
}
}
}
Like you, I could not see the output on the screen. It was in the output text file, though.