Ich habe dies in C # und Delphi getan, aber C ++ ist böse. Der Zweck besteht darin, eine Datei im aktuellen Verzeichnis zu erstellen (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 erhalte eine Ausnahme bei GetCurrentDirectory ().
Bitte sagen Sie mir, warum ich eine Ausnahme bekomme und wie ich es in C ++ einfacher mache.
Antworten:
Ich würde empfehlen, ein Buch über C ++ zu lesen, bevor Sie fortfahren, da es hilfreich wäre, einen festeren Stand zu bekommen. Accelerated C ++ von Koenig und Moo ist ausgezeichnet.
Verwenden Sie GetModuleFileName, um den ausführbaren Pfad abzurufen :
TCHAR buffer[MAX_PATH] = { 0 }; GetModuleFileName( NULL, buffer, MAX_PATH );
Hier ist eine C ++ - Funktion, die das Verzeichnis ohne den Dateinamen abruft:
#include <windows.h> #include <string> #include <iostream> wstring ExePath() { TCHAR buffer[MAX_PATH] = { 0 }; GetModuleFileName( NULL, buffer, MAX_PATH ); std::wstring::size_type pos = std::wstring(buffer).find_last_of(L"\\/"); return std::wstring(buffer).substr(0, pos); } int main() { std::cout << "my directory is " << ExePath() << "\n"; }
quelle
GetModuleFileNameA
GetModuleFileNameA
für Code, der einen Mehrbyte -Zeichensatz verwendet, undGetModuleFileNameW
für Unicode verwenden.GetModuleFileName
(ohneA
oderW
) ist eigentlich ein Alias für den Zeichensatz, den Ihr Projekt verwenden soll. So werden die meisten Win32-API-Methoden eingerichtet, die Zeichenfolgen verwenden. Wenn Sie also ein Unicode-Projekt haben und Ihre Zeichenfolgen auch Unicode sind, müssen Sie nur aufrufenGetModuleFileName
. Gleiches gilt, wenn Ihr Projekt mehrbyte ist und mehrbyte Zeichenfolgen verwendet.find_last_of()
Methode nicht, gibt es keine Konstante, die das Trennzeichen in Verzeichnisnamen definiert, wie "... / ... / ..." oder "... \ ... \. .. "?GetCurrentDirectory
reserviert keinen Platz für das Ergebnis, es liegt an Ihnen, dies zu tun.Werfen Sie auch einen Blick auf Boost.Filesystem Bibliothek , wenn Sie diese der C ++ Art und Weise tun wollen.
quelle
Die Frage ist nicht klar, ob das aktuelle Arbeitsverzeichnis oder der Pfad des Verzeichnisses mit der ausführbaren Datei gewünscht wird.
Die meisten Antworten scheinen letztere zu beantworten.
Für den ersteren und für den zweiten Teil der Frage der Erstellung der Datei enthält der C ++ 17-Standard jetzt die Dateisystembibliothek, die dies erheblich vereinfacht:
#include <filesystem> #include <iostream> std::filesystem::path cwd = std::filesystem::current_path() / "filename.txt"; std::ofstream file(cwd.string()); file.close();
Dadurch wird das aktuelle Arbeitsverzeichnis abgerufen, der Dateiname zum Pfad hinzugefügt 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.
quelle
IMHO hier sind einige Verbesserungen an Anons 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( "\\/" )); }
quelle
#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 habe GetModuleFileName nicht richtig verwendet. Ich fand diese Arbeit sehr gut. gerade unter Windows getestet, noch nicht unter Linux ausprobiert :)
quelle
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, das Argumente enthält, mit denen Sie die EXE-Datei ausgeführt haben, aber das erste ist immer ein Pfad zur ausführbaren Datei. Wenn ich das baue, zeigt die Konsole:C:\Users\Ulisse\source\repos\altcmd\Debug\currentdir.exe
quelle
Sie sollten einen gültigen Pufferplatzhalter angeben. das ist:
TCHAR s[100]; DWORD a = GetCurrentDirectory(100, s);
quelle
WCHAR path[MAX_PATH] = {0}; GetModuleFileName(NULL, path, MAX_PATH); PathRemoveFileSpec(path);
quelle
Bitte vergessen Sie nicht, Ihre Puffer auf 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
quelle
#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); }
quelle
currentDir
- Ein Argument vom Typ"char *"
ist nicht kompatibel mit einem Parameter vom Typ"LPWSTR"
(Unicode-Codierung)Sie können den Dateinamen auf
GetModuleFileName()
elegantere 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);
Ich hoffe es hilft!
quelle
GetCurrentDirectory () wird das aktuelle Verzeichnis , das ist , wo die exe aufgerufen wird , aus . Verwenden Sie GetModuleFileName (NULL ...), um den Speicherort der Exe abzurufen.
Wenn Sie das Handle für die Exe haben, können Sie es von GetCommandLine () ableiten, wenn Sie dies nicht tun.Wie Mr. Butterworth betont, brauchen Sie keinen Griff.
quelle
Warum erwägt hier niemand, 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;
quelle
Ich denke, der einfachste Weg, das aktuelle Verzeichnis zu finden, besteht darin, es aus den Befehlszeilenargumenten herauszuschneiden.
#include <string> #include <iostream> int main(int argc, char* argv[]) { std::string cur_dir(argv[0]); int pos = cur_dir.find_last_of("/\\"); std::cout << "path: " << cur_dir.substr(0, pos) << std::endl; std::cout << "file: " << cur_dir.substr(pos+1) << std::endl; return 0; }
Möglicherweise wissen Sie, dass jedes Programm seinen ausführbaren Namen als erstes Befehlszeilenargument erhält. Sie können dies also verwenden.
quelle
Codefragmente 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 templete CA2CAEX oder CA2AEX , die die interne API - Aufrufe :: MultiByteToWideChar oder :: WideCharToMultiByte .
quelle
Wenn Sie die Poco- Bibliothek verwenden, handelt es sich um einen Einzeiler , der meiner Meinung nach auf allen Plattformen funktionieren sollte.
quelle
Um das Verzeichnis zu finden, in dem sich Ihre ausführbare Datei befindet, können Sie Folgendes verwenden:
TCHAR szFilePath[_MAX_PATH]; ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
quelle
quelle