web-dev-qa-db-ger.com

Wie bekomme ich ein aktuelles Verzeichnis?

Ich habe dies in C # und Delphi gemacht, aber C++ ist böse. Der Zweck ist das Erstellen einer Datei im aktuellen Verzeichnis (in dem die ausführbare Datei ausgeführt wird).

Mein Code:

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

Ich bekomme eine Ausnahme bei GetCurrentDirectory ().

Bitte sagen Sie mir, warum ich eine Ausnahme bekomme und wie mache ich es in C++ einfacher?

47
Ivan Prodanov

Ich würde empfehlen, ein Buch über C++ zu lesen, bevor Sie weitergehen, da es hilfreich wäre, einen besseren Stand zu finden. Beschleunigtes C++ von Koenig und Moo ist ausgezeichnet.

Um den ausführbaren Pfad zu erhalten, benutze GetModuleFileName :

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

Hier ist eine C++ - Funktion, die das Verzeichnis ohne Dateinamen abruft:

#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 weist keinen Platz für das Ergebnis zu, es liegt an Ihnen, dies zu tun.

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

Schauen Sie sich auch die Datei Boost.Filesystem library an, wenn Sie dies auf C++ - Weise tun möchten.

34
avakar

IMHO hier sind einige Verbesserungen an anon's Antwort

#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

Sie sollten einen gültigen Pufferplatzhalter angeben. 

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

Die Frage ist nicht klar, ob das aktuelle Arbeitsverzeichnis gewünscht wird oder der Pfad des Verzeichnisses, in dem sich die ausführbare Datei befindet.

Die meisten Antworten scheinen das Letztere zu beantworten.

Für den ersten und den zweiten Teil der Frage nach dem Erstellen der Datei enthält der C++ 17-Standard jetzt die Dateisystembibliothek, die dies sehr vereinfacht:

#include <filesystem>
#include <iostream>

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

Dadurch wird das aktuelle Arbeitsverzeichnis abgerufen, der Pfad wird mit dem Dateinamen versehen und eine leere Datei erstellt. Beachten Sie, dass das Pfadobjekt die os-abhängige Pfadbehandlung übernimmt, sodass cwd.string () eine os-abhängige Pfadzeichenfolge zurückgibt. Neato.

4
Rasmus Dall

Vergessen Sie nicht, Ihre Puffer mit etwas zu initialisieren, bevor Sie sie verwenden. Und genauso wichtig, geben Sie Ihren String-Puffern Platz für die Endung null

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

Referenz

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

Ich konnte GetModuleFileName nicht korrekt verwenden. Ich fand diese Arbeit sehr gut. 

4
MsLate

Sie können den Dateinamen auf elegante Weise von GetModuleFileName() entfernen:

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

Ich hoffe es hilft!

3
ProXicT

GetCurrentDirectory () ruft das aktuelle Verzeichnis ab, in dem das Exe from aufgerufen wird. Verwenden Sie GetModuleFileName (NULL ...), um den Speicherort des Exe abzurufen. wenn Sie das Handle für das Exe haben, können Sie es von GetCommandLine () ableiten, wenn Sie dies nicht tun.

Wie Mr. Butterworth betont, brauchen Sie keinen Griff.

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

Warum zieht es hier niemand in Betracht, diesen einfachen Code zu verwenden?

TCHAR szDir[MAX_PATH] = { 0 };

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

oder noch einfacher

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

Wenn Sie die Poco - Bibliothek verwenden, handelt es sich um einen Einzeiler, der meiner Meinung nach auf allen Plattformen funktionieren sollte.

Poco::Path::current()
0

Code-Snippets aus meinem CAE-Projekt mit Unicode-Entwicklungsumgebung:

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

Verwenden Sie einfach die Vorlage CA2CAEX oder CA2AEX, die die interne API :: MultiByteToWideChar oder :: WideCharToMultiByte aufruft.

0
user3782257

Ein einfacher Weg, dies zu tun, ist: 

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

argv[] ist so ziemlich ein Array mit Argumenten, mit denen Sie die .exe ausgeführt haben, aber das erste ist immer ein Pfad zur ausführbaren Datei. Wenn ich dies baue, zeigt die Konsole: C:\Users\Ulisse\source\repos\altcmd\Debug\currentdir.exe

0
user5736737