¿Cómo llamar a un programa externo con parámetros?
-
20-08-2019 - |
Pregunta
Me gustaría llamar a un programa de Windows dentro de mi código con parámetros determinados dentro del propio código.
No estoy buscando llamar a una función o método externo, sino a un archivo .exe o por lotes / script real dentro del entorno WinXP.
C o C ++ sería el lenguaje preferido, pero si esto se hace más fácilmente en cualquier otro idioma, hágamelo saber (ASM, C #, Python, etc.).
Solución
Cuando llame a CreateProcess (), System (), etc., asegúrese de poner comillas dobles a las cadenas de nombre de archivo (incluido el nombre del archivo del programa de comando) en caso de que su (s) nombre (s) de archivo y / o la ruta completamente calificada tengan espacios de lo contrario, el intérprete de comandos analizará las partes de la ruta del nombre del archivo como argumentos separados.
system("\"d:some path\\program.exe\" \"d:\\other path\\file name.ext\"");
Para Windows se recomienda usar CreateProcess (). Tiene una configuración más desordenada, pero tiene más control sobre cómo se inician los procesos (como lo describe Greg Hewgill). Para rápido y sucio también puede usar WinExec (). (system () es portátil para UNIX).
Al iniciar archivos por lotes, es posible que deba iniciar con cmd.exe (o command.com).
WinExec("cmd \"d:some path\\program.bat\" \"d:\\other path\\file name.ext\"",SW_SHOW_MINIMIZED);
(o SW_SHOW_NORMAL
si desea que se muestre la ventana de comandos).
Windows debería encontrar command.com o cmd.exe en la RUTA del sistema, por lo que no es necesario que esté completamente calificado, pero si desea estar seguro puede componer el nombre de archivo completo usando CSIDL_SYSTEM
(no use simplemente C: \ Windows \ system32 \ cmd.exe).
Otros consejos
Ejemplo de C ++:
char temp[512];
sprintf(temp, "command -%s -%s", parameter1, parameter2);
system((char *)temp);
Ejemplo de C #:
private static void RunCommandExample()
{
// Don't forget using System.Diagnostics
Process myProcess = new Process();
try
{
myProcess.StartInfo.FileName = "executabletorun.exe";
//Do not receive an event when the process exits.
myProcess.EnableRaisingEvents = false;
// Parameters
myProcess.StartInfo.Arguments = "/user testuser /otherparam ok";
// Modify the following to hide / show the window
myProcess.StartInfo.CreateNoWindow = false;
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
myProcess.Start();
}
catch (Exception e)
{
// Handle error here
}
}
Creo que está buscando el CreateProcess función en la API de Windows. En realidad, hay una familia de llamadas relacionadas, pero esto lo ayudará a comenzar. Es bastante fácil.
Una de las formas más simples de hacer esto es usar la función de biblioteca de tiempo de ejecución system()
. Toma una sola cadena como parámetro (¡muchos menos parámetros que CreateProcess
!) Y la ejecuta como si estuviera escrita en la línea de comando. exec*
también espera automáticamente a que finalice el proceso antes de que regrese.
También hay limitaciones:
- tiene menos control sobre el stdin y el stdout del proceso lanzado
- no puede hacer nada más mientras se ejecuta el otro proceso (como decidir matarlo)
- no puede obtener un identificador del otro proceso para consultarlo de ninguna manera
La biblioteca de tiempo de ejecución también proporciona una familia de execl
funciones (execlp
, execle
, execv
, execvp
, <=>, más o menos) que se derivan de la herencia de Unix y ofrecen más control sobre el proceso.
En el nivel más bajo, en Win32 todos los procesos se inician con la función <=>, que le brinda la mayor flexibilidad.
ejemplo simple de c ++ (encontrado después de buscar en algunos sitios web)
#include <bits/stdc++.h>
#include <cassert>
#include <exception>
#include <iostream>
int main (const int argc, const char **argv) {
try {
assert (argc == 2);
const std::string filename = (const std::string) argv [1];
const std::string begin = "g++-7 " + filename;
const std::string end = " -Wall -Werror -Wfatal-errors -O3 -std=c++14 -o a.elf -L/usr/lib/x86_64-linux-gnu";
const std::string command = begin + end;
std::cout << "Compiling file using " << command << '\n';
assert (std::system ((const char *) command.c_str ()) == 0);
std::cout << "Running file a.elf" << '\n';
assert (std::system ((const char *) "./a.elf") == 0);
return 0; }
catch (std::exception const& e) { std::cerr << e.what () << '\n'; std::terminate (); }
catch (...) { std::cerr << "Found an unknown exception." << '\n'; std::terminate (); } }