Checking if a Folder/File is Hidden/System in Windows C/C++ - windows

I am writing a Cross platform application using C++/STL/Boost and I realized they do not provide a way to check if a folder or file is hidden or is a system file in Windows.
What's the simplest way to do this in C/C++ for Windows ?
Ideally I have a std::string with the path (either to a file or folder), and would return if it's hidden or is a system file. best if it works across all windows versions. I am using MinGW g++ to compile this as well.

GetFileAttributes will work for this.
It takes a path to either a file or a directory as a parameter and returns set of flags including FILE_ATTRIBUTE_HIDDEN and FILE_ATTRIBUTE_SYSTEM.
DWORD attributes = GetFileAttributes(path);
if (attributes & FILE_ATTRIBUTE_HIDDEN) ...
if (attributes & FILE_ATTRIBUTE_SYSTEM) ...

Related

Haskell Directory creates invalid symlink on Windows

This year System.Directory was updated to include createFileLink and createDirectoryLink actions, and for me on Windows 10 both work fine for relative paths.
When I use either on an absolute path (of about 50 character length, so I suppose in unicode it exceeds 260) it prepends \\?\ (i.e. "\\\\?\\") to the paths, which can be seen from DIR as follows
<SYMLINKD> source [\\?\T:\Code\hLink\binaries\dest]
<SYMLINK> source.txt [\\?\T:\Code\hLink\binaries\dest\source.txt]
The directory link works fine, but the file link doesn't do anything, it doesn't even say that the target file is missing.
When I create a file link using MKLINK without \\?\ in the absolute path it works fine as well, and when I create either link using MKLINKwith \\?\ it has the same result.
Is this a Windows problem? Can I make Haskell use short path format instead? (Using Win10 so apparently I can enable long paths via registry)
Should the Windows api be passing the \\?\ header to symlinks at all?
References:
MaxPath and the meaning of \\?\, plus disabling path limitations on Win10
https://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
Changelog reporting the addition of \\?\ to win32 calls https://hackage.haskell.org/package/directory-1.3.1.1/changelog

QFile::copy returns true even though copy failed in Windows

I have QString variable named "src", which holds a filename. Operation QFile::copy(src, target) works Ok, until target is "C:" or "C:/" (I have the problem in Windows 10). In this case the operation returns true, even though I do not see any files actually copied to C:/ (in fact, normally I cannot copy anything to C:/ without administrator rights). Moreover, when I debug, I see that it says it has copied to C:// (two slashes). Is it a Qt bug or do I miss something?
UPD: Copying, e.g., to C:/Users which also requires administrator rights fails, as it should (returns false). Qt version is 5.7.
UPD:
QString src = "C:/Stuff/somefile.pdf";
QString target = "C:/somefile.pdf";
if (QFile::copy(src, target)) qDebug() << "Copy successful";
else qDebug() << "Copy failed";
This code yields "Copy succeful", whereas neither do I have write access to C:/ nor actually file somefile.pdf appears there.
When your application does not have permissions for writing to some directories, the files are stored into the Windows Virtual Store located at C:\Users\%USERNAME%\AppData\Local\VirtualStore. So in fact your file is successfully saved (albeit the path is redirected), that is why QFile::copy() returns true.
This redirection is called UAC Virtualization, and it works for C:, C:\Program Files, C:\Windows and HKLM\Software.
I guess the most genuine way to avoid such problems is to stick to saving configuration data in the designated locations such as application data (which in the context of the Qt framework will also meet the terms of cross-platform code).

Processing 3.0 launch() function doesn't launch my .exe

Processing 3.0 launch function doesn't launch my .exe.
I am using the Launch() function (https://processing.org/reference/launch_.html)
launch("C:/Program Files (x86)/Google/Chrome/Application/chrome.exe");
Or
launch("C:/app/keyboard.exe");
Result: Chrome browser will open. keyboard.exe will not. I've tryed different locations and relative paths.
I only get a windows loader when the link is correct. So that is correct.
The function discriptions says this:
"Be sure to make the file executable before attempting to open it (chmod +x). "
https://superuser.com/questions/106181/equivalent-of-chmod-to-change-file-permissions-in-windows
I also made a .bat file to execute the .exe but the launch() function only works on exe files.
but that didnt work either.
System:
Processing 3.0
Java 8
Windows 10, 64 bit
So what am I missing?
It is a bit dodgy but works in windows 8:
PrintWriter output=null;
output = createWriter("myfile.bat");
output.println("cd "+sketchPath(""));
output.println("start archivo.exe");
output.flush();
output.close();
output=null;
launch(sketchPath("")+"myfile.bat");
And you can choose another relative or absolute path
for instance
output.println("cd ..");
output.println("cd directoriy");
...
As Samuil advises, Windows uses \ instead of a / as a separator character, which you'll need to escape, hence \\: launch("C:\\app\\keyboard.exe");
I recommend using File.separator:
launch("C:"+File.separator+"app"+File.separator+"keyboard.exe");
It's a bit longer, but will work regardless of the operating system(Linux/OSX/Windows/etc.).
Aside launch(), also try exec():
exec(new String[]{"start","C:"+File.separator+"app"+File.separator+"keyboard.exe");
also Process. (If you need to check the output, you may need to write your own thread that will pipe the output)

Trying to open a file in C++, but the file cannot be found

I have an algorithm in C++ (main.cpp) and I use CLion to compile and run it. Algorithm would read strings from text file, but there is a mistake:
Could not open data.txt (file exists and placed in one folder with main.cpp)
How can I fix it and make this file "visible" to CLion?
If you are using fopen or something similar and just passing "data.txt", it is assumed that that file is in the current working directory of the running program (the one you just compiled).
So, either
Give a full path instead, like fopen("/full/path/to/data.txt"), where you use the actual full path
(not preferable), Move data.txt to the directory where CLion runs its compiled programs from.
(for #2, here's a hacky way to get that directory)
char buf[1024]; // hack, but fine for this
printf("%s\n", getcwd(buf, 1024));
Run/Edit configurations...
Select your application (on the lefthandside of the window)
Specify Working directory
Apply
Now you can fopen relatively from working directory.
I found another way to solve this problem.
#Lou Franco's solution may affect the project structure. For example, if I deploy code on a server, I should move the resource file to specific directory.
What I do is modify the CmakeLists.txt, on Windows, using
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "D:\\science\\code\\English-Prediction")
CMAKE_RUNTIME_OUTPUT_DIRECTORY is a CMake variable, it assigns the work directory of CLion work directory.
Continuing with the CMAKE_RUNTIME_OUTPUT_DIRECTORY CMakeLists variables, I do the following. In the root directory of my project, I create a directory, e.g., out. Then, in my CMakeLists.txt I set the CMAKE_RUNTIME_OUTPUT_DIRECTORY to that directory:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/out)
Note, that must come before you have
add_executable(YourProject ${SOURCE_FILES})
I might also add that instead of using fopen() I would keep it more object-oriented by using std::ifstream:
std::ifstream inFile("data.txt");
// check if it opened without issue...
if (!inFile) {
processError(); // a user-defined function to deal with the issue
} else {
// All is good, carry on...
// and when you're done don't forget
inFile.close();
}

How to get the parent folder of a Windows user's profile path using C++

I am trying get the parent folder of a Windows user's profile path. But I couldn't find any "parameter" to get this using SHGetSpecialFolderPath, so far I am using CSIDL_PROFILE.
Expected Path:
Win7 - "C:\Users"
Windows XP - "C:\Documents and Settings"
For most purposes other than displaying the path to a user, it should work to append "\\.." (or "..\\" if it ends with a backslash) to the path in question.
With the shell libary version 6.0 you have the CSIDL_PROFILES (not to be confused with CSIDL_PROFILE) which gives you what you want. This value was removed (see here), you have to use your own workaround.
On any prior version you'll have to implement your own workaround, such as looking for the possible path separator(s), i.e. \ and / on Windows, and terminate the string at the last one. A simple version of this could use strrchr (or wcsrchr) to locate the backslash and then, assuming the string is writable, terminate the string at that location.
Example:
char* path;
// Retrieve the path at this point, e.g. "C:\\Users\\username"
char* lastSlash = strrchr(path, '\\');
if(!lastSlash)
lastSlash = strrchr(path, '/');
if(lastSlash)
*lastSlash = 0;
Or of course GetProfilesDirectory (that eluded me) which you pointed out in a comment to this answer.

Resources