How to select a file from windows file explorer - c++

Is there a way to use ShellExecute and grab the file (or rather the file path) and save it in a variable upon selecting it?
Should I use a different function all together?
I've looked at some of the other similar functions for opening the windows file explorer and all of them need a path first, before opening the window.
ShellExecute(NULL, L"explore", NULL, NULL, NULL, SW_SHOWNORMAL);
My goal is to open the file explorer (like ShellExecute does) and select one file, plug the path of that file into a variable and do a thing with it later.

Use IFileDialog, IFileOpenDialog or IFileSaveDialog

Related

How to find window handle from exe file's name

Imagine I have Firefox and I open Firefox Start Page, then I should have a Window with the title: "Mozilla Firefox Start Page - Mozilla Firefox".
I can find window handle with the code below
HWND hwnd = ::FindWindow(0, _T("Mozilla Firefox Start Page - Mozilla Firefox"));
But what I want is find window handle from the window's exe file's name like this
HWND hwnd = FindWindowFromExe(_T("firefox.exe"));//How to make this function?
Does windows Api has a function like FindWindowFromExe()? If it doesn't, what is the best way to Find window from its exe?
Thanks for reading :)
There is no single API function to find a window by its owning process's file name. You will have to search for it manually.
You can use EnumWindows() to enumerate all top-level windows, or use FindWindow()/FindWindowEx() to find/enumerate specific types of windows.
For each window, you can either:
use GetWindowThreadProcessId() to get the process ID that owns the window, then
use OpenProcess() to open a HANDLE to that process, then
use GetModuleFileNameEx(), GetProcessImageFileName(), or QueryFullProcessImageName() to query the process for its full path and filename.
or
use GetWindowModuleFileName() to query the window for the full path and filename of the module that created it (assuming the intended window is created by an actual EXE and not a DLL used by an EXE).
Once you have the window's filename, you can then compare that to your target filename.

How to prevent "How do you want to open this file" dialog?

In my app I open a report using HTML file as such:
//pStrPath is file:///C:/Users/appts/AppData/Local/Temp/Report_View.htm
ShellExecute(hParentWnd, L"", pStrPath, NULL, NULL, SW_SHOW);
On my development machine it opens up in a web browser, but when I just tested it on a new installation of Windows 10, it showed this dialog instead:
So how can I prevent it from being shown and go with "keep using this app" option from the get-go? Otherwise it may be very confusing for my users.
PS. Note that Edge is installed and can open .htm files if I double-click them.
Referring to Launching Applications (ShellExecute, ShellExecuteEx, SHELLEXECUTEINFO) we note the text
Object Verbs
The verbs available for an object are essentially the items that you find on an object's shortcut menu. To find which verbs are available, look in the registry under HKEY_CLASSES_ROOT\CLSID{object_clsid}\Shell\verb
Commonly available verbs include:
edit - Launches an editor and opens the document for editing.
find - Initiates a search starting from the specified directory.
open - Launches an application. If this file is not an executable
file, its associated application is launched.
print - Prints the document file.
properties - Displays the object's properties.
Given that a double-click is the generally equivalent to selecting "open" in the object's shortcut menu, if we supply the function with the open verb, we can expect the behaviour to mirror that of a user's double-click. - Please see Ken's comment below
As such, we can expect the following code to achieve the desired result.
//pStrPath is file:///C:/Users/appts/AppData/Local/Temp/Report_View.htm
ShellExecute(hParentWnd, L"open", pStrPath, NULL, NULL, SW_SHOW);
If you are trying to open the default program FROM a 32 bit program in 64 bit Windows the ShellExecute and ShellExecuteEX may display the "How do you want to open this file?" dialog box each time. This is due to the way that the default program registered itself in Windows I think.
I could reproduce this error on Windows 11 fresh install where the Photos is set to the Default Program for .jpg files.
In my case, I found that if I use the ShellExecuteExW function and pass the extension into the .lpClass of SHELLEXECUTEINFOW Type that it works.
It should also work with the ShellExecuteExA function
Make sure it's not an exe, reg, bat file, or a URL you are trying to open. It has to be a document type of file.
Use the .lpClass to pass the extension like ".jpg"
Add the SEE_MASK_CLASSNAME As Long = &H1 to the .fMask parameter you are passing in like .fMask = YourMaskValue Or SEE_MASK_CLASSNAME
The reason I think this works is it bypasses any redirection and reads directly from the HKEY_CLASSES_ROOT.jpg

MFC CFileDialog open only select files

Using CFileDialog as a file open, I need to allow the user to only select a file that is displayed in the dialog list area, such as by clicking on it. We don't want the user to be able to type in a name in the File Name control. The OPENFILENAME (OFN) struct has several different flags (http://msdn.microsoft.com/en-US/library/ms646839%28v=vs.80%29.aspx), but I don't see one that prevents the user from typing in a filename.
The closest thing I saw was OFN_FILEMUSTEXIST, but that only specifies that the file exists; it still allows the user to type in a name.
Is there any way to do this without inheriting a new class?
MORE INFO
We need to prevent them from typing in a filename because they could open an inappropriate one. With the lpszFilter parameter, we filter the filenames so it only displays files with ABC in the filename (not the extension). So if they typed in a filename, they could enter something like myCoolFileDEF.ext. If the file exists, it will go ahead and let them open it (the dialog will close w/o an error message) even though they were only supposed to open files with ABC in the filename.
Since you are using MFC, just inherit a CFileDialog and disable the file name edit control and combobox. I don't see the point of using CFileDialog AND writing another OFNHookProc callback, though you could start from GetOpenFileName if you want to.
As a previous answer notes, you could root around in the dialog for the filename control and disable it. This is not without penalty though - if you turn on the CFileDialog hook callback logic, you get the "old style" file dialog on Vista and above, not the "new style" one. The "new style" file dialog is a lot more restrictive in what can be customized, and, as far as I know, doesn't provide a supported way to get at the filename control.
Reading your question, my first instinct is that you're over-designing your solution: if you supply a filter then the user has to go to quite a lot of trouble to select the wrong sort of file, and most users won't do that. If they do, it's possible that the user knows better than your program. If it were me, I would just use a filter, then after the file dialog has closed, check the returned filename - if it doesn't match the required pattern, I'd put up a message dialog to ask if the user if they're really sure, and open the file anyway if they insist that they are.

Is there a special method to remove a shortcut from a desktop?

I created a shortcut (.lnk) file on the desktop using the IShellLink interface similar to the code described at the bottom of this page.
So my assumption was that to remove this shortcut I could simply call DeleteFile on the .lnk file, but evidently it is not enough... if I do that I get a remnant of the shortcut file that looks like this:
But what is interesting is that if I browse files in the desktop folder, say with Windows Explorer, the .lnk file is not actually there. What I see is some artifact on the desktop GUI surface.
Any idea how to remove a shortcut (the way Microsoft wants it done?)
OK, per suggestion above, here's the API that needs to be called afterwards to refresh the shell:
SHChangeNotify(SHCNE_DELETE, SHCNF_PATH | SHCNF_FLUSHNOWAIT, pDeletedFilePath, NULL);

Open in Explorer

How do you open a path in explorer by code in c++. I googled and couldn't find any thing but systems commands to do this, however, i dont want it to block or show the console window.
You probably are looking for the ShellExecute() function in shellapi.h. It is called with an "action verb", a path, and optional parameters. In your case this will want either "open" or "explore" as follows:
ShellExecuteA(NULL, "open", "C:\\", NULL, NULL, SW_SHOWDEFAULT);
This will open an unattached explorer window at C:. ShellExecute() will give basically the same action as typing in a command at the Run dialog. It will also handle URLs, so the following will open up the user's default browser:
ShellExecuteA(NULL, "open", "http://www.google.com", NULL, NULL, SW_SHOWDEFAULT);
Although make sure to pay attention to the note in the documentation that ShellExecute relies on COM (Although your code doesn't have to worry about any COM objects itself).
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)
This does not show the command window, just opens the directory.
system("explorer C:\\");
I'm now using VS2017, using as follows works:
ShellExecute(NULL, L"open", L"YourFolderPath\\YourFile.xxx", NULL, NULL, SW_RESTORE);
also reference ShellExecute to open an .exe in C++