Clean Windows 7 Start Menu MRU List - windows-7

Is there a way to clean the most recently started applications from the Windows 7 start menu programmatically?
I'm looking for some registry entries and/or files to delete so the corresponding items in the Winodws 7 start menu are removed.

SHAddToRecentDocs(SHARD_PIDL,NULL) is the documented way to clear the recent documents, not messing in the registry like surya suggests.
Since your question includes the word "applications" I'm assuming that you are actually mean the list of applications, and there is no real way to modify that programmatically since that list "belongs" to the user.
If you want to go the undocumented hacky route you can use get a IContextMenu for the specific .lnk and call the "Remove from this list" command.
On XP the start menu application usage is stored in HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist{75048700-EF1F-11D0-9888-006097DEACF9} but explorer will cache those entries so you can't just delete the key without killing explorer first.

Now this is the solution for my question:
I Cleaned the values under the Registry Keys
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\Count
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\Count
Then I executed the following PInvoke to refresh the cache of the Explorer.exe:
C#:
using System.Runtime.InteropServices;
[DllImport("shell32.dll")]
static extern void SHChangeNotify(int wEventId, int uFlags, IntPtr dwItem1, IntPtr wItem2);
private const int SHCNE_ASSOCCHANGED = 0x08000000;
private const int SHCNF_IDLIST = 0x0000;
private void ClearCache()
{
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero);
}
Regards,
Boris

In the Registry, delete unneccessary stuff. The key is HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs

Related

How to force Explorer use modern file operation dialog with Shell Namespace Extension

In my understanding currently there are two ways to copy virtual files from a Shell Namespace Extension with the Explorer so that Copy GUI will be shown to the user:
Via IDataObject interface:
Reading a file is done via IDataObject::GetData that should support CFSTR_FILEDESCRIPTORW, CFSTR_FILECONTENTS and CFSTR_SHELLIDLIST clipboard formats at very minimum. Requesting CFSTR_FILECONTENTS from IDataObject::GetData should create an IStream that is used to access the data. UI is enabled via setting FD_PROGRESSUI flag when CFSTR_FILEDESCRIPTORW is requested.
Via ITransferSource interface:
Reading a file is done via ITransferSource::OpenItem requesting for IShellItemResources. Then IShellItemResources should report {4F74D1CF-680C-4EA3-8020-4BDA6792DA3C} resource as supported (GUID indicating that there is an IStream for the item). Finally an IStream is requested via parent ShellFolder::BindToObject for accessing the data. UI is handled by the Explorer itself, it is always shown.
My problem is: these two mechanisms are working just fine separately (as you can see from the screenshots). But once I enable both IDataObject from IShellFolder::GetUIObjectOf and ITransferSource from IShellFolder::CreateViewObject - the approach via IDataObject is always used leading to the old copy GUI (as on the first screenshot). I see from the trace logs that ITransferSource is requested several times, but no actions are performed, it just gets Released and destroyed right away.
So how may I force Explorer to show fancy copy GUI when copying from my Shell Namespace Extension?
A minimal reproducible example may be found here: https://github.com/BilyakA/SO_73938149
While working on Minimal Reproducible example I somehow managed to make it work as expected with both IDataObject and ITranfserSource interfaces enabled. It happened after:
unregistred x64 build SNE example (regsvr32 /u)
registred x32 build SNE example (it was not working in x64 explorer, root was not opening)
unregistred x32
registred x64 again.
Somehow new copy UI was shown to me when copying the files.
But I was not able to reproduce this result constantly after I have unregistred x64 SNE, restarted explorer and registered SNE x64 again.
What I have tried:
Registred both x32 and x64 SNE - still old GUI
Removed Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Cached value with my NSE GUID and restarted Explorer afterwards. Still old GUI.
I suspect there is some kind of cache (other than Registry) that keeps track if NSE supports ITransferSource. And since I have developed and tested without ITransferSource at the beginning - it is cached that my NSE does not support it even that I have added it later. And somehow registering 32bit reset that cache value.
The current code is doing something like this when asked for an IDataObject:
HRESULT CFolderViewImplFolder::GetUIObjectOf(HWND hwnd, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT rgfReserved, void **ppv)
{
....
if (riid == IID_IDataObject)
{
CDataObject* dataObject = new (std::nothrow) CDataObject(this, cidl, apidl);
return ::SHCreateDataObject(m_pidl, cidl, apidl, dataObject, riid, ppv);
}
...
}
SHCreateDataObject already creates already a full-blown IDataObject with everything needed from the (optional) input PIDL(s), including all Shell formats for items in the Shell namespace (CFSTR_SHELLIDLIST, etc.).
Passing an inner object 1) will probably conflict with what the Shell does and 2) requires a good implementation (I've not checked it).
So you can just replace it like this:
HRESULT CFolderViewImplFolder::GetUIObjectOf(HWND hwnd, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT rgfReserved, void **ppv)
{
....
if (riid == IID_IDataObject)
{
return ::SHCreateDataObject(m_pidl, cidl, apidl, NULL, riid, ppv);
}
...
}
In fact, the IDataObject provided by the Shell is complete (supports SetData method, etc.) so you should never need to implement it yourself, it's more complex than it seems. You can reuse it as a general purpose IDataObject (you can pass nulls and 0 for the 4 first arguments).
PS: the Shell also provides the "reverse" method: SHCreateShellItemArrayFromDataObject that gets a list of Shell items from an IDataObject (if the data object contains the expected clipboard formats).
For those who need to use inner IDataObject within SHCreateDataObject for additional format:
Inner IDataObject should support CFSTR_SHELLIDLIST clipboard format in GetData() as well as report this format in EnumFormatEtc(). Supporting SetData() with CFSTR_SHELLIDLIST format is really useful here since DefDataObject sets inner data object with already fully constructed CIDA and you may just store a copy of it.
Once inner data object will report CFSTR_SHELLIDLIST in EnumFormatEtc() and return valid CIDA in GetData() - modern Copy UI will be used since it relies only on PIDL of the items.

Control Panel Settings from Command Line

I'm looking for a way to make a Registry Change take affect right away.
Specifically the value I want to touch is:
HKEY_CURRENT_USER/Control\ Panel/Desktop/WindowArrangementActive
When you change this setting directly from the Control Panel it takes effect immediately, but when I'm changing it manually, it is not registered before rebooting.
I'm trying to make a script to disable/enable window snapping in Windows 10.
I've currently tried running the following command after the change with no luck:
RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters ,1 ,True
I ended up getting the job done in C# using the SystemParametersInfo:
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
public static extern bool SystemParametersInfo(int uiAction, int uiParam, IntPtr pvParam, int fWinIni);
and calling it with the following params:
SystemParametersInfo(0x0083, 0, IntPtr.Zero, 0x001A);
The final param is the one informing the system that the variable has changed in accordance with this documentation by Microsoft:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms725497(v=vs.85).aspx

Windows 8 Store app, Type.IsClass and System.ComponentModel.DesignerProperties.IsInDesignTool missing

I am investigating Windows 8 Store app development, and am having trouble locating the following members
Type.IsClass
System.ComponentModel.DesignerProperties.IsInDesignTool
Visual studio claims they don't exist, but MSDN suggests they should.
I am obviously missing something silly: Can anyone point me in the right direction please?
Regards
John.
The IsClass property has moved to the TypeInfo class. Basically you need to replace;
bool result = type.IsClass;
with;
bool result = type.GetTypeInfo().IsClass;
GetTypeInfo() is an extension method from the System.Reflection namespace, no not obviously visible on System.Type unless you're already using System.Reflection.
The IsInDesignTool property has moved to another place too and changed name;
bool result = Windows.ApplicationModel.DesignMode.DesignModeEnabled;

Calling VS2012 Solution Explorer Commands in code

I'm trying to make an extension and I need to call two commands from code...
SolutionExplorer.SyncWithActiveDocument
The Collapse All command in the Solution Explorer.
I can't find anyway to call these functions.
Does anyone know how to do this?
Have you tried executing the commands via the DTE?
dte.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Activate();
// Sync with Active Document
dte.ExecuteCommand("SolutionExplorer.SyncWithActiveDocument");
// Collapse All
int cmdidSolutionExplorerCollapseAll = 29;
Guid guidCMDSETID_StandardCommandSet11 = new Guid("D63DB1F0-404E-4B21-9648-CA8D99245EC3");
dte.Commands.Raise(guidCMDSETID_StandardCommandSet11.ToString("B"), cmdidSolutionExplorerCollapseAll, null, null);
If you need to identify the ID's for any other commands, you can switch on VSIP logging:
http://blogs.msdn.com/b/dr._ex/archive/2007/04/17/using-enablevsiplogging-to-identify-menus-and-commands-with-vs-2005-sp1.aspx

Overriding IE settings when embedding a WebBrowser control using IE9

I have an application (written in C++ with MFC, but I don't think that that's particularly relevant) that embeds the Internet Explorer ActiveX WebBrowser control for the purpose of showing some HTML pages. One requirement has always been to use the application's font name and size settings as the default settings for the HTML, rather than Internet Exporer's defaults.
To achieve this, the application implements the IDocHostUIHandler2 COM interface, which it passes to the WebBrowser control. This causes the control to call the application's implementation of GetOptionKeyPath, which lets the application set the registry location that the WebBrowser control gets its settings from. Armed with Sysinternals' tools to see which keys IE uses to find the font name and size, this has been sufficient to do what I need.
However, the appeareance of Internet Explorer 9 has come as a nasty surprise: on all machines that I've tested with that have IE9 installed, the WebBrowser control uses its own settings, ignoring the registry location from the application. Testing with a debugger shows that the WebBrowser control never calls the provided GetOptionKeyPath.
A bit more experimentation shows that the IE9 WebBrowser control is calling the similar (but not identical) GetOverrideKeyPath method: this allegedly provides a way to override IE settings, while falling back to IE's actual settings if nothing is found in the relevant part of the registry. Unfortunately this has two problems: 1) It's not quite what I want, and 2) IE9 doesn't always check under the GetOverrideKeyPath registry location before going to the IE default registry settings.
Looking at the GetOptionKeyPath MSDN page there are a few complaints along similar lines, but no solutions. Has anyone found a clean way to persuade the WebBrowser control to revert to the pre-IE9 behaviour of actually calling GetOptionKeyPath as documented?
I've come up with a hack to solve this problem, but I should warn you: it's not pretty. Stop reading now if you've easily offended ...
Since there seems to be no way of making IE9 use the IDocHostUIHandler::GetOptionKeyPath() method, I used SysInternals' tools to see which IE9 DLLs accessed the relevant parts of the registry to load the IE9 settings. This revealed the only culprits as "mshtml.dll" and "iertutil.dll", both of which call RegOpenKeyExW().
The plan was then to load these DLLs before initializing the WebBrowser control, and patch them so that calls are redirected to my code, where I can lie about what registry key I've opened, using dbghelp.dll. So, to start, before initializing the WebBrowser control:
if (theApp.GetIEVersion() >= 9.0)
{
HMODULE advadi = ::LoadLibrary("advapi32.dll");
HMODULE mshtml = ::LoadLibrary("mshtml.dll");
HookApiFunction(mshtml,advadi,"advapi32.dll","RegOpenKeyExW",(PROC)HookRegOpenKeyExW);
HMODULE iertutil = ::LoadLibrary("iertutil.dll");
HookApiFunction(iertutil,advadi,"advapi32.dll","RegOpenKeyExW",(PROC)HookRegOpenKeyExW);
}
And now, the code that does the evil work of scanning the DLLs import address tables, and patching the requested function (error handling omitted to keep the code size down):
void HookApiFunction(HMODULE callingDll, HMODULE calledDll, const char* calledDllName, const char* functionName, PROC newFunction)
{
// Get the pointer to the 'real' function
PROC realFunction = ::GetProcAddress(calledDll,functionName);
// Get the import section of the DLL, using dbghelp.dll's ImageDirectoryEntryToData()
ULONG sz;
PIMAGE_IMPORT_DESCRIPTOR import = (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(callingDll,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&sz);
// Find the import section matching the named DLL
while (import->Name)
{
PSTR dllName = (PSTR)((PBYTE)callingDll + import->Name);
{
if (stricmp(dllName,calledDllName) == 0)
break;
}
import++;
}
if (import->Name == NULL)
return;
// Scan the IAT for this DLL
PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)((PBYTE)callingDll + import->FirstThunk);
while (thunk->u1.Function)
{
PROC* function = (PROC*)&(thunk->u1.Function);
if (*function == realFunction)
{
// Make the function pointer writable and hook the function
MEMORY_BASIC_INFORMATION mbi;
::VirtualQuery(function,&mbi,sizeof mbi);
if (::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect))
{
*function = newFunction;
DWORD protect;
::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&protect);
return;
}
}
thunk++;
}
Finally, the function that I have patched the DLLs to call in my code, in place of RegOpenKeyExW():
LONG WINAPI HookRegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
{
static const wchar_t* ieKey = L"Software\\Microsoft\\Internet Explorer";
// Never redirect any of the FeatureControl settings
if (wcsstr(lpSubKey,L"FeatureControl") != NULL)
return ::RegOpenKeyExW(hKey,lpSubKey,ulOptions,samDesired,phkResult);
if (wcsnicmp(lpSubKey,ieKey,wcslen(ieKey)) == 0)
{
// Redirect the IE settings to our registry key
CStringW newSubKey(m_registryPath);
newSubKey.Append(lpSubKey+wcslen(ieKey));
return ::RegOpenKeyExW(hKey,newSubKey,ulOptions,samDesired,phkResult);
}
else
return ::RegOpenKeyExW(hKey,lpSubKey,ulOptions,samDesired,phkResult);
}
Amazingly enough, this horrible hack actually works. But please, Microsoft, if you're listening, please fix this properly in IE10.

Resources