Come chiamare un programma esterno con parametri?
-
20-08-2019 - |
Domanda
Vorrei chiamare un programma Windows nel mio codice con parametri determinati all'interno del codice stesso.
Non sto cercando di chiamare una funzione o un metodo esterno, ma un vero file .exe o batch / script all'interno dell'ambiente WinXP.
C o C ++ sarebbe la lingua preferita, ma se ciò viene fatto più facilmente in qualsiasi altra lingua fammelo sapere (ASM, C #, Python, ecc.)
Soluzione
Quando chiami CreateProcess (), System (), ecc., assicurati di citare due volte le stringhe del nome file (incluso il nome file del programma di comando) nel caso in cui i nomi file e / o il percorso completo abbiano spazi in caso contrario le parti del percorso del nome file verranno analizzate dall'interprete dei comandi come argomenti separati.
system("\"d:some path\\program.exe\" \"d:\\other path\\file name.ext\"");
Per Windows si consiglia di utilizzare CreateProcess (). Ha una configurazione più complicata ma hai un maggiore controllo su come vengono avviati i processi (come descritto da Greg Hewgill). Per veloce e sporco puoi anche usare WinExec (). (system () è portabile su UNIX).
All'avvio di file batch potrebbe essere necessario avviare 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
se si desidera visualizzare la finestra di comando).
Windows dovrebbe trovare command.com o cmd.exe nel PERCORSO di sistema, quindi non dovrebbe essere necessario essere pienamente qualificato, ma se vuoi essere sicuro puoi comporre il nome completo con CSIDL_SYSTEM
(non utilizzare semplicemente C: \ Windows \ system32 \ cmd.exe).
Altri suggerimenti
Esempio C ++:
char temp[512];
sprintf(temp, "command -%s -%s", parameter1, parameter2);
system((char *)temp);
Esempio 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
}
}
Penso che tu stia cercando il CreateProcess funzione nell'API di Windows. In realtà esiste una famiglia di chiamate correlate ma questo ti farà iniziare. È abbastanza semplice.
Uno dei modi più semplici per farlo è utilizzare la funzione di libreria di runtime system()
. Prende una singola stringa come parametro (molti meno parametri rispetto a CreateProcess
!) E la esegue come se fosse digitata sulla riga di comando. exec*
attende inoltre automaticamente che il processo termini prima che ritorni.
Esistono anche limitazioni:
- hai meno controllo sullo stdin e sullo stdout del processo avviato
- non puoi fare nient'altro mentre è in esecuzione l'altro processo (come decidere di ucciderlo)
- non puoi ottenere un controllo sull'altro processo per interrogarlo in alcun modo
La libreria di runtime fornisce anche una famiglia di execl
funzioni (execlp
, execle
, execv
, execvp
, <=>, più o meno) che derivano dall'eredità di Unix e offrono un maggiore controllo sopra il processo.
Al livello più basso, su Win32 tutti i processi vengono avviati dalla funzione <=>, che offre la massima flessibilità.
semplice esempio c ++ (trovato dopo aver cercato alcuni siti 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 (); } }