【问题标题】:WinAPI - Create .ini file if it doesn't exist [duplicate]WinAPI - 如果.ini文件不存在则创建它[重复]
【发布时间】:2012-10-02 02:03:55
【问题描述】:

可能重复:
c++ how to create a directory from a path

我正在尝试在应用程序数据文件夹中创建一个 .ini 文件,以便我可以使用设置。我试了一下,但我不知道如何检查它是否已经存在,如果不存在,则创建子目录和 .ini 文件。

当我收到最后一条错误消息时,它显示“系统找不到指定的路径。”

#include <string>
using namespace std;

#include <Windows.h>
#include <Shlwapi.h>
#include <ShlObj.h>
#pragma comment(lib, "shlwapi.lib")

namespace Settings
{
    CIni        Ini;
    bool        Available = false;
    char        Directory[MAX_PATH];
    const char *IniFileName = "Settings.ini";

    void CheckError() {
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
        DWORD dw = GetLastError(); 

        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, dw,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR)&lpMsgBuf, 0, NULL
        );

        string msg = (LPTSTR)lpMsgBuf;
        Error(msg); // MessageBox
    }

    void Initialize() {
        // Get AppData directory
        if (SHGetFolderPath(0, CSIDL_COMMON_APPDATA, 0, 0, Directory) >= 0) {
            string fullpath;
            string subDir = "\\MyCompany\\MyProgram\\1.0\\";

            PathAppend(Directory, subDir.c_str());
            fullpath = Directory;
            fullpath += IniFileName;

            // If directory doesn't exist, create it.
            DWORD attrib = GetFileAttributes(Directory);
            if (!(attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY))) {

                if (CreateDirectory(Directory, NULL)) {
                    HANDLE file = CreateFile(
                        fullpath.c_str(), GENERIC_WRITE, 0, 0,
                        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
                    );

                    if (file != INVALID_HANDLE_VALUE) {
                        CloseHandle(file);
                    } else {
                        CheckError();
                        return;
                    }
                } else {
                    CheckError();
                    return;
                }
            }

            Ini.SetPathName(fullpath.c_str());
            Available = true;
        }
    }
}

我检查了一下,我对CreateDirectory() 的调用返回错误。 如何检查文件和目录是否存在,如果不存在则创建它们?

【问题讨论】:

    标签: c++ winapi file-io settings ini


    【解决方案1】:
    if (SHCreateDirectoryEx(NULL, Directory, NULL) || 
        GetLastError() == ERROR_ALREADY_EXISTS) 
       {
       HANDLE file = CreateFile(
          fullpath.c_str(), GENERIC_WRITE, 0, 0,
          CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
    
       if (file != INVALID_HANDLE_VALUE) 
         {
         CloseHandle(file);
         } 
         else if (GetLastError() != ERROR_FILE_EXISTS) 
           {
           CheckError();
           return;
           }
       } 
       else 
       {
       CheckError();
       return;
       }
    

    【讨论】:

    • 花了我一段时间看看你做了什么改变,所以基本上我只需要使用CREATE_NEW?因为 CreateDirectory 是返回 false 并且在您的代码中没有更改。
    • 另一个变化是在尝试创建目录后检查 GetLastError() == ERROR_ALREADY_EXISTS。我刚刚用SHCreateDirectoryEx替换了CreateDirectory
    • +1 例如代码和CREATE_NEW 更正。但我希望它适用于旧版本的 Windows。所以我一次只做一个子目录。
    • @BrandonMiller: 早于 Win2000?
    • 我认为 SHCreateDirectoryEx 是 XP SP2 或更高版本,我在 Frédéric 建议的可能副本中看到了这一点。
    【解决方案2】:

    您需要一次创建一层子文件夹。

    即创建“MyCompany”,然后创建“MyProgram”,然后创建“1.0”。您可以编写一个函数来执行此操作,类似于 VCL 的 ForceDirectories。

    此外,请注意,除非以管理员权限运行,否则常见的应用程序数据在 windows7 上是不可写的。除非您的应用程序安装程序创建一个子文件夹并在其上设置适当的安全 ACL 以允许访问。尽可能避免使用用户应用数据文件夹。

    【讨论】:

    • 如何获取用户 AppData 文件夹?因为我想避免获得管理员权限。
    • 哦,CSIDL_APPDATA 还是 CSIDL_APPDATA_LOCAL?还是两者都行?
    • CSIDL_APPDATA。那就是与漫游配置文件一起使用的那个。
    • CSIDL_APPDATA +1,我试图不要求提升。
    猜你喜欢
    • 2014-07-20
    • 2017-11-22
    • 2016-01-22
    • 2020-07-12
    • 1970-01-01
    • 2022-01-11
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多