0

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

mauroaraujo
  • 332
  • 1
  • 10
  • 23
  • What sort of error are you getting? – Timo Geusch Jul 31 '14 at 23:55
  • It just doesn't create the specifyed folder... – mauroaraujo Aug 01 '14 at 02:05
  • Of course not, because you are not attempting to ask Windows to translate `CSIDL_APPDATA` into a real path. – Remy Lebeau Aug 01 '14 at 02:11
  • Oh, I'm confused now... I've asked before, how to get the %APPDATA% directory in another topic, and other user said that I could use CSIDL_APPDATA or CSIDL_LOCAL_APPDATA as ROOT of path... – mauroaraujo Aug 01 '14 at 02:22
  • What the other user said is correct, but you misread his answer. He did not tell you to *literally* put `"CSIDL_..."` in your path string directly. He told you to pass the desired `CSIDL` ID number to `SHGetSpecialFolderPath()`. Read my answer, it shows you how to use a `CSIDL` that way, albeit using `SHGetFolderPath()` instead (which replaces `SHGetSpecialFolderPath()`. – Remy Lebeau Aug 01 '14 at 02:27
  • Ok, now I understood the question, and sorry to trouble you. – mauroaraujo Aug 01 '14 at 02:33

2 Answers2

3

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);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Does this code needs a specific library or just with winbase.h it will works? Sorry, I'm learning it slowly, I'm still a newbie with C++ – mauroaraujo Aug 01 '14 at 02:16
  • `SHGetFolderPath()` and `SHGetKnownFolderPath()` are both in `Shell32.dll`, and `GetEnvironmentVariable()` is in the RTL itself and wraps the Win32 version in `kernel32.dll`. The RTL already links to both libraries for you. – Remy Lebeau Aug 01 '14 at 02:25
  • Hello, I'm here just to say that I've changed the latest code to works fine with my program... The first two options I don't know why it doesn't works the C++ builer says: Unknown command, this problems occurs with: SHGetKnownFolderPath; FOLDERID_RoamingAppData; CSIDL_APPDATA and SHGetFolderPathW. Thanks for your support! XD – mauroaraujo Aug 01 '14 at 23:00
  • You need to add `#include ` to your code to use those functions. – Remy Lebeau Aug 02 '14 at 03:26
  • Ah ok, was about that when I was asking if is needed to add a different library... So, thanks. – mauroaraujo Aug 02 '14 at 18:42
  • Remember that the term "library" has a particular meaning in C/C++, so the first thing I thought of was you asking which "import library" was needed. – Remy Lebeau Aug 02 '14 at 23:59
-1

i think this should help you out (=.

File NewDirectory.cpp

//includes standard libraries
#include <iostream>

//includes windows libraries
#include <windows.h>

//includes header files

int NewDirectory(){

    char *Directory = "C://Users/user/AppData/somefolder/";

    //Checks if folder of file exist
    int FilePath = PathFileExist(Directory);

    //Makes new directory
    int NewFolder = CreateDirectory(Directory, NULL);

    if(!FilePath){
        std::cout << "Error could not find folder, trying to create new Directory" << std::endl;

        NewFolder;

        if(!NewFolder){
            std::cout << "Could not make new directory closing" << std::endl;

            return 1;
        } else {
            std::cout << "New Directory" << Directory << "Created!" << std::endl;

            return 0;
        }
    } else {
        std::cout << "the Directory" << Directory << "already exist" << std::endl;

        return 0;
    }
}
daniel
  • 121
  • 9
  • Keep in mind that `CreateDirectory()` fails with an `ERROR_ALREADY_EXISTS` error if the directory already exists. Your example does not handle that case. – Remy Lebeau Aug 01 '14 at 01:12
  • He specifically wants to use the resolution of `%APPDATA%.` This code doesn't comply. – user207421 Aug 01 '14 at 01:29
  • i hate to tell you this code does comply, it creates a folder within the %appdata% directory, so yeah make sure you know what your talking about before insinuating something is false. – daniel Aug 01 '14 at 01:36
  • and @Remy lebeau my code does handle it if a directory exist already, if the directory already exist it outputs the directory is already there. – daniel Aug 01 '14 at 01:41
  • @Daniel: this code DOES NOT comply with the user's request, because you hard-coded the entire path instead of using `%APPDATA%` or `CSIDL_APPDATA`. The actual path may be different on different systems (`C:\Users\\AppData` is not the default on pre-Win7 systems), that is why `%APPDATA%` and `CSIDL_APPDATA` exist. And how many people do you know who have a username of `user`? – Remy Lebeau Aug 01 '14 at 02:00
  • @daniel: Also, your code DOES NOT handle the directory already existing, because `CreateDirectory()` returns 0 on all errors, including `ERROR_ALREADY_EXISTS`, so your code would display `"Could not make new directory closing"`. Try it and see for yourself. – Remy Lebeau Aug 01 '14 at 02:02
  • I've seen, I should use that just with console application, isn't it? (because os iostream...) I intent to use it with FireMonkey (Or VCL -> What it works with...) If it works with Firemonkey, thanks. I'm saying that, because I'm still a newbie with C++. Each day I learn a little more XD. – mauroaraujo Aug 01 '14 at 02:10
  • I've revised this code and yeah, it doesn't works with VCL or FireMonkey. However maybe part of the code is usefull for me, like the directory creation part, so thanks too... – mauroaraujo Aug 01 '14 at 02:14
  • i didnt fully test the code i was just giving input and making a example reference, and although i have a lot of experience im still learning all there is to know about win32 so @RemyLebeau thanks for your input to, cause as coders we are all learning something new every day. – daniel Aug 01 '14 at 02:23
  • @Daniel: Since nothing in your example actually addresses the user's request, you really should delete your answer. – Remy Lebeau Aug 01 '14 at 02:26