【问题标题】:How to get Current Directory?如何获取当前目录?
【发布时间】:2010-10-26 21:22:58
【问题描述】:

我一直在 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++ 中使其更容易?

【问题讨论】:

标签: c++ windows


【解决方案1】:

我建议您在进一步学习之前阅读一本有关 C++ 的书,因为这有助于站稳脚跟。 Koenig 和 Moo 的 Accelerated C++ 非常棒。

要获取可执行路径,请使用GetModuleFileName:

TCHAR buffer[MAX_PATH] = { 0 };
GetModuleFileName( NULL, buffer, MAX_PATH );

这是一个获取没有文件名的目录的 C++ 函数:

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

std::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";
}

【讨论】:

  • 注意您可能需要使用宽字符,例如 wchar_t buffer[MAX_PATH];这些天...
  • GetModuleFileNameA
  • 重申@Mikhail 所说的,您将使用GetModuleFileNameA 用于使用多字节字符集的代码,而GetModuleFileNameW 用于unicode。 GetModuleFileName(没有AW)实际上是项目设置使用的任何字符集的别名,这是大多数使用字符串的Win32 API 方法的设置方式。因此,如果您有一个 unicode 项目,并且您的字符串也是 unicode,那么您只需调用GetModuleFileName。如果您的项目是多字节并使用多字节字符串,则同样适用。
  • 我不喜欢该参数或find_last_of() 方法,是不是有一些常量定义了目录名称中的分隔符,例如“.../.../...”还是“...\...\...”?
  • 这只是 Windows
【解决方案2】:

我想,找到当前目录最简单的方法是从命令行参数中剪切它。

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

您可能知道每个程序都将其可执行名称作为第一个命令行参数。所以你可以使用它。

【讨论】:

    【解决方案3】:

    如果您使用的是 Poco 库,它是单行的,它应该适用于我认为的所有平台。

    Poco::Path::current()
    

    【讨论】:

      【解决方案4】:

      这个问题不清楚是想要当前工作目录还是包含可执行文件的目录的路径。

      大多数答案似乎都回答了后者。

      但是对于前者,以及关于创建文件问题的第二部分,C++17 标准现在合并了文件系统库,这大大简化了这一点:

      #include <filesystem>
      #include <iostream>
      
      std::filesystem::path cwd = std::filesystem::current_path() / "filename.txt";
      std::ofstream file(cwd.string());
      file.close();
      

      这会获取当前工作目录,将文件名添加到路径并创建一个空文件。请注意,路径对象负责处理依赖于操作系统的路径,因此 cwd.string() 返回一个依赖于操作系统的路径字符串。尼托。

      【讨论】:

      • 我们如何使用 库来获取包含可执行文件的目录的路径?
      • afaik 没有直接的方法来做到这一点。对不起。请参阅该部分问题的其他答案。
      【解决方案5】:

      一个简单的方法是:

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

      argv[] 几乎是一个包含运行 .exe 的参数的数组,但第一个始终是可执行文件的路径。如果我构建它,控制台将显示: C:\Users\Ulisse\source\repos\altcmd\Debug\currentdir.exe

      【讨论】:

      • 简洁的最佳答案。
      【解决方案6】:

      为什么这里没有人考虑使用这个简单的代码?

      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;
      

      【讨论】:

        【解决方案7】:

        请不要忘记在使用它们之前将缓冲区初始化为something。同样重要的是,为结尾的 null 提供字符串缓冲区空间

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

        Reference

        【讨论】:

          【解决方案8】:
          #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。我发现这项工作非常好。 刚刚在 Windows 上测试过,还没有在 Linux 上尝试过 :)

          【讨论】:

            【解决方案9】:

            我的 CAE 项目中的代码 sn-ps 与 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);
            }
            

            只需使用模板 CA2CAEXCA2AEX 调用内部 API ::MultiByteToWideChar::WideCharToMultiByte

            【讨论】:

              【解决方案10】:
              String^ exePath = Application::ExecutablePath;<br>
              MessageBox::Show(exePath);
              

              【讨论】:

                【解决方案11】:

                您可以用更优雅的方式从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);
                

                希望对你有帮助!

                【讨论】:

                  【解决方案12】:
                  #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);
                  }
                  

                  【讨论】:

                  • currentDir - "char *" 类型的参数与 "LPWSTR" 类型的参数不兼容(Unicode 编码)
                  【解决方案13】:
                  WCHAR path[MAX_PATH] = {0};
                  GetModuleFileName(NULL, path, MAX_PATH);
                  PathRemoveFileSpec(path);
                  

                  【讨论】:

                    【解决方案14】:

                    恕我直言,这里是对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( "\\/" ));
                    }
                    

                    【讨论】:

                    • 这其实是不一样的。你不提供目录路径,你提供文件的路径,包括文件。
                    【解决方案15】:

                    GetCurrentDirectory() 获取当前目录,它是调用 exe 的位置。要获取 exe 的位置,请使用 GetModuleFileName(NULL ...)。 如果你有 exe 的句柄,或者如果你没有,你可以从 GetCommandLine() 派生它。

                    正如巴特沃思先生所指出的,您不需要把手。

                    【讨论】:

                    • 其实你不需要一个真正的句柄——一个NULL句柄获取可执行文件名,带路径。
                    【解决方案16】:

                    要查找可执行文件所在的目录,您可以使用:

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

                    【讨论】:

                      【解决方案17】:

                      您应该提供一个有效的缓冲区占位符。 那就是:

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

                      【讨论】:

                        【解决方案18】:

                        GetCurrentDirectory 不会为结果分配空间,这取决于您。

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

                        此外,如果您想以 C++ 方式执行此操作,请查看 Boost.Filesystem 库。

                        【讨论】:

                        • 嗯,NPath指向另一个目录,如何让它显示可执行文件所在的目录?
                        • 当前目录与可执行文件的目录不一样,即使在C#和Delphi下也是如此。也许你可以让你的问题更清楚?
                        • 约翰,这有点牵涉,不能简单地在评论中回答。也许你应该听从 Neil 的建议(两者都是)。
                        猜你喜欢
                        • 2010-11-11
                        • 2013-01-29
                        • 2016-04-05
                        • 2019-02-18
                        • 2012-12-12
                        • 1970-01-01
                        • 1970-01-01
                        • 2016-08-20
                        相关资源
                        最近更新 更多