Click here to Skip to main content
15,889,867 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I play Terraria. I host games sometimes. I want users to be able to grab a current map of my world, whenever they want to. So I created a simple web page to use MoreTerra (a mapping software) to create a map in the background for me and a web page to display the map to users.

MoreTerra comes with a batch file that runs itself from the command line. the batchfile contains the following:

@ECHO OFF
cmd.exe /c MoreTerra.exe %1 %2 %3 %4
@ECHO ON


I want to execute this when a user clicks a button on my web page, so I created the following code:

C#
try
           {
               // declare variables
               string worldFile = "\"" + AppSettings.GetAppSetting("WorldFile", false) + "\"";
               string outputLocation = "\"" + AppSettings.GetAppSetting("OutputLocation", false) + @"\" + AppSettings.GetAppSetting("ImageFileName", false) + "\"";
               string fileName = AppSettings.GetAppSetting("MT_Location", false) + @"\" + "MoreTerraNoGui.bat";
               ProcessStartInfo si = new ProcessStartInfo();
               // define StartInfo
               si.FileName = @"C:\Windows\SysWOW64\cmd.exe";
               si.Arguments = "/c " + fileName + " -w " + worldFile + " -o " + outputLocation;
               si.WorkingDirectory = AppSettings.GetAppSetting("MT_Location", false);
               si.CreateNoWindow = true;
               si.WindowStyle = ProcessWindowStyle.Hidden;
               si.UseShellExecute = false;
               si.RedirectStandardOutput = true;
               si.RedirectStandardError = true;
               // log arguments for debug check
               Log.WriteToLog(ProjectLogType, "btnRefresh_Click", si.Arguments, LogEnum.Debug);
               // start process and wait for it to finish
               Process subProcess = Process.Start(si);
               subProcess.WaitForExit();
               // log output and errors
               string output = subProcess.StandardOutput.ReadToEnd();
               string error = subProcess.StandardError.ReadToEnd();
               Log.WriteToLog(ProjectLogType, "btnRefresh_Click", output, LogEnum.Debug);
               Log.WriteToLog(ProjectLogType, "btnRefresh_Click", error, LogEnum.Debug);
           }
           catch(Exception x)
           {
               Log.WriteToLog(ProjectLogType, "btnRefresh_Click", x, LogEnum.Critical);
           }


So far it hasn't really done anything. In the Task Manager, I can see Console Window Host process start and stop in less than a second every time I click the button, but no image is generated. The Output and Error variables are always empty. but when I debug and break at "subProcess.WaitForExit();" I can see this error in the Locals Window in Visual Studio

-       MainModule  'subProcess.MainModule' threw an exception of type 'System.ComponentModel.Win32Exception'   System.Diagnostics.ProcessModule {System.ComponentModel.Win32Exception}
+       base    {"A 32 bit processes cannot access modules of a 64 bit process."}   System.Runtime.InteropServices.ExternalException {System.ComponentModel.Win32Exception}
        NativeErrorCode 299 int


I've tried using the same cmd.exe in both the C# code and in the batch file, both x86, and x64, but to no avail.
I used corflags.exe to check MoreTerra.exe, and it's not 32bit required, my code is compiled for AnyCPU, so I'm at a real loss.
I've been scouring the internet, but everything I've found is incorporated into the above code.

Any help would be greatly appreciated. TIA
Posted

cmd.exe /c MoreTerra.exe %1 %2 %3 %4
makes no sense at all. You need simply
MoreTerra.exe %1 %2 %3 %4

or
start MoreTerra.exe %1 %2 %3 %4

Start is different: it starts the application and does not wait for its termination.

Do understand: CMD.EXE has nothing to do with starting any process. This is a command interpreter which you only need for manual use.

In C# code:
C#
string exe = "MoreTerra.exe"; // but you really need to CALCULATE its path name
string first = //...
string second = //...
string third = //...
string forth = //...
System.Diagnostics.Start(exe, string.Format("{0} {1} {2} {3}", first, second, third, forth));

—SA
 
Share this answer
 
Comments
kod3brkr 19-Jan-18 18:24pm    
makes sense, Sergey. Sorry i didn't get back to you on this. the Scheduled Task worked quite well, and I had it refresh the images every hour or so. Your solution would have worked just as well, and would have been a little more dynamic what with being able to put all that code under a button press so the user could refresh the maps at any time. I no longer run the Terraria Server anyway. I accept your solution so you can have internet points!!!
kod3brkr
kod3brkr 19-Jan-18 18:24pm    
makes sense, Sergey. Sorry i didn't get back to you on this. the Scheduled Task worked quite well, and I had it refresh the images every hour or so. Your solution would have worked just as well, and would have been a little more dynamic what with being able to put all that code under a button press so the user could refresh the maps at any time. I no longer run the Terraria Server anyway. I accept you solution so you can have internet points!!!
kod3brkr
It was suggested to just use the batch file in a Scheduled Task and have the website show the generated image rather than risk the process spam of multiple users clicking the refresh button on the website, in another forum that I also asked this question in. Problem solved. I added a variable to the map display page to pull the last updated date from the generated file and boom, done. Thanks for all the advice and the lesson on Start vs CMD.exe
 
Share this answer
 
Try this line instead :
C#
si.FileName = @"cmd.exe"; // the OS will select the write cmd for 32/64 bit
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 22-Oct-14 3:42am    
Sorry. Really sorry.
I tired to explain: "CMD.EXE" is never needed. This is a command interpreter. designed for interactive use. It does not help to start any other application; you could use "/C" parameter, but it is totally redundant. Well, OP did not get it, but you should understand it, if you give an advice.

I really advise you to remove this answer (even if it would work), to avoid confusing people with that completely wrong idea to use CMD.EXE.

—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900