2009-05-17 26 views
42

Ich habe dies in C# und Delphi getan, aber C++ ist böse. Der Zweck ist, eine Datei im aktuellen Verzeichnis (wo die ausführbare Datei ausgeführt wird) zu erstellen.Wie bekomme ich das aktuelle Verzeichnis?

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 Ausnahme bei GetCurrentDirectory().

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

+2

#include char * getcwd (char * buf, size_t size); http://stackoverflow.com/questions/298510/how-to-get-the-current-directory-in-ac-program – Anuswadh

+0

möglich Duplikat [Wie kann ich das Verzeichnis, das ein Programm läuft von?] (http://stackoverflow.com/questions/143174/how-do-i-get-the-directory-that-a-program-is-running-from) – user

+2

Bitte beachten Sie: aktuelles Verzeichnis ist nicht immer das Verzeichnis, in dem sich die exe befindet. (zB c: \ users \ me> \ dir1 \ dir2 \ runme.exe Hier befinden Sie sich in c: \ users \ me und laufen exe von \ dir1 \ dir2 \). – Mercury

Antwort

97

Ich würde empfehlen, ein Buch über C++ zu lesen, bevor Sie weiter gehen, da es hilfreich wäre, einen festeren Fuß zu bekommen. Accelerated C++ von Koenig und Moo ist ausgezeichnet.

Um die ausführbare Datei Pfad GetModuleFileName verwenden zu erhalten:

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

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

#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"; 
} 
+4

NB, dass Sie möglicherweise ein breites Zeichen verwenden müssen, wie wchar_t Puffer [MAX_PATH]; in diesen Tagen ... – rogerdpack

+2

Oder 'GetModuleFileNameA' – Mikhail

+1

Um zu wiederholen, was @Mikhail sagte, würden Sie' GetModuleFileNameA' für Code verwenden, der einen Multi-Byte-Zeichensatz verwendet, und 'GetModuleFileNameW' für Unicode. 'GetModuleFileName' (ohne' A' oder 'W') ist eigentlich ein Alias ​​für den Zeichensatz, den Ihr Projekt verwenden soll. So werden die meisten Win32-API-Methoden, die Zeichenfolgen verwenden, eingerichtet. Wenn Sie also ein Unicode-Projekt haben und Ihre Strings ebenfalls Unicode sind, müssten Sie nur 'GetModuleFileName' aufrufen. Gleiches gilt, wenn Ihr Projekt Multi-Byte ist und Multi-Byte-Strings verwendet. – RectangleEquals

30

GetCurrentDirectory reserviert keinen Platz für das Ergebnis, es liegt an Ihnen, dies zu tun.

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

Werfen Sie auch einen Blick auf Boost.Filesystem Bibliothek, wenn Sie diese der C++ Art und Weise tun wollen.

+0

Hmm, NPath verweist auf ein anderes Verzeichnis. Wie kann ich das Verzeichnis anzeigen, in dem die ausführbare Datei gespeichert ist? –

+6

Das aktuelle Verzeichnis ist nicht identisch mit dem Verzeichnis der ausführbaren Datei, auch nicht unter C# und Delphi. Vielleicht könnten Sie Ihre Frage klarer stellen? –

+0

John, das ist ein bisschen mehr beteiligt und kann nicht einfach in einem Kommentar beantwortet werden. Vielleicht solltest du Neils Rat befolgen (beide). – avakar

4

Sie sollten einen gültigen Puffer Platzhalter zur Verfügung stellen. das ist:

TCHAR s[100]; 
DWORD a = GetCurrentDirectory(100, s); 
2

GetCurrentDirectory() wird das aktuelle Verzeichnis, das ist, wo die exe von aufgerufen wird. Verwenden Sie GetModuleFileName (NULL ...), um den Speicherort der Exe abzurufen. Wenn Sie das Handle mit der exe haben, oder Sie können es von GetCommandLine() ableiten, wenn Sie nicht tun.

Wie Mr. Butterworth hervorhebt, brauchen Sie keinen Griff.

+3

Eigentlich brauchen Sie kein echtes Handle - ein NULL-Handle bekommt den Namen der ausführbaren Datei mit Pfad. –

-1

das Verzeichnis zu finden, wo die ausführbare Datei ist, können Sie verwenden:

TCHAR szFilePath[_MAX_PATH]; 
::GetModuleFileName(NULL, szFilePath, _MAX_PATH); 
3

Bitte vergessen Sie nicht Ihre Puffer etwas zu initialisieren bevor sie verwendet wird. Und genauso wichtig, geben Sie Ihren String Puffer Platz für die Endung null

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

Reference

9

IMHO sind hier einige Verbesserungen anon's answer.

#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("\\/")); 
} 
+0

Das ist eigentlich anders. Wenn Sie den Verzeichnispfad nicht angeben, geben Sie den Pfad der Datei einschließlich der Datei an. – dyesdyes

1
WCHAR path[MAX_PATH] = {0}; 
GetModuleFileName(NULL, path, MAX_PATH); 
PathRemoveFileSpec(path); 
1
#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); 
} 
3

Sie können den Dateinamen von GetModuleFileName() mit eleganter Art und Weise 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); 

Hoffe, es hilft!

-3
String^ exePath = Application::ExecutablePath;<br> 
MessageBox::Show(exePath); 
0

-Code-Schnipsel aus meinem CAE-Projekt mit Entwicklungsumgebung 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); 
} 

einfach die templete verwenden CA2CAEX oder CA2AEX, die die interne API :: MultiByteToWideChar oder ruft :: WideCharToMultiByte

2
#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. nur unter Windows getestet, noch nicht auf Linux :)

1

Warum denkt hier niemand mit diesem einfachen Code?

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; 
Verwandte Themen