CComboBox::Dir function does not list directory if Archive attribute is unset and Index attribute is set - winapi

I am using CComboBox::Dir(DDL_READWRITE, path) to populate the contents of a combobox. Everything is fine, but when I reset the Archive flag and set the Index flag, the Dir() returns no files. I am using
attrib -A *.*
attrib +I *.*
in the directory I am listing. I have tried changing the first parameter to Dir() function but it does not help. I have tried FindFirstFile()/FindNextFile() and they are working fine
Any ideas to explain the reason of this behavior?
Could this a bug in the Dir() function? If yes, what other functions could it effect?
How to solve this problem?

This is quite an interesting issue. I debugged it on Win 7 64 Bit down into comctl32.dll ListBox_DirHandler assembler code and found out that Windows is doing something like this (just some simplified code):
// attr is the low word of the parameter passed to CComboBox::Dir.
attr &= FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL;
attr |= FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_READONLY;
WIN32_FIND_DATA finddata;
FindFirstFile(..., &finddata)
while(...) {
if(finddata.dwFileAttributes == FILE_ATTRIBUTE_COMPRESSED)
finddata.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
if(finddata.dwFileAttributes & attr) {
// some more checks and then might add the file name to the control;
}
FindNextFile(..., &finddata);
}
The problem is that your file is returned with finddata.dwFileAttributes==FILE_ATTRIBUTE_NOT_CONTENT_INDEXED. At entry of the function attr is changed so that it can never have FILE_ATTRIBUTE_NOT_CONTENT_INDEXED set, so the if inside the loop will never be true and the file name never be added to the control.
Sorry, but as far as I can see you will have to wait for an MS bugfix or do the work yourself.

Related

Clarification of code to change target of a Shortcut(.lnk) file

I am a Java programmer, and I do not know anything about VBScript. I needed a way to modify the target path of a certain shortcut, and I according to my research, only VBScript can help me. I tried it, but there were many errors.
I tried to resolve them by a butt ton of googling, but I think there is some other problem.
Here is the code:
Set sh = CreateObject("WScript.Shell")
Set shortcut = sh.CreateShortcut("C:\Users\pedne\Desktop\Zoom.lnk")
shortcut.TargetPath = "C:\Users\pedne\AppData\Roaming\Zoom\bin\Zoom.exe ""--url=zoommtg\://zoom.us/join?action=join&confno=955 1234 1234&pwd=12345"""
shortcut.Save
I do not know whether I need any prerequisites or external libraries for writing VBScript code, and I wrote it on notepad.I would also like to know whether there is any 100% Java or any other workaround to this. (Totally up to you)
Please excuse me if I do not understand anything about your answers as I copied the code from Change a shortcut's target from command prompt
The last error I got was at Line 3 char 1, Invalid procedure or call
Do not append the arguments to the target path. Use the Arguments property instead:
shortcut.TargetPath = "C:\Users\pedne\AppData\Roaming\Zoom\bin\Zoom.exe"
shortcut.Arguments = "--url=zoommtg\://zoom.us/join?action=join&confno=955 1234 1234&pwd=12345"
shortcut.Save

Catch errorlevel from cmd command in shellexecute

I have batch script, to create backup of some 30 locations on work network, and it works.
Now I am programming the same app, but in MFC VC++, so im using little trick to set parameters for xcopy in string, then execute it with ShellExecute.
m_destination is variable from editbox, as destination input, where files are going.
Code is:
if (m_line1.GetCheck() == BST_CHECKED)
{
temp_dest = _T("/min /c xcopy \"\\\\pc_name.sub_domain.domain.local\\c$\\Users\\Test\\Desktop\\Test\\*.*\" \"") + m_destination + _T("\" /Y /E /Q");
ShellExecute(
GetSafeHwnd(),
L"open", // open edit print
L"C:\\Windows\\System32\\cmd.exe", // FILE PATH,
temp_dest, // PARAMETERS
NULL, // WORKING DIR
SW_HIDE); // WINDOW SHOW HIDE
m_status = "Line 1 - OK\r\n";
}
This code above works, but there are some cases, when target PC is shutdown, and in cmd window, it says "path has changed or destination unreachable" (something like that). In that case, %errorlevel% has some value, and some other if copying successfully done. Then u have condition to trigger different warnings to user.
The thing is, I dont have clue how to catch it to indicate unsuccessful copying.
I need some kind of warning that copying from that PC is not done. How can I retrieve error code after copying in this way?
Or if there is simple function to replace copyx with (*.*) (all contents) copying, with ability to be directed to specific directory, I would like to hear about it.
Thanks in advance.
I don't think there's a straightforward way to do this with ShellExecute because it doesn't give you a process handle. However, ShellExecuteEx does, via the hProcess field of the SHELLEXECUTEINFO struct you pass in. With that handle, you can wait (WaitForSingleObject) and then get the exit code (GetExitCodeProcess). However, you can also do this with a simple CreateProcess. Also SHFileOperation supports some xcopy-like operations and gives you additional programmatic control.

Autoit replace string in multiple text files

I have this code:
$szFile = "text.txt"
$szText = FileRead($szFile,FileGetSize($szFile))
$szText = StringReplace($szText, "before", "after")
FileDelete($szFile)
FileWrite($szFile,$szText)
It works but I have loads of text files to do this with and to configure the script each time is a problem. Does any one know how I could make it so it would do it for every file in that dir. I have tried $szFile = "*.txt" but that doesn't work. Thanks.
FileFindFirstFile supports wildcards. Note that the function returns a file handle which could then be used in your FileOpen call.

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.

Why is FindNextFile failing on Windows 7

This code works on Windows XP at home but fails at work on 64bit Windows 7. The loop isn't entered even once although there are more than 50 files in the supplied folder. Not only it doesn't enter, it also returns ERROR_NO_MORE_FILES for GetLastError. Why?
string dir = "d:\\validfolder";
WIN32_FIND_DATA ffd;
HANDLE h = FindFirstFile(dir.c_str(), &ffd);
while(FindNextFile(h, &ffd))
{
// some operation
}
DWORD dw = GetLastError();// returns ERROR_NO_MORE_FILES
I tried Wow64DisableWow64FsRedirection but that has no effect.
You need to add a file wildcard to your dir:
string dir = "d:\\validfolder\\*";
For it to list the files in a directory. Otherwise you are only asking for information about the directory itself.
At least that's how I read the documentation for FindFirstFile
To examine a directory that is not a root directory, use the path to
that directory, without a trailing backslash. For example, an argument
of "C:\Windows" returns information about the directory "C:\Windows",
not about a directory or file in "C:\Windows". To examine the files
and directories in "C:\Windows", use an lpFileName of "C:\Windows*".
I don't know why it's working for you on XP
This code is incorrect in a number of ways.
You must check the return value of FindFirstFile. If the call to FindFirstFile succeeds then you already have the first file in ffd. As your code stands, you throw away the first file. So you need to re-jig your loop logic to account for that. Naturally, if GetLastError returns ERROR_NO_MORE_FILES then that means the search has exhausted all files.
So, what is probably happening is you ask for the first file matching the search string "d:\\validfolder". This is returned in ffd after the call to FindFirstFile. You then ignore that information and ask for the next match. But there is no subsequent match since there is only one object matching "d:\\validfolder" since you included no wildcards in your search pattern.
This code will behave exactly the same on XP as it does on Windows 7 and I suspect that you are not running the same code on both systems.
If you want to enumerate the contents of the folder then you need to search for "d:\\validfolder\\*". Something like this:
string dir = "d:\\validfolder\\*";
WIN32_FIND_DATA ffd;
HANDLE h = FindFirstFile(dir.c_str(), &ffd);
BOOL success = h<>INVALID_HANDLE_VALUE;
while(success)
{
// do something with ffd
success = FindNextFile(h, &ffd));
}

Resources