kod3brkr Ответов: 3

C# Run CMD from website button


Я играю в Террарию. Я иногда устраиваю игры. Я хочу, чтобы пользователи могли захватить текущую карту моего мира, когда они захотят. Поэтому я создал простую веб-страницу, чтобы использовать MoreTerra (картографическое программное обеспечение) для создания карты в фоновом режиме для меня и веб-страницу для отображения карты пользователям.

MoreTerra поставляется с пакетным файлом, который запускается из командной строки. пакетный файл содержит следующее:

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


Я хочу выполнить это, когда пользователь нажимает кнопку на моей веб-странице, поэтому я создал следующий код:

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);
           }


До сих пор это ничего не дало. В Диспетчере задач я вижу, как процесс Хоста окна консоли запускается и останавливается менее чем за секунду каждый раз, когда я нажимаю кнопку, но изображение не генерируется. Переменные вывода и ошибки всегда пусты. но когда я отлаживаю и ломаю на "подпроцессе.WaitForExit();" я вижу эту ошибку в окне Locals в 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


Я пробовал использовать то же самое cmd.exe как в коде C#, так и в пакетном файле, как x86, так и x64, но безрезультатно.
Я использовал corflags.exe чтобы проверить MoreTerra.exe, и это не 32-битный требуется, мой код компилируется для AnyCPU, так что я в реальной потере.
Я прочесал интернет, но все, что я нашел, включено в приведенный выше код.

Любая помощь будет очень признательна. ТИА

3 Ответов

Рейтинг:
23

Sergey Alexandrovich Kryukov

cmd.exe /c MoreTerra.exe %1 %2 %3 %4
в этом нет никакого смысла. Вам нужно просто
MoreTerra.exe %1 %2 %3 %4

или
start MoreTerra.exe %1 %2 %3 %4

Start отличается: он запускает приложение и не ждет его окончания.

Поймите же: CMD.EXE не имеет ничего общего с запуском какого-либо процесса. Это интерпретатор команд, который вам нужен только для ручного использования.

В коде 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));

—СА


kod3brkr

в этом есть смысл, Сергей. Прости, что не перезвонил тебе по этому поводу. запланированное задание работало довольно хорошо, и я заставил его обновлять изображения каждый час или около того. Ваше решение работало бы так же хорошо и было бы немного более динамичным, если бы вы могли поместить весь этот код под нажатие кнопки, чтобы пользователь мог обновить карты в любое время. В любом случае, я больше не управляю сервером Terraria. Я принимаю ваше решение, чтобы у вас были Интернет-точки!!!
код3бркр

kod3brkr

в этом есть смысл, Сергей. Прости, что не перезвонил тебе по этому поводу. запланированное задание работало довольно хорошо, и я заставил его обновлять изображения каждый час или около того. Ваше решение работало бы так же хорошо и было бы немного более динамичным, если бы вы могли поместить весь этот код под нажатие кнопки, чтобы пользователь мог обновить карты в любое время. В любом случае, я больше не управляю сервером Terraria. Я принимаю ваше решение, чтобы у вас были Интернет-точки!!!
код3бркр

Рейтинг:
0

kod3brkr

Было предложено просто использовать пакетный файл в запланированной задаче и заставить веб-сайт показывать сгенерированное изображение, а не рисковать спамом процесса нескольких пользователей, нажимающих кнопку обновления на веб-сайте, на другом форуме, где я также задал этот вопрос. Проблема решена. Я добавил переменную на страницу отображения карты, чтобы вытащить последнюю обновленную дату из сгенерированного файла, и бум, готово. Спасибо за все советы и урок по Start vs CMD.exe


Рейтинг:
0

Mehdi Gholam

Попробуйте вместо этого эту строку :

si.FileName = @"cmd.exe"; // the OS will select the write cmd for 32/64 bit


Sergey Alexandrovich Kryukov

Извиняюсь. Мне очень жаль.
Я устал объяснять: CMD.EXE-он никогда не нужен. Это интерпретатор команд. предназначен для интерактивного использования. Это не помогает запустить какое-либо другое приложение; вы можете использовать параметр "/C", но он полностью избыточен. Ну, ОП этого не понял, но вы должны это понять, если даете совет.

Я действительно советую вам удалить этот ответ (даже если он будет работать), чтобы не путать людей с этой совершенно неправильной идеей использования CMD.EXE-да.

—СА