Create directory under local app data - visual-c++

I have application written in C/C++ and it needs to create a folder and file under the local app directory. When I call CreateDirectory the result is False and the directory is never created. What am I missing?
TCHAR szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL,CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath)))
{
PathAppend(szPath,_T("\\FredDir\\backupfirmware\\"));
bool result = CreateDirectory(szPath, NULL);
}
As near as I can tell this should work.

CreateDirectory can't create several levels worth of directories at once. You need to create them one by one - first FredDir, then backupfirmware under that.

Related

Deleting a file with I/O in progress: Is it a filesystem and/or an OS feature?

I'm writing a shell script that will run on Linux but can operate on files sitting on a mounted partition,
that may or may not have an ext* file-system. It could eg be NTFS, FAT32, or any inode- or non-inode-based system;
that could get further re-mounted on other boxes running non-Linux OSes like Windows or Mac.
Further, my script needs to be able to delete a file on this shared, arbitrarily formatted partition (even while the file's being read from or written to) by a remote process running on Linux, Windows, or Mac boxes
Questions:
Is the ability to be able to delete a file in use a feature of,
a. only the file-system?
b. or, only the OS?
c. or, a combo of both?
(Extension of Q1) Does it matter if the processe doing I/O on the file and the one deleting the file are both local or remote?
Does it matter if the processes doing I/O on the file and the one
deleting the file are both local or remote?
interesting - how remote system can access file (open, read-write data, delete) on windows direct ? really this impossible. we need some agent (LANMan server), running in the local system, which will be by remote commands (send say by Network Redirector) do local operations on file. so from file system view - all operations always local.
Is the ability to be able to delete a file in use a feature of
this is implemented of course by file system driver, but this driver written for concrete OS and based on it rules. while file system data on disk is have common format (as result drive formatted(and written files) in one OS, can be read from another OS) - how file system driver process requests, open, read, write, delete files - this is OS specific. different for different OS. based on it rules. so data format on disk is common and only depend from file system. but how this data read/write/delete - already os specific.
in windows we have next rules for delete files:
Normally a file marked for deletion is not actually deleted until all
open handles for the file have been closed and the link count for the
file is zero. When marking a file for deletion using
FILE_DISPOSITION_POSIX_SEMANTICS, the link gets removed from the
visible namespace as soon as the POSIX delete handle has been closed,
but the file’s data streams remain accessible by other existing
handles until the last handle has been closed.
so in general file will be not deleted, until the last handle to it will be closed. file became not accessible after we try delete it - can not more open it (we get error A non close operation has been requested of a file object with a delete pending. if try do this, after file marked to delete). but if file was already opened - we can still work with it by this handle. also file can not be deleted if section exist on file - will be error An attempt has been made to remove a file or directory that cannot be deleted.
begin from win10 redstone1 build exist FILE_DISPOSITION_POSIX_SEMANTICS flag which let removed file name from the visible namespace when delete handle has been closed, but the file’s data streams remain accessible by other existing handles until the last handle has been closed
windows code test demo: (FILE_DISPOSITION_POSIX_SEMANTICS supported by ntfs begin only from _WIN32_WINNT_WIN10_RS1. FileDispositionInfoEx information class also supported begin from _WIN32_WINNT_WIN10_RS1 only. in previous build we simply got not implemented error)
void print_error(PCSTR name)
{
PWSTR sz;
NTSTATUS status = RtlGetLastNtStatus();
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle(L"ntdll"), status, 0, (PWSTR)&sz, 0, 0))
{
DbgPrint("%s=%x\n%S\n", name, status, sz);
LocalFree(sz);
}
}
HANDLE OpenFile(PCWSTR lpFileName, DWORD dwDesiredAccess)
{
HANDLE hFile = CreateFileW(lpFileName, dwDesiredAccess, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
print_error("OpenFile");
return 0;
}
return hFile;
}
void ReadTest(HANDLE hFile)
{
if (hFile)
{
ULONG dwBytes;
if (ReadFile(hFile, &dwBytes, sizeof(dwBytes), &dwBytes, 0))
{
DbgPrint("ReadFile=OK\n");
}
else
{
print_error("ReadFile");
}
}
}
void DeleteTest(PCWSTR lpFileName)
{
HANDLE hFile1, hFile2, hFile3;
if (hFile1 = OpenFile(lpFileName, DELETE))
{
hFile2 = OpenFile(lpFileName, FILE_GENERIC_READ);
FILE_DISPOSITION_INFO_EX fdi = { FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS };
if (!SetFileInformationByHandle(hFile1, FileDispositionInfoEx, &fdi, sizeof(fdi)))
{
print_error("SetFileInformationByHandle");
}
// file already not accessible here (open must fail) but visible
if (hFile3 = OpenFile(lpFileName, FILE_GENERIC_READ))
{
CloseHandle(hFile3);
}
ReadTest(hFile2);
// win10 rs1: file removed from the visible namespace here
CloseHandle(hFile1);
// are file still visible ?
if (hFile3 = OpenFile(lpFileName, FILE_GENERIC_READ))
{
CloseHandle(hFile3);
}
// are possible create new file with this name &
hFile3 = CreateFileW(lpFileName, DELETE,
FILE_SHARE_VALID_FLAGS, 0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);
if (hFile3 == INVALID_HANDLE_VALUE)
{
print_error("CreateFile");
}
else
{
CloseHandle(hFile3);
DbgPrint("CreateFile OK\n");
}
ReadTest(hFile2);
if (hFile2)
{
CloseHandle(hFile2);
}
}
}
and output
OpenFile=c0000056
A non close operation has been requested of a file object with a delete pending.
ReadFile=OK
OpenFile=c0000034
Object Name not found.
CreateFile OK
ReadFile=OK
it depends how do you define filesystem and OS. Generally, I understand under filesystem the way how the data storage is organized on a device. OS is then responsible for the I/O of data and files. Particularly, if your script wants to delete a file it calls some utility like rm and provides name of the file. This utility is a program which makes an appropriate system call. This system call is a part of operating system which is executed in the privileged mode. It realizes what and how to do (e.g. which drivers should be used to mark HDD blocks as free on a particular drive or maybe some remote procedure should be called or samba server involved etc.)
So, to give an answer to your question 1, I would tend to the answer b.

How can I count the files inside a folder of project solution?

I want to develop a windows phone based application in which I need to put the number of files in a folder (this folder is already a part of the project) to a list so that at run time I can access those files. If anybody can give me idea of how to do that then it will be great help.
In normal WPF applications we can write code like
DirectoryInfo di = new DirectoryInfo("D:\\Tempo");
FileInfo[] fi = di.GetFiles("*", SearchOption.AllDirectories);
MessageBox.Show(fi.Length.ToString());
But Windows phone inside solution how do I do that?
I can get a single file access by this code
if (Application.GetResourceStream(new Uri("/WindowsPhone;component/Folder/file09.jpg", UriKind.Relative)) != null)
{
MessageBox.Show("Hi");
}
But inside that folder there are many files and I want to put them into list so at run time I can access those images. But the user won't be knowing about that so it should be a C# code, not a XAML code. Any help would be great.
It's pretty easy.
Make sure you add the specific folder to the Solution. Along with any files you want in that folder.
Make sure each file's Properties are set like so:
Build Action: Content
Copy to Output Directory: Do not copy
Make sure the application had loaded before calling
Lets say I had a folder called "Testfiles" and I want to read from it then:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
ReadAllFilesFromFolder("Testfiles");
}
// TODO: recursion to get subfolders and files (maybe?)
public async void ReadAllFilesFromFolder(string folder_name)
{
var package = Windows.ApplicationModel.Package.Current.InstalledLocation;
var assetsFolder = await package.GetFolderAsync(folder_name);
foreach (var file in await assetsFolder.GetFilesAsync())
{
// TODO: whatever you want to do with file
// string filename = file.Name;
}
}

UnauthorizedAccessException while scanning directory 'User\Documents\My Music'

Question: Why do I get this error while scanning a users 'My Documents' folder, but not when I scan the 'My Music/My Pictures/My Videos' directory?
Secondary, less important question: Is there a way to avoid this without having to specifically filter these folders out, or using a try/catch block?
I prefer answers that teach me how to fish, instead of just giving me fish. Just at this point I am not sure where I need to look to specifically answer this question. I've read through documents about elevating permissions and iterating through the file system, and spent a good week looking for why I can set DirectoryInfo on 'User\My Music' but not 'User\Documents\My Music'(link) and just would enjoy a little boost in a different direction in regards to learning more.
I catch the initial 'UnauthorizedAccessException' that is thrown initially when attempting Directory.GetFiles('path', "*", SearchOption.AllDirectories) where path is the users 'My Documents'. To handle the exception I know that I need to walk the directory manually. Which works, returning the files from the sub-directories.
The code for the initial GetFiles function:
public static string[] GetFiles(string path)
{
string[] files;
try
{
files = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
}
catch(UnauthorizedAccessException ex)
{ files = WalkDirectory(path); }
return files;
}
public static string[] WalkDirectory(string path)
{
List<string> files = new List<string>();
DirectoryInfo dir = new DirectoryInfo(path);
foreach (DirectoryInfo subDir in dir.GetDirectories())
{
try
{
files.AddRange(WalkDirectory(subDir.FullName));
}
catch(UnauthorizedAccessException ex)
{
// complete fail to walk directory listed
throw ex;
}
}
foreach (FileInfo file in dir.GetFiles())
{
files.Add(file.FullName);
}
}
This works out perfectly, until the code attempts to walk the hidden folders: My Music, My Pictures, or My Videos. No matter how I try and re-code to walk the hidden files, I keep receiving the UnauthorizedAccessException.
I understand completely that I am going to code around this. Mainly what I am curious to know, is why is the exception happening under a users folder?
An asssumption I am making is that the folder is a symlink to another directory, because I can make the path ?:\users directory\user\My (Music, Pictures, or Videos) and the code walks those directories then without any issues. This only happens when trying to scan the directory files after setting them from within the users My Documents.
OS: Windows 7
User Privliages: Administrator
Application Elevated to run as administrator
I was speaking about this with a friend, who is not technical, but knows enough tech to hold a conversation and he helped me narrow this question down further. This is actually a duplicate question and was answered at Check if a file is real or a symbolic link.
The folder is a symbolic link that was placed there for backwards compatibility purposes according to this article on TechRepublic: Answers to some common questions about symbolic links under the section Windows Vista and Windows 7 have built-in symbolic links paragraph 2.
In order to specifically avoid attempting to scan this directory without a Try/Catch block on an UnauthorizedAccessException the folder attributes need to be checked to determine if the folder or file in question is a symbolic link. Which again was answered in the above listed stackoverflow question.

While parsing into a root folder how can I distinguish the upcoming is whether a file or a folder in C language?

I want to parse through a root folder which is entered by the user by using multi threading and multi processing at different versions.But how can I distinguish while I am parsing through a root folder whether the next is a folder or a file?To summarize I want to learn how I can distinguish the upcoming is a file or a folder.I wanna learn this because if it is a folder then I let opening this folder to a dynamically thread and/or process.If it is a file the existing thread or process can continue its work without any necessarity to create any different thread and/or process.I hope I can express my problem.I am waiting your answers.Thank you.
You can check whether a path refers to a file or directory using the stat() function, and checking the st_mode field on the returned structure (see http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/stat.h.html).
On Windows, you can use GetFileAttributesEx to get the file attributes, which you can check to see if it is a file or a directory.
Note that whatever you use may be subject to a race condition if the file system is being updated by another thread or process at the same time, as the file/directory may be deleted and/or changed after you checked it and before you access it.
Here are some quick samples. It will be up to you to thread from multiple root locations, call these recursively, and sync all the data.
Under *nix systems;
struct dirent *entry;
while ((entry = readdir("/root")) != NULL)
{
if (entry->d_type == DT_DIR)
{
// do something
}
}
closedir(dir);
Under Windows:
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile(("C:\\root" + "*.*").c_str(), &findData);
do
{
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// do something
}
} while (FindNextFile(hFind, &findData));
FindClose(hFind);

How to check if Directory already Exists in MFC(VC++)?

How to check if Directory already Exists in MFC(VC++) ?
I am using below code to get current application Path and there i am creating NDSLog folder
so that all my Logfiles should place there , now i want to check the condition if NDSLog folder already exists dont create it .How to do that ?
Thanks.
char strPathName[_MAX_PATH];
::GetModuleFileName(NULL, strPathName, _MAX_PATH);
// The following code will allow you to get the path.
CString newPath(strPathName);
int fpos = newPath.ReverseFind('\\');
if (fpos != -1)
newPath = newPath.Left(fpos+1);
newPath += "NDSLog\\" ;
CreateDirectory(newPath,NULL);
The simplest way to check if a file/directory exists is to use GetFileAttributes:
if (GetFileAttributes(newPath) == INVALID_FILE_ATTRIBUTES) {
CreateDirectory(newPath,NULL);
}
Note that the function will return INVALID_FILE_ATTRIBUTES even if it fails due to some other reason, such as not having permissions to access the file, so you should check the return value of CreateDirectory to make sure that it succeeded.
Actually, you don't need to check whether the directory already exists; CreateDirectory will set an error code if the directory already exists:
if (!CreateDirectory(newPath,NULL)) {
if (GetLastError() == ERROR_ALREADY_EXISTS) {
// directory already exists
} else {
// creation failed due to some other reason
}
}
How about PathIsDirectory()? In the original example, you can use PathRemoveFilespec() followed by PathCombine() to add a new filename/extension. In the unlikely case that your target is only Windows 8 or later, there are safer PathCch...() flavors of these functions.
I use PathFileExists.
FindFirstFile. Despite the "File" in the name, it'll find directories perfectly well.
You can use _accees or _waccess from C runtime.
This is the msdn page and you can see sample usage
And also you don't have to wory about if directory already exist because CreateDirectory checks and returns ERROR_ALREADY_EXISTS if exists. You can see from here (Return Codes).
I must note, that GetFileAttributes work slow when file is a network path.
Actually, it works slow for the first time, and fast afterwards.

Resources