web-dev-qa-db-ja.com

現在のディレクトリを取得する方法は?

私はこれをC#とDelphiで行ってきましたが、C++は悪です。目的は、現在のディレクトリ(実行可能ファイルが実行されている場所)にファイルを作成することです。

私のコード:

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

GetCurrentDirectory()で例外が発生します。

なぜ例外が発生するのか、そしてC++でそれをどのように簡単にするのか教えてください。

53
Ivan Prodanov

しっかりと足を踏み入れると役立つので、先に進む前にC++に関する本を読むことをお勧めします。 Accelerated C++ Koenig and Mooによる素晴らしい。

実行可能パスを取得するには、 GetModuleFileName を使用します。

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

ファイル名なしでディレクトリを取得するC++関数は次のとおりです。

#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";
}
111
anon

GetCurrentDirectoryは結果にスペースを割り当てません。それはあなた次第です。

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

また、これをC++の方法で実行する場合は、 Boost.Filesystem ライブラリをご覧ください。

36
avakar

私見は 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( "\\/" ));
}
11
cdiggins

現在の作業ディレクトリが必要なのか、実行可能ファイルを含むディレクトリのパスが必要なのかは不明です。

ほとんどの答えは後者に答えているようです。

しかし、前者、およびファイル作成の質問の2番目の部分では、C++ 17標準にファイルシステムライブラリが組み込まれているため、これが大幅に簡素化されます。

#include <filesystem>
#include <iostream>

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

これにより、現在の作業ディレクトリが取得され、ファイル名がパスに追加され、空のファイルが作成されます。パスオブジェクトがOS依存のパス処理を処理するため、cwd.string()はOS依存のパス文字列を返すことに注意してください。ネイト。

6
Rasmus Dall

有効なバッファープレースホルダーを指定する必要があります。あれは:

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

使用する前に、バッファをsomethingに初期化することを忘れないでください。同様に重要なのは、文字列バッファに終了null用のスペースを与えることです

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

参照

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

GetModuleFileNameを正しく使用できませんでした。私はこの作品を非常によく見つけました。 Linuxでまだ試していない、Windowsでテスト済み

4
MsLate

より洗練された方法で、GetModuleFileName()からファイル名を削除できます。

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

それが役に立てば幸い!

3
ProXicT
#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
freezotic

GetCurrentDirectory()は、exeが呼び出される現在のディレクトリを取得しますfrom。 exeの場所を取得するには、GetModuleFileName(NULL ...)を使用します。 exeのハンドルを持っている場合、または持っていない場合はGetCommandLine()から派生させることができます。

バターワース氏が指摘するように、ハンドルは必要ありません。

2
nickd
WCHAR path[MAX_PATH] = {0};
GetModuleFileName(NULL, path, MAX_PATH);
PathRemoveFileSpec(path);
2
Zhi Wang

なぜこの単純なコードの使用を検討する人がいないのですか?

TCHAR szDir[MAX_PATH] = { 0 };

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

またはさらにシンプル

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

これを行う簡単な方法は次のとおりです。

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

argv[]はほとんど.exeを実行した引数を含む配列ですが、最初の引数は常に実行可能ファイルへのパスです。これをビルドすると、コンソールにC:\Users\Ulisse\source\repos\altcmd\Debug\currentdir.exeと表示されます

1
user5736737

Poco ライブラリを使用している場合、これは1つのライナーであり、私が考えるすべてのプラットフォームで動作するはずです。

Poco::Path::current()
0

Unicode開発環境を使用したCAEプロジェクトのコードスニペット:

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

内部APIを呼び出すテンプレートCA2CAEXまたはCA2AEXを使用するだけです:: MultiByteToWideCharまたは:: WideCharToMultiByte

0
user3782257