Change selection in explorer window? - c++

I have a "Show in folder" button which executes the following:
explorer.exe /select,"C:\dir\somefile.txt"
In Win7 this works great, a new window is always opened, but in XP, if "C:\dir" is already open, this window is reused but the selection is not changed to "somefile.txt".
This is not the expected behaviour from the point of view of the user, he expects to see "somefile.txt", but instead sees another file, and that might confuse him. At worst, he might assume that something went wrong and the file was not created.
So I need to somehow force Explorer in XP to always select the file I give it in the cmd line, or not to reuse the window.
Can anyone suggest a way to do this (different cmd parameters, maybe COM automation)?

As I don't have Windows 7, I can't confirm if this works the way you expect on subsequent Windows versions. But on my XP machine:
explorer.exe /e,/select,"C:\dir\somefile.txt"
Works exactly the way I think you'd want by opening a new explorer window each time with the right selection and avoids that confusing behavior you described.

Related

Why is IExplorerCommand::Invoke() no longer being called?

I have created a File Explorer context menu extension that uses the IExplorerCommand interface to add menu commands to the Windows 11 context menu.
This has been working fine, but after the last Windows update, it no longer works properly.
Although the menu commands still appear, nothing happens when I click on any of them. I've added logging and I can see that IExplorerCommand::Invoke() is no longer being called.
Strangely, if I select the "Show more options" menu to get the legacy Windows 10 context menu, the commands work fine from that menu, it is only in the new Windows 11 context menu that they don't work.
I have tried running File Explorer in a debugger while selecting my menu commands, and I get lines like this in the output window when I click on the command:
onecore\com\combase\dcomrem\stdid.cxx(726)\combase.dll!00007FF9EB9947F5: (caller: 00007FF9C22E1E38) ReturnHr(2627) tid(67bc) 8001010E The application called an interface that was marshalled for a different thread.
I'm guessing this is the reason why my commands are not being called. Does anyone have any suggestions for what is causing this? Could it be a bug in File Explorer?
I've tried both STA and MTA threading models, and changing this made no difference.
Well, after wasting hours on this I finally have a solution!
My code was based on the PhotoStoreContextMenu sample code here:
https://github.com/microsoft/AppModelSamples/tree/master/Samples/SparsePackages/PhotoStoreContextMenu
This uses the Windows Runtime C++ Template Library (WRL), and defines the base classes used by the class like this:
class TestExplorerCommandBase : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IExplorerCommand, IObjectWithSite>
The change that fixed it for my code was to use WinRtClassicComMix instead of ClassicCom, i.e.
class TestExplorerCommandBase : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IExplorerCommand, IObjectWithSite>
I'm pretty sure this problem started when I installed KB5019509, which is the Windows update that changes File Explorer so that it now has tabs.
Note: this problem only happens for IExplorerCommands created in the plug-in for submenus, the top level commands that are defined in the APPX file work fine.
Also note that although this change does fix the problem with Invoke() not being called, it does introduce a new problem which is that IOleWindow::GetWindow() no longer works so it is not possible to get the parent HWND. (See Calling IOleWindow::GetWindow() from IExplorerCommand::Invoke() is giving error 8001010d (RPC_E_CANTCALLOUT_ININPUTSYNCCALL)).

How to lock Windows 7 into a single program with C++?

I have been working on an app in Visual Studio 2015 (C++). It's a kiosk app for my school's tech support. Basically, it's a support site that will run in a kiosk. I need to figure out how to lock windows so it only runs that program. It would also be helpful to run the program in fullscreen mode. Keep in mind that all of the kiosks run Windows 7.
Set registry key
HKCU SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
Shell="c:\path\to\whatever.exe"
Disallow task manager via security of taskmgr.exe (add a deny read + deny execute to the binary)
Set autologn:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
DefaultUserName = whatever
DefaultPassword = whatever
Have a boot disk handy. The only way to reverse this is to boot the boot disk and undo one of the steps after mounting the appropriate hive.
you can create your program with main window in full screen mode and popup:
hWnd = CreateWindowEx(WS_EX_CLIENTEDGE|WS_EX_APPWINDOW|WS_EX_TOPMOST,
lpClsName,
"MDI Project under Visual C++ WINAPI",
WS_BORDER|WS_POPUP,
...);// add the remaining parameters
and find taskmgr.exe and hide it and start menu button and hide them also:
hTaskBar = ::FindWindow ("Shell_TrayWnd", "");
hStart = ::FindWindowEx(GetDesktopWindow(), NULL, "Button", "Start");
ShowWindow(hTaskBar, SW_HIDE);
ShowWindow(hStart, SW_HIDE);
so your program looks like easycafe or handycafe
I actually switched from C++ to C#, so I'm gonna explain my answer with C#.
I used a keyboard hook library to capture keyboard input and block all non-letter/number input so alt-f4, alt-tab etc. would not work. I then determined a closing sequence of characters using another keyboard hook (LWin+C+Home+F12+PrtSc).
As for Ctrl-Alt-Del, that cannot be disabled (as far as I know) because it is a system function, so I just left that as it is.
I also got the bounds of the screen and set the size of the window to the maximum screen size at application launch, as well as whenever the app is resized or moved. This essentially makes it so the app covers the task bar, and the bar with the close and minimize buttons is also covered, but if someone found a way to move it it would immediately go back to it's full size.
I also set up autologin as was detailed in a previous answer, but I just didn't do it through code.

Prevent a Windows app from stealing the focus

I have created a windows application in C++ and I want to make so whenever I run it, it doesn't steal focus from whichever window is currently focused(or maybe steal the focus and give it back right away). I'm not creating any window so i'm not sure how to change the window style, my program runs in the background.
I couldn't find any answer that worked for C++, is there any way I can do this?
When you start your application by clicking on the EXE or shortcut, Windows Explorer takes focus, not your app. The only way to start your app and not let Windows Explorer take focus is to start your program when Windows starts, via registry key.
Make sure you use the extended style WS_EX_NOACTIVATE when using CreateWindowEx().
See the Microsoft Docs for CreateWindowEx.

Retrieving Menu in Explorer

As the context menu for the desktop and explorer windows is disabled, I wanted to make a little something to bring back some functionality. My idea was to just list out things in a context menu (copy, paste, new, open with, etc) whenever a user right-clicks one of these windows, and then just simulate the appropriate event in the actual menu (file->new, edit->copy, etc). It wouldn't look perfectly pretty, but it would hopefully allow for the use of right-clicking.
The problem is that I cannot seem to get the actual menu. I opened My Documents and tried going down the child list towards SysListView32, calling GetMenuItemCount each time. Most returned -1, and the only other return value than that was 0.
How am I supposed to get a handle to the (file, edit, view...) menu?
If this isn't possible, is there a way I could simulate the user clicking something on the normal context menu, even if it's disabled?
Also, is there a way of making this work for the desktop? You can get the same type of thing if you view it in the explorer window, so I figured there might be a way.
I'm running Windows XP and any help is appreciated.
As per David Heffernan's comment,
As for your question, you are on the wrong track.
GetMenuItemCount needs an HMENU but you've been feeding it HWND.
That won't work. It also won't work from a different process.
You could possibly write a program that use the shell COM APIs
to show a context menu for a shell item. But your basic problem
is the bone-headed group policy. You really need to get that fixed.
Tell the IT guy that takes the decision that I said he was a fool
and was stopping you doing any useful work. ;-)
This led me onto the path of using the correct alternative method to achieve my goal.

Is it possible to embed a command prompt in a win32 app?

In linux and when installing packages etc. There are some installers that have a progress bar and a dos window which shows the files being extracted etc. How can i add this window to my C++ Win32 programs so that i can have it showing the tasks im doing? I cannot find any documentation on MSDN.
Question: How can i add a console window (if that's what its called, sure looks like one) in my program to show the details of the task at hand being done?
Here is a window with what i am asking.. (personal info so I erased the details. :]
You cannot embed a real console window inside another window (although a windowed process can have a separate console window). While it looks like a console window / command prompt, it is just a matter of appearances. What you want to do is create a sub-window/control with similar characteristics as a console window and then redirect the console output from the application(s) being run to append to that sub-window. For more information on how to do redirect the console output in Windows, see http://support.microsoft.com/kb/190351.
That "dos window" is a regular edit control: CreateWindow(ES_MULTILINE, EDIT, ...
However, it has the font set to a fixed-width one (Looks like courier). This is done by sending WM_SETFONT to the edit control.
#user995048 says "You cannot embed a real console window inside another window". But "cannot" is a strong word! I can run an entire virtualized computer in a window if I wish. :) So one can quite reasonably intuit that there are ways of doing what you say.
Sure, it is true that what you've seen are almost certainly cases of output redirection into a custom widget, designed to mimic the simple appearance of a terminal. However...if you want to embed one application's window inside another, there are things you can look into which might fit. Cooperative methods exist like GtkPlug, for instance:
http://developer.gnome.org/gtk/2.24/GtkPlug.html
To actually capture a not-designed-to-cooperate app's window and throw it in your app would be trickier. But possible, just as screen captures and virtual machines are possible. Probably best to avoid that sort of thing unless there's really a cause for it, though...
Try this
http://www.codeguru.com/cpp/misc/misc/article.php/c277/
link. I think the solution provided is what you need.
I tried it many years ago and it worked. I have not tried it in newer versions of windows though.