web-dev-qa-db-fra.com

Comment obtenir le répertoire actuel?

Je fais cela en C # et en Delphi, mais C++ est diabolique. Le but est de créer un fichier dans le répertoire actuel (où l'exécutable est en cours d'exécution).

Mon code:

LPTSTR NPath = NULL;
DWORD a = GetCurrentDirectory(MAX_PATH,NPath);
HANDLE hNewFile = CreateFile(NPath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

Je reçois une exception à GetCurrentDirectory ().

Dites-moi pourquoi j'obtiens une exception et comment puis-je simplifier les choses en C++?

47
Ivan Prodanov

Je recommanderais de lire un livre sur C++ avant d'aller plus loin, car il serait utile de prendre des mesures plus solides. C++ accéléré de Koenig et Moo est excellent.

Pour obtenir le chemin du fichier exécutable, utilisez GetModuleFileName :

char buffer[MAX_PATH];
GetModuleFileName( NULL, buffer, MAX_PATH );

Voici une fonction C++ qui obtient le répertoire sans le nom du fichier:

#include <windows.h>
#include <string>
#include <iostream>
using namespace std;;

string ExePath() {
    char buffer[MAX_PATH];
    GetModuleFileName( NULL, buffer, MAX_PATH );
    string::size_type pos = string( buffer ).find_last_of( "\\/" );
    return string( buffer ).substr( 0, pos);
}

int main() {
    cout << "my directory is " << ExePath() << "\n";
}
105
anon

GetCurrentDirectory n'alloue pas d'espace pour le résultat, c'est à vous de le faire.

TCHAR NPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH, NPath);

Regardez aussi Boost.Filesystem library si vous voulez utiliser C++.

34
avakar

IMHO voici quelques améliorations à réponse d'Anon

#include <windows.h>
#include <string>
#include <iostream>

std::string GetExeFileName()
{
  char buffer[MAX_PATH];
  GetModuleFileName( NULL, buffer, MAX_PATH );
  return std::string(buffer);
}

std::string GetExePath() 
{
  std::string f = GetExeFileName();
  return f.substr(0, f.find_last_of( "\\/" ));
}
10
cdiggins

Vous devez fournir un espace réservé de tampon valide ..__ qui correspond à: 

TCHAR s[100];
DWORD a = GetCurrentDirectory(100, s);
4
yves Baumes

La question n'est pas claire si le répertoire de travail en cours est voulu ou le chemin du répertoire contenant l'exécutable.

La plupart des réponses semblent répondre à ces dernières.

Mais pour l’ancien, et pour la deuxième partie de la question de la création du fichier, le standard C++ 17 incorpore maintenant la bibliothèque du système de fichiers, ce qui simplifie beaucoup ceci:

#include <filesystem>
#include <iostream>

std::filesystem::path cwd = std::filesystem::current_path();
cwd /= "filename.txt";
std::ofstream file(cwd.string());
file.close();

Ceci récupère le répertoire de travail actuel, ajoute le nom de fichier au chemin et crée un fichier vide. Notez que l'objet path prend en charge le traitement du chemin dépendant du système d'exploitation. Cwd.string () renvoie donc une chaîne de chemin d'accès dépendant du système d'exploitation. Neato.

4
Rasmus Dall

N'oubliez pas d'initialiser vos tampons sur quelque chose avant de les utiliser. Et tout aussi important, donnez à vos chaînes de caractères un espace pour la fin null

TCHAR path[MAX_PATH+1] = L"";
DWORD len = GetCurrentDirectory(MAX_PATH, path);

Référence

4
Jj Rivero
#include <iostream>    
#include <stdio.h>
#include <dirent.h>

std::string current_working_directory()
{
    char* cwd = _getcwd( 0, 0 ) ; // **** Microsoft specific ****
    std::string working_directory(cwd) ;
    std::free(cwd) ;
    return working_directory ;
}

int main(){
    std::cout << "i am now in " << current_working_directory() << endl;
}

J'ai échoué à utiliser GetModuleFileName correctement. J'ai trouvé ce travail très bien .. juste testé sur Windows, pas encore sur Linux :) 

4
MsLate

Vous pouvez supprimer le nom de fichier de GetModuleFileName() de manière plus élégante:

TCHAR fullPath[MAX_PATH];
TCHAR driveLetter[3];
TCHAR directory[MAX_PATH];
TCHAR FinalPath[MAX_PATH];
GetModuleFileName(NULL, fullPath, MAX_PATH);
_splitpath(fullPath, driveLetter, directory, NULL, NULL);
sprintf(FinalPath, "%s%s",driveLetter, directory);

J'espère que ça aide!

3
ProXicT

GetCurrentDirectory () obtient le répertoire en cours dans lequel l'exe est appelé from. Pour obtenir l'emplacement de l'exe, utilisez GetModuleFileName (NULL ...). si vous avez le pseudo de l'exe, ou vous pouvez le dériver de GetCommandLine () si vous n'en avez pas.

Comme M. Butterworth l'a fait remarquer, vous n'avez pas besoin d'une poignée.

2
nickd
WCHAR path[MAX_PATH] = {0};
GetModuleFileName(NULL, path, MAX_PATH);
PathRemoveFileSpec(path);
2
Zhi Wang
#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);
}
2
freezotic

Pourquoi personne ici n'envisage-t-il d'utiliser ce code simple?

TCHAR szDir[MAX_PATH] = { 0 };

GetModuleFileName(NULL, szDir, MAX_PATH);
szDir[std::string(szDir).find_last_of("\\/")] = 0;

ou même plus simple

TCHAR szDir[MAX_PATH] = { 0 };
TCHAR* szEnd = nullptr;
GetModuleFileName(NULL, szDir, MAX_PATH);
szEnd = _tcsrchr(szDir, '\\');
*szEnd = 0;
1
123iamking

Si vous utilisez la bibliothèque Poco , c'est une ligne et cela devrait fonctionner sur toutes les plateformes, je pense.

Poco::Path::current()
0
James Selvakumar

Extraits de code de mon projet CAE avec environnement de développement Unicode:

/// @brief Gets current module file path. 
std::string getModuleFilePath() {
    TCHAR buffer[MAX_PATH];
    GetModuleFileName( NULL, buffer, MAX_PATH );
    CT2CA pszPath(buffer);
    std::string path(pszPath);
    std::string::size_type pos = path.find_last_of("\\/");
    return path.substr( 0, pos);
}

Utilisez simplement le modèle CA2CAEX ou CA2AEX qui appelle l'API interne :: MultiByteToWideChar ou :: WideCharToMultiByte

0
user3782257

Un moyen facile de le faire est: 

int main(int argc, char * argv[]){
    std::cout << argv[0]; 
    std::cin.get();
}

argv[] est en gros un tableau contenant les arguments avec lesquels vous avez exécuté le fichier .exe, mais le premier est toujours un chemin d'accès à l'exécutable. Si je construis cela, la console affiche: C:\Users\Ulisse\source\repos\altcmd\Debug\currentdir.exe

0
user5736737