c++directoryfiremonkeyappdatac++builder-xe6

How to create a new folder in %APPDATA% using C++?


I've tried to include the IOUtils library and use the CSIDL command, but it isn't working...

Here is the part of the code that does it:

//------------------- Includes -----------------------
#include <fmx.h>
#include <IOUtils.hpp>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
#include "Unit3.h"
//---------------------- end  ------------------------
//---- On Form Show (bugged event: It doesn't create the needed folder) ----

void __fastcall TfrmInicio::FormShow(TObject *Sender)
{
    if (TDirectory::Exists("CSIDL_APPDATA\\Nintersoft\\Ninterfin")) {
        if (FileExists("CSIDL_APPDATA\\Nintersoft\\Ninterfin\\Inf.nf")) {
            mmInfo->Lines->LoadFromFile("CSIDL_APPDATA\\Nintersoft\\Ninterfin\\Inf.nf");
        }
    }
    else {
            TDirectory::CreateDirectory("CSIDL_APPDATA\\Nintersoft\\Ninterfin");
    }
}

//--------------------------------- end ------------------------------------

I hope you can helpe me... Thanks a lot XD


Solution

  • You are not supposed to hard-code "CSIDL_APPDATA" itself directly into your directory path string. CSIDL_APPDATA is an ID number (specifically, 26) for a virtual folder that you have to resolve dynamically at runtime using the Win32 API, eg:

    void __fastcall TfrmInicio::FormShow(TObject *Sender)
    {
        WCHAR szPath[MAX_PATH+1] = {0};
        if (SUCCEEDED(SHGetFolderPathW(FmxHandleToHWND(Handle), CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, szPath)))
        {
            String DirPath = TPath::Combine(szPath, L"Nintersoft\\Ninterfin");
            TDirectory::CreateDirectory(DirPath);
    
            String FileName = TPath::Combine(DirPath, L"Inf.nf");
            if (TFile::Exists(FileName))
                mmInfo->Lines->LoadFromFile(FileName);
        }
    }
    

    Alternatively, on Vista and later only, use SHGetKnownFolderPath() instead:

    void __fastcall TfrmInicio::FormShow(TObject *Sender)
    {
        PWSTR pszPath;
        if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pszPath)))
        { 
            String DirPath = TPath::Combine(pszPath, L"Nintersoft\\Ninterfin");
            CoTaskMemFree(pszPath);
    
            TDirectory::CreateDirectory(DirPath);
    
            String FileName = TPath::Combine(DirPath, L"Inf.nf");
            if (TFile::Exists(FileName))
                mmInfo->Lines->LoadFromFile(FileName);
        }
    }
    

    Alternatively, use Sysutils::GetEnvironmentVariable() to retrieve the value of %APPDATA% instead of using a CSIDL or KNOWNFOLDERID:

    void __fastcall TfrmInicio::FormShow(TObject *Sender)
    {
        String DirPath = TPath::Combine(Sysutils::GetEnvironmentVariable(L"APPDATA"), L"Nintersoft\\Ninterfin");
        TDirectory::CreateDirectory(DirPath);
    
        String FileName = TPath::Combine(DirPath, L"Inf.nf");
        if (TFile::Exists(FileName))
            mmInfo->Lines->LoadFromFile(FileName);
    }