c++ - trovare - javac non è riconosciuto come comando interno o esterno un programma eseguibile o un file batch




Come posso ottenere la directory da cui è in esecuzione un programma? (14)

Esiste un metodo agnostico indipendente dalla piattaforma e dal filesystem per ottenere il percorso completo della directory da cui viene eseguito un programma utilizzando C / C ++? Da non confondere con la directory di lavoro corrente. (Si prega di non suggerire librerie a meno che non siano standard come clib o STL.)

(Se non esiste alcun metodo indipendente da piattaforma / file system, i suggerimenti che funzionano in Windows e Linux per specifici filesystem sono anch'essi benvenuti.)


Come menzionato da Minok , non esiste una funzionalità del genere specificata nello standard C o C ++. Questa funzione è considerata puramente specifica per il sistema operativo ed è specificata nello standard POSIX, ad esempio.

Thorsten79 ha dato buoni suggerimenti, è la libreria Boost.Filesystem. Tuttavia, potrebbe essere scomodo nel caso in cui non si desideri avere dipendenze in tempo reale in formato binario per il proprio programma.

Una buona alternativa che mi sento di raccomandare è la raccolta di librerie STLSoft C ++ al 100% solo per intestazioni Matthew Wilson (autore di libri da leggere sul C ++). C'è una facciata portatile PlatformSTL dà accesso alle API specifiche del sistema: WinSTL per Windows e UnixSTL su Unix, quindi è una soluzione portatile. Tutti gli elementi specifici del sistema sono specificati con l'uso di tratti e politiche, quindi è un framework estendibile. C'è una libreria di filesystem fornita, ovviamente.


Ecco il codice per ottenere il percorso completo per l'app in esecuzione:

Finestre:

int bytes = GetModuleFileName(NULL, pBuf, len);
if(bytes == 0)
    return -1;
else
    return bytes;

Linux:

char szTmp[32];
sprintf(szTmp, "/proc/%d/exe", getpid());
int bytes = MIN(readlink(szTmp, pBuf, len), len - 1);
if(bytes >= 0)
    pBuf[bytes] = '\0';
return bytes;

Il Filesystem TS ora è uno standard (e supportato da gcc 5.3+ e clang 3.9+), quindi puoi usare la funzione current_path() da esso:

std::string path = std::experimental::filesystem::current_path();

In gcc (5.3+) per includere Filesystem è necessario utilizzare:

#include <experimental/filesystem>

e collega il tuo codice con -lstdc++fs .

Se si desidera utilizzare Filesystem con Microsoft Visual Studio, leggere questo .


Il comando linux bash che progname riporterà un percorso da programmare.

Anche se si può emettere il comando da all'interno del programma e indirizzare l'output in un file tmp e il programma legge successivamente quel file tmp, non ti dirà se quel programma è quello che sta eseguendo. Ti dice solo dove si trova un programma con quel nome.

È necessario ottenere il numero identificativo del processo e analizzare il percorso del nome

Nel mio programma voglio sapere se il programma è stato eseguito dalla directory bin dell'utente o da un altro nel percorso o da / usr / bin. / usr / bin conterrebbe la versione supportata. La mia sensazione è che in Linux c'è l'unica soluzione che è portatile.


No, non esiste un modo standard. Credo che gli standard C / C ++ non considerino nemmeno l'esistenza di directory (o altre organizzazioni di file system).

Su Windows, GetModuleFileName () restituirà il percorso completo del file eseguibile del processo corrente quando il parametro hModule è impostato su NULL . Non posso aiutare con Linux.

Inoltre, è necessario chiarire se si desidera che la directory corrente o la directory in cui risiede l'immagine del programma / eseguibile. Così com'è, la tua domanda è un po 'ambigua su questo punto.


Non è possibile utilizzare argv [0] per questo scopo, di solito contiene il percorso completo dell'eseguibile, ma non necessariamente - il processo potrebbe essere creato con un valore arbitrario nel campo.

Inoltre, la directory corrente e la directory con l'eseguibile sono due cose diverse, quindi getcwd () non ti aiuterà neanche.

Su Windows usa GetModuleFileName (), su Linux read / dev / proc / procID / .. file.


Per i percorsi relativi, ecco cosa ho fatto. Sono consapevole dell'età di questa domanda, voglio semplicemente contribuire a una risposta più semplice che funziona nella maggior parte dei casi:

Di 'che hai un percorso come questo:

"path/to/file/folder"

Per qualche ragione, gli eseguibili costruiti da Linux realizzati in eclipse funzionano bene con questo. Tuttavia, Windows diventa molto confuso se viene fornito un percorso come questo con cui lavorare!

Come detto sopra ci sono diversi modi per ottenere il percorso corrente verso l'eseguibile, ma il modo più semplice che trovo funzioni un fascino nella maggior parte dei casi è aggiungerlo al FRONT del tuo percorso:

"./path/to/file/folder"

Aggiungendo semplicemente "./" dovresti farti smistare! :) Quindi puoi iniziare a caricare da qualunque directory desideri, purché sia ​​con l'eseguibile stesso.

EDIT: Questo non funzionerà se proverai ad avviare l'eseguibile da code :: blocks se questo è l'ambiente di sviluppo usato, perché per qualche ragione, code :: blocks non carica roba a destra ...: D

EDIT2: alcune nuove cose che ho trovato è che se si specifica un percorso statico come questo nel codice (supponendo che Example.data sia qualcosa che è necessario caricare):

"resources/Example.data"

Se quindi si avvia l'app dalla directory effettiva (o in Windows, si crea una scorciatoia e si imposta la dir di lavoro nella directory dell'app) allora funzionerà in questo modo. Tienilo a mente quando esegui il debug di problemi relativi a percorsi di risorse / file mancanti. (Soprattutto negli IDE che impostano la directory di lavoro errata all'avvio di un exe di build dall'IDE)


Per il sistema Windows alla console è possibile utilizzare il comando system ( dir ). E console ti dà informazioni sulla directory e così via. Leggi informazioni sul comando dir in cmd . Ma per i sistemi di tipo Unix, non lo so ... Se questo comando viene eseguito, leggi il comando bash. ls non visualizza la directory ...

Esempio:

int main()
{
    system("dir");
    system("pause"); //this wait for Enter-key-press;
    return 0;
}

Se si recupera la directory corrente all'avvio del programma, la directory da cui è stato avviato il programma è effettivamente valida. Memorizza il valore in una variabile e fai riferimento ad esso più avanti nel tuo programma. Questo è diverso dalla directory che contiene il file di programma eseguibile corrente . Non è necessariamente la stessa directory; se qualcuno esegue il programma da un prompt dei comandi, il programma viene eseguito dalla directory di lavoro corrente del prompt dei comandi anche se il file del programma vive altrove.

getcwd è una funzione POSIX e supportata immediatamente da tutte le piattaforme conformi a POSIX. Non dovresti fare nulla di speciale (a parte inclinare le intestazioni giuste unistd.h su Unix e direct.h su Windows).

Dato che stai creando un programma C, si collegherà con la libreria di runtime di default c che è collegata a TUTTI i processi nel sistema (eccezioni appositamente predisposte evitate) e includerà questa funzione per impostazione predefinita. Il CRT non è mai considerato una libreria esterna perché fornisce l'interfaccia standard di base conforme al sistema operativo.

Sulla funzione getcwd di windows è stato dichiarato obsoleto a favore di _getcwd. Penso che potresti usarlo in questo modo.

#include <stdio.h>  /* defines FILENAME_MAX */
#ifdef WINDOWS
    #include <direct.h>
    #define GetCurrentDir _getcwd
#else
    #include <unistd.h>
    #define GetCurrentDir getcwd
 #endif

 char cCurrentPath[FILENAME_MAX];

 if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
     {
     return errno;
     }

cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */

printf ("The current working directory is %s", cCurrentPath);

Se vuoi un modo standard senza librerie: No. L'intero concetto di una directory non è incluso nello standard.

Se sei d'accordo sul fatto che alcune dipendenze (portatili) su una lib quasi normale è accettabile: usa la libreria del filesystem di Boost e chiedi il percorso initial_path() .

IMHO che è il più vicino possibile, con un buon karma (Boost è un set di librerie di alta qualità ben consolidato)


Solo per accumulare tardivamente qui, ...

non esiste una soluzione standard, perché le lingue sono agnostiche dei file system sottostanti, così come altri hanno detto, il concetto di un file system basato su directory è al di fuori dell'ambito dei linguaggi c / c ++.

inoltre, non si desidera la directory di lavoro corrente, ma la directory in cui è in esecuzione il programma, che deve tenere conto del modo in cui il programma è arrivato dove è, cioè è stato generato come un nuovo processo tramite una fork, ecc. Per ottenere la directory in cui è in esecuzione un programma, come hanno dimostrato le soluzioni, è necessario ottenere tali informazioni dalle strutture di controllo del processo del sistema operativo in questione, che è l'unica autorità su questa domanda. Quindi, per definizione, è una soluzione specifica per il sistema operativo.


Su Windows il modo più semplice è usare la funzione _get_pgmptr in stdlib.h per ottenere un puntatore a una stringa che rappresenta il percorso assoluto dell'eseguibile, incluso il nome degli eseguibili.

char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe

Una soluzione di libreria (anche se so che questo non è stato chiesto). Se ti capita di utilizzare Qt: QCoreApplication::applicationDirPath()


#include <windows.h>
using namespace std;

// The directory path returned by native GetCurrentDirectory() no end backslash
string getCurrentDirectoryOnWindows()
{
    const unsigned long maxDir = 260;
    char currentDir[maxDir];
    GetCurrentDirectory(maxDir, currentDir);
    return string(currentDir);
}




current-dir