How can i create a dir in Documents folder? [C++] - c++

Im trying to create a directory , or a subdirectory in the Documents folder.
PWSTR ppszPath; // variable to receive the path memory block pointer.
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &ppszPath);
std::wstring myPath;
if (SUCCEEDED(hr)) {
myPath = ppszPath; // make a local copy of the path
}
const wchar_t* str = myPath.c_str();
_bstr_t b(str);
int status = _mkdir(b+"\\New");
As you can see , I'm trying to create a new folder named "New" in Documents Folder.
The path to the documents is correct but the dir is not created.

This is using _bstr_t to avoid using Unicode, the new path is converted to ANSI and will be invalid unless the original path was ANSI, (or ASCII to be guaranteed)
Just pad L"\\New" and wide string functions to solve the problem.
You also have to free ppszPath as stated in documentation
std::wstring myPath;
wchar_t *ppszPath;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &ppszPath);
if (SUCCEEDED(hr))
{
myPath = ppszPath;
CoTaskMemFree(ppszPath);
}//error checking?
myPath += L"\\New";
std::filesystem::create_directory(myPath)
//or _wmkdir(myPath.c_str());

The std::filesystem::path class understands Unicode just fine, so you don’t need to mess with any helpers there. Also, you need to check both function results to determine success or failure:
bool success = false;
PWSTR documents_path = nullptr;
if (SUCCEEDED( SHGetKnownFolderPath( FOLDERID_Documents, 0, NULL, &documents_path ) ))
{
using namespace std::filesystem;
success = create_directory( path{ documents_path } / "new_folder" );
CoTaskMemFree( documents_path );
documents_path = nullptr;
}
The result of the operation is indicated in the variable success.
I would personally separate the functions of obtaining the user’s Documents folder and the directory creation into two separate functions, but the above will do just fine.

Related

How can I give an old ActiveX control new GUIDs?

I am trying to modify an ActiveX control developed in Visual Studio 2008 to use it for a purpose for which it was not originally designed. I will be reusing at least 90% of its code. Therefore, I would like to begin by creating an identical control that uses different GUIDs. I tried to follow instructions I found here (a very old link, written in 2004), but when I tried to build my project, I got an assertion failure in ctlreg.cpp line 113. Then, I restored all my changed files back to their original states, and for each GUID is the .odl file, I searched for the GUID in my .cpp and .h files and changed it wherever I found it. I also made sure to change my major version number. I still get the assertion failure. What else should I be doing?
Here's the code from ctlreg.cpp from the start of the method containing the assertion to the assertion itself:
BOOL AFXAPI AfxOleRegisterTypeLib(HINSTANCE hInstance, REFGUID tlid,
LPCTSTR pszFileName, LPCTSTR pszHelpDir)
{
BOOL bSuccess = FALSE;
CStringW strPathNameW;
wchar_t *szPathNameW = strPathNameW.GetBuffer(_MAX_PATH);
::GetModuleFileNameW(hInstance, szPathNameW, _MAX_PATH);
strPathNameW.ReleaseBuffer();
LPTYPELIB ptlib = NULL;
// If a filename was specified, replace final component of path with it.
if (pszFileName != NULL)
{
int iBackslash = strPathNameW.ReverseFind('\\');
if (iBackslash != -1)
strPathNameW = strPathNameW.Left(iBackslash+1);
strPathNameW += pszFileName;
}
if (SUCCEEDED(LoadTypeLib(strPathNameW.GetString(), &ptlib)))
{
ASSERT_POINTER(ptlib, ITypeLib);
LPTLIBATTR pAttr;
GUID tlidActual = GUID_NULL;
if (SUCCEEDED(ptlib->GetLibAttr(&pAttr)))
{
ASSERT_POINTER(pAttr, TLIBATTR);
tlidActual = pAttr->guid;
ptlib->ReleaseTLibAttr(pAttr);
}
// Check that the guid of the loaded type library matches
// the tlid parameter.
ASSERT(IsEqualGUID(tlid, tlidActual));

Accessing files in resources folder in mac osx app bundle

I would like to access files which are inside Resources in app bundle. Unfortunately i cannot use QT resorces, as i'm using CascadeClassifier from opencv. My current paths are
const std::string FACE_CLASIFIER_PATH = "/Resources/haarcascade_frontalface_default.xml";
const std::string EYES_CLASIFIER_PATH = "/Resources/haarcascade_mcs_eyepair_big.xml";
I also tried
const std::string FACE_CLASIFIER_PATH = "../Resources/haarcascade_frontalface_default.xml";
const std::string EYES_CLASIFIER_PATH = "../Resources/haarcascade_mcs_eyepair_big.xml";
But nether of them work. As for config both files are present inside MyApp.app/Contents/Resources, i include them using qmake
mac {
APP_XML_FILES.files = ../haarcascade_frontalface_default.xml ../haarcascade_mcs_eyepair_big.xml
APP_XML_FILES.path = Contents/Resources
QMAKE_BUNDLE_DATA += APP_XML_FILES
}
I would appreciate any help with this issue
You don't say what you want to do with the files, though that could be due to my lack of knowledge of opencv. However you can use the Core Foundation classes to get paths to files in the resources folder: -
CFURLRef appUrlRef;
appUrlRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("somefile"), NULL, NULL);
// do something with the file
//...
// Ensure you release the reference
CFRelease(appUrlRef);
With a CFURLRef, you can use Apple's documentation to get what you need from it.
For example, if you want a file path: -
CFStringRef filePathRef = CFURLCopyPath(appUrlRef);
// Always release items retrieved with a function that has "create or "copy" in its name
CFRelease(filePathRef);
From the file path, we can get a char* to the path: -
const char* filePath = CFStringGetCStringPtr(filePathRef, kCFStringEncodingUTF8);
So, putting it all together, if you want to get a char* path to haarcascade_mcs_eyepair_big.xml: -
CFURLRef appUrlRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("haarcascade_mcs_eyepair_big.xml"), NULL, NULL);
CFStringRef filePathRef = CFURLCopyPath(appUrlRef);
const char* filePath = CFStringGetCStringPtr(filePathRef, kCFStringEncodingUTF8);
// Release references
CFRelease(filePathRef);
CFRelease(appUrlRef);

CopyFiles using IFileOperation (C++)

I want to copy multiple files using IFileOperation.
Copy a single file is not a problem like this example:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb775761%28v=vs.85%29.aspx
My Problem is that I don't find a way to copy multiple files like *.txt.
I have tried using SHCreateShellItemArrayFromIDLists, like this snippet:
IShellItem *psiTo = NULL;
HRESULT hr = SHCreateItemFromParsingName( csTarget, NULL, IID_PPV_ARGS(&psiTo) );
LPCITEMIDLIST pidlFiles = ILCreateFromPath(csSource);
UINT count = sizeof(pidlFiles);
IShellItemArray* psiaFiles = NULL;
hr = SHCreateShellItemArrayFromIDLists(count, &pidlFiles, &psiaFiles);
hr = pfo->CopyItems(psiaFiles, psiTo);
hr = pfo->PerformOperations();
A other way is to use SHCreateShellItemArray, like this:
LPCITEMIDLIST pidlParent = ILCreateFromPath(_T("C:\\"));
LPCITEMIDLIST pidlChild = ILCreateFromPath(_T("C:\\Temp\\*.txt"));
HRESULT hr = SHCreateShellItemArray(pidlParent, NULL, 1, &pidlChild, &psiaFiles);
hr = pfo->CopyItems(psiaFiles, psiTo);
hr = pfo->PerformOperations();
I tried different way but almost I get E_INVALIDIDARG or ERROR_PATH_NOT_FOUND.
Whats wrong?
ILCreateFromPath doesn't take wildcards. Couldn't, since it returns a single PIDLIST_ABSOLUTE.
The easiest solution is to enumerate all files manually FindFirstFile(*.txt), call CopyItem on each result, and then call PerformOperations once at the end.
As usual, the older Windows functions are better. SHFileOperation is ten times simpler and more capable to boot: it does support wildcards directly.

SymEnumSourceFiles get incomplete file names

I was tring to use SymEnumSourceFiles to get the file name within the debugging module.But the file name as a parameter in the callback function seems incomplete. e.g. A file named"c:\program files\test\test.cpp" only showed "c:\program fi" in the FileName part of the PSOURCEFILE type parameter, and that's very wired.
Here is my code:
struct foo
{
static BOOL CALLBACK run( PSOURCEFILE pSourceFile, PVOID UserContext)
{
static TCHAR szFileName[MAX_PATH] = _T("");
if (_tcscmp(szFileName, pSourceFile->FileName))
{
_tcscpy(szFileName, pSourceFile->FileName);
}
return TRUE;
}
};
HANDLE hCurrentProcess = GetCurrentProcess();
SymInitialize(hCurrentProcess, NULL, FALSE);
DWORD64 BaseOfDll = SymLoadModule64(hCurrentProcess,
NULL,
(LPCSTR)_bstr_t(lpszFile),
NULL,0,0);
if(!SymEnumSourceFiles(hCurrentProcess, BaseOfDll, NULL, foo::run, (PVOID)pCallBack))
{
ATLTRACE(_T(__FUNCTION__) _T(" error:0x%x\n"), GetLastError());
}
SymUnloadModule64(hCurrentProcess, BaseOfDll);
SymCleanup(hCurrentProcess);
Can anyone tell me where I go wrong please?
PS. When I simply replace SymEnumSourceFiles with SymEnumLines and change the callback function, the file name I got is correct.
There used to be a bug with SymEnumSymbols where symbol name was not zero terminated, maybe this one is related. Try zeroing out the filename after copying it (pSourceFile->FileName[0] = 0;).
Try ANSI version of SymEnumSourceFiles. There seems to be a bug in SymEnumSourceFilesW function.

C++ iterating through files and directories

I'm working on a C++ program that will automatically backup my work to my FTP server. So far I am able to upload a single file, by specifying a file name using this
CString strFilePath = szFile ;
int iPos = strFilePath.ReverseFind('\\');
CString strFileName = strFilePath.Right((strFilePath.GetLength()- iPos-1) );
CString strDirPath = m_szFolderDroppedIn ;
strDirPath = strDirPath.Mid(0,strDirPath.GetLength() - 1);
int iPost = strDirPath.ReverseFind('\\');
CString strDirName = strDirPath.Right((strDirPath.GetLength()- iPost -1) );
bool curdir = ftpclient.SetServerDirectory((char*)strDirName.GetBuffer(strDirName.GetLength()));
//Upload to Server
int uploadret = ftpclient.PutFile(szFile,(char*)strFileName.GetBuffer(strFileName.GetLength()),0,true,dwLastError);
m_lsDroppedFiles.RemoveAll();
break;
}
Now I want to be able to iterate through a directory (Which contains subdirectories) and recursively call. I'm having a problem getting a hold of the files in the directory.
Any help or code snippet...
Since you are using MFC, you can use the CFileFind class. Example code is given in MSDN. Alternatively, you can use boost.filesystem for the same.
#Swapnil: If you use boost::filesystem, there is a recursive_directory_iterator