Friday, November 23, 2012
I changed that and now the root of the website redirects correctly, but folders and direct page links are still broken, they display some 'page not found' frame with the same spam links instead of redirecting to the matching folder on the dtdns.net site.
I hope this is not some 'feature' added to get more spam clicks from others' domains. If the situation persists, it will be bye-bye namezero/dotster after 10 years of using their services...
Meanwhile, if you can't access direct links to my website, use instead the dynamic DNS addresses I mentioned above.
Wednesday, November 21, 2012
Visual Studio 2012 uses in a couple of windows a control that allows searching the window content. Examples are Quick Launch, tool windows like Toolbox/SolutionExplorer/ErrorList, etc.
The control can be easily reused in your package and added not only into Toolwindows, but to any piece of UI. This article will show you which interfaces to implement or call to implement a searchable dialog or toolwindow, from both native or managed code.
Too many search controls
Various windows in Visual Studio needed search capabilities, and without a common control to use, in time they have implemented their own solutions. Unfortunately, this leads to UI inconsistencies, usability problems and user confusion. In Visual Studio 2010 there were at least 15 different control implementations for the same purpose – simple search. Below are a couple examples of windows from Visual Studio 2012 that still use private implementations (hopefully in time they'll converge and use the common way)
- Minidump editor window (File/Open/File, pick a dmp file) allows searching in the modules list. Uses WPF edit/button, doesn't have a consistent start icon, no indication the list is filtered, etc.
If you’re consider adding search capabilities to a window in your package, please don’t perpetuate these inconsistencies and use the control provided by the shell team; if you find missing features or have suggestions for improvement, you can send mails to VS Shell team to consider including in next versions.
Anyway, back to implementation.
The common search control in Visual Studio is implemented as a WPF control (the Microsoft.VisualStudio.PlatformUI.SearchControl class). Its data model set in DataContext property needs to be a Gel Microsoft.VisualStudio.Shell.Interop.IVsUIDataSource with specific properties/verb names; an example of such data source is the Microsoft.VisualStudio.PlatformUI.SearchControlDataSource class. The control can be directly referenced from Xaml, however, to make it work you’d have to deal with data sources (setting the necessary properties when the verbs are invoked, e.g. setting search status ‘in progress’ when StartSearch verb is called, etc, because the UI binds directly to some of the data source properties), with data source wrapper classes that are marked internal, etc. It can be done (the editor team used it this way), but clearly that’s not the intended way to use the control.
Instead, the control should be used through Visual Studio interfaces like IVsWindowSearch, IVsWindowSearchHost, IVsSearchTask, etc. Beside making the control accessible from native code (via COM), this abstracts you from the control implementation and let’s you focus only on setting up the search and performing the searches.
The GenerIC Case
In order to implement a searchable window, the owner needs to implement the IVsWindowSearch interface.
To setup the search, you need to create first a search host. Query the SID_SVsWindowSearchHostFactory service from the shell, and call IVsWindowSearchHostFactory.CreateWindowSearchHost() function. Pass in as first argument an object identifying the control to be used as parent for the search control. The type of pParentControl argument depends on the UI technology used in your window, e.g. FrameworkElement for WPF, ElementHost for WinForms, or an object implementing IVsUIWin32Element/IVsUIWpfElement and returning the parent indirectly via GetHandle() or GetFrameworkElement() methods.
Once you have the search host, call IVsWindowSearchHost.SetupSearch() and pass in the object implementing IVsWindowSearch interface. There are a couple of things happening during this call:
- The shell creates the SearchControl WPF control child of the pParentControl specified during host creation
- The shell creates a settings data source and calls IVsWindowSearch.ProvideSearchSetting. Your window gets a chance to override the default values and influence the behavior of the search control (e.g. set a determinate progress type, or change the search to be instant or on-demand, disable MRU items and the popup, etc)
- The shell calls IVsWindowSearch.ProvideSearchFilters and ProvideSearchOptions to discover filter and options that will be shown (if necessary) in the search control’s popup
- The shell creates the necessary data sources and associates them with the search control.
- If the search control uses MRU items, the search control will use the SVsMRUItemsStore to store/retrieve the items under the IVsWindowSearchHost.Category guid.
As the user types in the search control (default using delayed search start) and the search is started, the shell will call IVsWindowSearch.CreateSearch() function. The shell parses the user input and creates an object implementing the IVsSearchQuery interface (this allows for a consistent parsing of search strings into tokens, and identifying some tokens as filtering tokens). In response to the CreateSearch() call, the search control’s user needs to return an object implementing IVsSearchTask. The shell will then call IVsSearchTask.Start() from a background thread to perform the actual search job. Should the user click the X Stop button while the search is running, the Stop() function will be called on the UI thread on the search task. Should the user click the X Clear button after the search completes or is stopped, the shell will call IVsWindowSearch.ClearSearch()
While the search is running, the search task is supposed to call IVsSearchCallback.ReportProgress() if the search control’s progress type was changed to SPT_DETERMINATE. When the search is complete, call ReportComplete to notify completion and the number of results found.
When the search is no longer needed, one can call IVsWindowSearchHost.TerminateSearch() to release early the resources associated with the control, such as the data sources.
Visual Studio also optimizes for the most common use case. To create a searchable toolwindow you don’t have to worry about setting up the search – instead, simply implement the IVsWindowSearch interface on the same class that implements the tool window pane (IVsWindowPane or IVsUIElementPane), and the shell will take from you the burden of setting up the search and will provide a hosting place for the search control in the toolwindow frame area. Even more, classes in Managed Package Framework (MPF) from like Toolwindow already implement the necessary interfaces so you can simply make the search control appear in your window by overriding SearchEnabled property and return ‘true’.
The Search control in managed toolwindows, with shell hosting
Visual Studio SDK Contains a Walkthrough: Adding Search to a Tool Window article which has step-by-step instructions for using the search control in a managed toolwindow. The control is hosted by the shell in the toolwindow frame area, so you don’t need to worry about setting up the search (just override SearchEnabled property). The search-control in the searchable toolwindow from the article supports most recently used (MRU) items, search filters and options, and looks like like this:
Because the article doesn’t link to a downloadable end-to-end solution that you can try right a way, I’ve made available on my website the sample built from the articles instructions. You can download it from Example.TestToolWindowSearch.zip
The Search control in managed dialogs
The Example.SearchControlCS.zip sample demonstrates using the search control from a managed dialog. When built, the sample’s package adds 2 menu items in Tools menu (‘Searchable WinForms dialog’/’Searchable WPF dialog’).
Both dialogs set up a search control and implement similar search capabilities – filter a list of fruits with names read from resources.
To setup the search, one needs to define a container control that will act as parent for the search control and call IVsWindowSearchHostFactory.CreateWindowSearchHost with that container. For WinForms, the most ‘natural’ container choice type is ElementHost, which ensures WinForms-WPF interoperability. For WPF, just pass in any FrameworkElement (e.g. Grid, Border, etc) and the search control will be added as Child of that element.
The two searchable dialogs are implemented in SearchableForm.cs and SearchableWpfWindow.xaml respectively.
In this example there is only one search control per dialog (and the dialogs are ref counted being managed objects), so it’s easier to just implement the IVsWindowSearch interface directly on the dialogs. Should you need to use more search controls in a dialog you’ll have to create separate objects implementing IVsWindowSearch and pass them to IVsWindowSearchHost.SetupSearch when you create the search controls.
Because I implemented the same kind of search in both dialogs, I was able to reuse the search task class SearchableWindowSearchTask. It derives from VsSearchTask class in MPF and does the real search by overriding OnStartSearch method. It compares the typed user strings (from tokens of the search query) with the known fruits read from resources. The results are added to UI via 2 callback methods, clearResultsCallback and addResultCallback passed in constructor of the search task; this way the class can be used to report the results in both a WinForms ListBox or add them to an ObservableCollection bound to by the WPF dialog’s ListBox.
The OnStopSearch() function on the search task is called by the search control on the UI threads; the base class sets the TaskStatus to Stopped and reports completion so there isn’t need to override this function.
The OnSearchStart() function on the search task is called from background threads. This allows performing the actual search job asynchronously and you’d have to get out of your way to block the UI. The search task uses ThreadHelper.Generic.BeginInvoke() to call the UI update callbacks (because WinForms controls can only be accessed on the UI thread that created them, and also ObservableCollections can’t be modified from more than one thread). To make sure the results are not added to the UI by these callbacks after a search is canceled and the task is stopped, the code needs to recheck the value of TaskStatus on the UI thread before calling the callbacks.
There are a few things necessary mentioning when using the search control in a dialog:
- By default, the search control uses a color scheme that follows the active theme in Visual Studio (e.g. Light/Dark). A dialog usually does not follow the theme colors, and to avoid having a black search control in a light dialog you’d probably want to set UseDefaultThemeColors property in the data source to False, and the control will use a the default color scheme regardless of the current theme. There is a Utilities class in the Microsoft.Internal.VisualStudio.PlatformUI namespace that allows easier interaction with Gel data sources: Utilities.SetValue(pSearchSettings, SearchSettingsDataSource.PropertyNames.UseDefaultThemeColors, false);
- The search control uses data source properties that allows it to resize between Min/Max values (default 100/400). The control’s width will probably not fit by default all the parent container’s width, so you’ll need to set a larger ControlMaxWidth value to make sure the control will stretch to all available space from parent. E.g. use the dialog’s width: Utilities.SetValue(pSearchSettings, SearchSettingsDataSource.PropertyNames.ControlMaxWidth, (uint)this.Width);
Managed Vs. Native Windows
If you have the choice in your window that needs to use search, go with managed implementation. Using the search control from managed code is simpler, as there are a lot of helper functions and classes in Managed Package Framework that helps you with the implementation.
- The ToolWindowPane class already implements IVsWindowSearch interface, so if your toolwindow derives from this you can quickly made a toolwindow searchable by overriding SearchEnabled=true.
- The VsSearchTask class can be used as a base class for your search task, to implement the IVsSearchTask members and let you focus on the actual search (derive from it and override OnStartSearch)
- Classes like WindowSearchBooleanOption and WindowSearchCommandOption in Microsoft.VisualStudio.PlatformUI namespace allow to easily define search options (shown in the search control’s popup as checkboxes or links). The WindowSearchOptionEnumerator class can be used to return a VS-style enumerator over IEnumerable list of search options to be easily returned from IVsWindowSearch.ProvideSearchOptions.
- The WindowSearchSimpleFilter class allows implementing a search filter (shown in popup as a button) by specifying just the name and filter field. For more advanced filtering derive from WindowSearchCustomFilter class. The WindowSearchFilterEnumerator class can be used to return a VS-style enumerator over IEnumerable list of search filters to be easily returned from IVsWindowSearch.ProvideSearchFilters.
- There are function like SetValue/GetTypedValue in Microsoft.Internal.VisualStudio.PlatformUI.Utilities class that allow providing search control’s settings in the data source without having to deal with IVsUIObjects
- There is another utility class, Microsoft.VisualStudio.PlatformUI.SearchUtilities that has methods for creating search queries (IVsSearchQuery) or search tokens from strings, parsing search queries into tokens, etc.
If you choose for a native implementation, you’d have to deal with all the above yourself. You’d have to create your own COM classes even for something simple like changing search control’s setting. In the examples below I’ll give you some sample implementations for IVsUIObjects, IVsSearchTask, IVsWindowSearch, if you have to use filters or options you’d have write your own classes.
In addition, using the search control in a native dialog requires more code to write to ensure Win32-WPF keyboard interoperability and there are also some bugs (more on this later).
The Search control in NATIVE TOOLWINDOWS aND DIALOGS
The Example.SearchControlCpp.zip sample demonstrates using the search control from a native toolwindow and dialog. When built, the sample’s package adds 2 menu items in Tools menu (‘Searchable Native Dialog’/’Searchable Native Toolwindow’).
The two menu commands display a dialog and a toolwindow like these:
To use a Win32 window as the search control’s parent, one needs to pass in an object implementing IVsUIWin32Element interface and returning the HWND of the parent window from the GetHandle() function. The class CWin32Element does exactly that. The sample uses a Static Win32 control for the search control’s parent.
For both dialog and toolwindow (in SearchControlCppWindowPane and SearchControlCppDialog), the search is setup from OnInitDialog() function that is a handler for dialog’s creation message WM_INITDIALOG.
As mentioned above, there is no help from the native VSL (Visual Studio Template Library in SDK) on dealing with the search interfaces. The example defines its own COM classes CMyDialogWindowSearch (implementing IVsWindowSearch), CMySearchTask (implementing IVsSearchTask). If you need to use filters or options with the search control you’d also need to create your own classes implementing IVsWindowSearchSimpleFilter, IVsWindowSearchCustomFilter, IVsWindowSearchBooleanOption, IVsWindowSearchCommandOption and the enumerators IVsEnumWindowSearchFilters, IVsEnumWindowSearchOptions.
Also, in providing search control settings (e.g. for setting the search type to instant search), you’d have to pass in property values which are objects implementing IVsUIObject interface. In the sample I’m defining a class CVsUIBuiltInPropertyValue that can be used to create values for built-in Gel data types (int, strings, booleans, etc) and a couple of functions like Gel::CreateBuiltInValue to easily create such property values.
The 2 properties mentioned above for using the search control in managed dialogs (UseDefaultThemeColors and ControlMaxWidth) will need to be set for native dialogs, too. In addition, there are a couple of gotchas for using the search control in a native dialog:
- To ensure the Win32 dialog forwards keyboard input to the WPF control, the HwndSource window created by the search host, child of the dialog needs to intercept the WM_GETDLGCODE message and return DLGC_WANTCHARS | DLGC_WANTTAB | DLGC_WANTARROWS | DLGC_WANTALLKEYS to indicate it wants to process keyboard input. The SearchControlHostProc is the subclass proc that does this.
- To ensure correct tabbing into the search control I’m subclassing the Static parent of the search control, intercepting WM_SETFOCUS messages and forwarding focus activation to the HwndSource child. WPF will further focus the SearchControl. The SearchControlParentProc is the subclassed window proc of the Static control.
- To ensure tabbing out the search control, I’m intercepting WM_CHAR(VK_TAB) on the HwndSource and focusing the next parent dialog’s control in tab order.
All these could be done by the VS shell on your behalf, so hopefully in a future VS version these will no longer be necessary from the search implementer…
And there is another problem you may have noticed in the screenshot above: if the height of the parent Static control is bigger than needed by the search control, a black band appears under the search box. This is a bug that will have to be fixed in VS side (set the background brush on the HwndSource at creation time).
Samples used in the article
Friday, September 14, 2012
Visual Studio 2012 ships out of the box with 2 color themes, Light and Dark. Many users have complained the Light theme is too gray, depressing and ugly, some went as far as to claim they’d commit suicide if they’d be forced to look a whole day to this UI.
Personally I think that’s an exaggeration. However, while I absolutely like the Dark theme, and I could use the Light theme without problems, sometimes I’d prefer a bit more color.
For Visual Studio 2012 Professional/Premium/Ultimate there is a free Visual Studio 2012 Color Theme Editor extension that Matt Johnson wrote. It adds a couple color themes such as Red, Green, Blue, Purple, Tan, Dark with Light editor, Light with Dark editor. It also allows creating new themes, editing colors, etc.
Unfortunately, the extension is not available for Express editions of Visual Studio (and usually Express editions don’t allow loading extensions). It seems like on Express you’d be forced to use only the Light/Dark themes… Well, that’s not true!
Below I’ll tell you how to install the color themes on a Visual Studio 2012 Express, and I’ll exemplify with the newly released Visual Studio Express for Windows Desktop.
1) First, download the zip file http://www.alinconstantin.net/download/VS2012Themes.zip – it contains the 7 pkgdef files defining the colors of the default themes from Matt’s extension.
2) Now, create a folder under "%ProgramFiles%\Microsoft Visual Studio 11.0\Common7\IDE\WDExpressExtensions”, and lets name it “Themes”. Unpack the zip file in that folder.
3) Open a ‘Developer Command Prompt for VS2012” window. In the command line, type “wdexpress.exe /updateconfiguration”. This will make Visual Studio to read the pkgdef files on next restart, and import the color themes into registry.
4) Launch Visual Studio Express, and now you should be able to see the new themes and switch them in Tools/Options dialog, Environment/General tab
Should someone with a VS Professional/Ultimate install use Matt’s extension to create/edit a custom theme that you want to use on Express, that’s also possible. On the machine with the VS install look under ‘%LocalAppData%\Microsoft\VisualStudio\11.0\Extensions’ folder. There should be some subfolders with random names, and one of them will contain a Colors.pkgdef file containing the theme of interest (open it with notepad and you should see in the beginning the theme’s name to confirm). Copy that file in the WDExpressExtensions\Themes folder, rename it to give it a more appropriate name (repeat steps 2-4), and you should be able to use the new custom theme.
Friday, August 31, 2012
As you may know, Microsoft has replaced Windows Live Mesh from Windows Live Essentials 2011 with Microsoft
SkyDrive in the updated Windows Essentials 2012. While SkyDrive offers new interesting sync functionality, it does not completely replace all the functionality you had with Windows Live Mesh. I used to have a folder shared with my parents and sister where we could easily exchange pictures just by dropping new files in a local folder and have the file appear on my parent’s computer without any action necessary from their part. While Skydrive can be used for sharing, it requires my parents to look on the web in my Skydrive folder and manually download new files. (Why, Microsoft this usability regression?) If you’re like me and miss the removed functionality, please spend a few minutes and give Microsoft feedback about SkyDrive, if we’re many sending feedback hopefully Microsoft may reconsider the current decision.
Anyway, while I like the updated functionality from MovieMaker, SkyDrive, etc, I still want to run Live Mesh. But upgrading to Windows Essentials 2012 (downloadable from Essentials installer files for Windows 7, Windows 8, and Windows Server 2008 section) will remove Windows Live Essentials 2011 (downloadable from Essentials installer files for Windows Vista section). And the later will not install if you have already installed/upgraded to the 2012 version.
So, here is how to install Windows Live Mesh 2011 after installing Windows Essentials 2012:
- open an elevated command prompt
- cd %ProgramFiles%\Common Files\Windows Live\ (or “Program Files (x86)” on 64-bit OS-es)
- make sure you exit any running Windows Live program (Messenger, Writer, etc)
- “attrib –s –h .cache” to change the attributes of the .cache folder
- delete the folder “rmdir /q/s .cache”
- now you can run the wlsetup-all.exe from Windows Live Essentials 2011 (download links above) and it won’t complain anymore about the newer version installed.
I got the idea after finding Jonathan’s blog, where he made available for download a Live Mesh Installer tool: http://messengergeek.wordpress.com/2012/08/09/installing-windows-live-mesh-2011-with-windows-essentials-2012/ The tool downloads WLE2011 web version and installs it even if you have 2012 version installed. It didn’t work for me (it failed to delete the .cache folder, I may have had WL programs running), but at least it pointed me in the right direction to which folder needs to be manually deleted to make things work. Thanks!
Thursday, August 30, 2012
Over the last months I’ve been asked twice how should a Visual Studio package register a new standard previewer that will show up in the BrowseWith… dialog. It turns out that MSDN documentation is not very explicit about what’s possible and what’s not. Also, there are a couple of holes in Manage Packet Framework (MPF) that will need additional explanation to avoid them. So here’s this article and sample hoping to bring some light.
In Visual Studio, when you right click a html file in Solution Explorer and choose BrowseWith… you can access a dialog listing all system-installed browsers (auto-detected by Visual Studio), package-registered browsers or browsers added explicitly by the user.
For user-registered browsers, in Visual Studio 2012 the “Add program” dialog has been changed to allow specifying explicitly program’s arguments, and the code has been changed to support saving and passing the arguments at the browser’s invocation time. (To some extent arguments could have been passed in VS2010 as well in the Program edit box, but that was not evident to the user, plus there were bugs that caused the arguments to be discarded in various situations).
Packages can also register browsers via the SVsUIShellOpenDocument service. Here is how adding a new browser is supposed to work:
1) the package should write a key under “Visual Studio\11.0\AddStandardPreviewer” with the package Guid. Unfortunately there is no RegistrationAttribute helper class in MPF that can be used to declare these keys, so you’d have to write your own.
2) at the appropriate time, the environment parses the registry entries and calls ResetDefaults, passing in a value of PKGRF_ADDSTDPREVIEWER for the grfFlags parameter on the VSPackage. Unfortunately, the Package class in MPF already implements ResetDefaults() and does not allow derived classes to override virtual functions for registering previewers.
3) at that point the VSPackage should call IVsUIShellOpenDocument.AddStandardPreviewer. The function however does not have an explicit argument for passing browser’s arguments (it only has ‘string pszExePath’ suggesting the browser’s executable and not the actual command line string), so it may not be clear this thing is possible/supported.
To demonstrate how a package can register a browser, I wrote a sample, Example.BrowseWithExplorer.zip that implements a package registering 2 browsers: Internet Explorer InPrivate (allowing InPrivate previewing of the file of interest) and Internet Explorer Kiosk (which opens the browser without toolbars, menus, status bar, tabs, etc. – to close the browser use Alt-F4).
The sample defines a registration attribute, ProvideStandardPreviewerAttribute, that can be used on the package class to declare the package will register standard previewers. Hopefully, future versions of MPF will include such class so you won’t have to write your own.
Then, the package will have to re-implement the IVsPackage interface as shown in the above picture, and re-implement the ResetDefaults method so it can intercept the calls with __VSPKGRESETFLAGS.PKGRF_ADDSTDPREVIEWER flag
As for the browser’s invocation, when registering a standard previewer, the first argument in the AddStandardPreviewer allows specifying command line arguments for the previewer in addition to the path to the browser's executable. If there are no quotes in the path, the whole string is assumed to be the full path to the binary exe file of the previewer. However, if the pszExePath string beings with a quote (quotes are used around the executable binary) then arguments can be added separated by a space from the quoted filename.
%1, %URL or %url can be used in the arguments list, and Visual Studio will replace it at runtime with the name of the file to be previewed, (as a URL-formatted quoted string, e.g. "file:///C:/temp/My%20File.txt" ). If the arguments don't contain either of %1, %URL, %url, then Visual Studio will append the file name to be previewed to the pszExePath string before launching the previewer process with that concatenated string as arguments.
Multiple previewers can be registered with the same executable path if the list of arguments passed are different.
The 2 browsers registered by the sample invoke “IExplore.exe –k [filename]” for the Kiosk mode and “IExplore.exe –private [filename]” for InPrivate browsing, as described in Internet Explorer Command-Line Options MSDN article.
And finally, a few words about the system browsers listed in the dialog. When the OpenWith… dialog is displayed, Visual Studio will try to detect the browsers installed on the system. These browsers cannot be deleted from the dialog (well, you can delete them but they will re-detected and will appear back next time the dialog is reopen, unless the browser has been uninstalled at that point). In order to detect system browsers, Visual Studio looks in a couple of known locations:
- The shell\open\command for the ProgID associated with the http protocol for the current user or with the .htm files.
- The Default value under HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\[Executable.exe] or HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\[Executable.exe]
- HKCR\Applications\[Executable.exe]\Shell\Open\Command, for a couple of known executable of browsers with highest market use share.
- HKCU\SOFTWARE\Clients\StartMenuInternet and HKLM\SOFTWARE\Clients\StartMenuInternet, as described in this MSDN article http://msdn.microsoft.com/en-us/library/dd203067%28VS.85%29.aspx
Some browsers don’t write any version-independent registry values that can be used to locate their executable, hence they are not listed in the dialog unless they are also made the default system browser. Current examples of browsers with bad registration are SRWare Iron, Maxthon, Lynx. System browsers are encouraged to write their registration under StartMenuInternet so they can be detected by Visual Studio and Windows (and be listed in Windows’ Change Program Defaults dialogs as well).
The sample in this article can be downloaded from: http://www.alinconstantin.net/Download/Example.BrowseWithExplorer.zip
Wednesday, August 29, 2012
I was looking for Notepad’s arguments for a sample I’m thinking of writing; I’ve searched the net and found some of these, and had to investigate a bit to find out about the others. I’m a bit surprised it only supports so few flags, I was expecting at least a “go to line” capability. Anyway, here they are:
/A Ansi: notepad /a file.txt Opens the specified file as Ansi (overrides encoding auto-detection)
/W Wide: notepad /w file.txt Opens the specified file as Unicode (overrides encoding auto-detection)
/P Print: notepad /p file.txt Opens the file, prints its content to the default printer and exit
/PT PrintTo: notepad /pt “file.txt” “<printername>” prints the file to the specified printer. Both the filename and the printer name have to be in quotes, regardless of the names containing spaces or not. E.g.: notepad /pt “file.txt” “Send To OneNote 2013” or notepad /pt “file.txt” “\\Server\SharedPrinter”
/.SETUP SetupMode: E.g. notepad /.setup file.txt. I’m unclear what this is used for. It’s a weird mode, it does not repaint the window if it was started restored. You’d have to press Alt-Space and Maximize it to view the file content. The window has 2 sets of scrollbars in that case (one set is apparently unused), and it closes if Escape or Ctrl+D are pressed. Perhaps some setup programs invoke notepad with these arguments to display the EULA? Who knows.
That being said, for a better small & fast replacement of notepad, I suggest using SaneStudio’s NitroLite, downloadable from http://sanestudios.com/n2.html. No installation needed, at only ~100kb, it packs loads of features, syntax coloring, binary editor, etc.
Friday, August 17, 2012
I run yesterday into a weird error, for which I spent half of day to solve the problem. It’s unlikely you’d run into the same problem, so this is more for me to remember what I did to fix it in case I run into this again…
Yesterday I upgraded my laptop to Windows 8 Pro and installed Office 2013 Consumer Preview (upgrade from Win7 Ultimate/Office 2010). After the upgrade, when I tried to install latest Windows updates, I kept getting error 0x8024402F.
I tried the Help page on the error code, I launched the troubleshooter there (which claimed it could be a problem with the server connection, and claimed to have applied fixes), but all lead to nothing.
Knowing in the past I had trouble with Windows Update I searched my blog, which pointed out to problems related to UseWUServer set when I joined CorpNet. I left corp.microsoft.com domain and joined my home domain, but that only cost me 2 reboots and still didn’t fix anything.
I searched the the net for the error code, I found more KnowledgeBase pages with more FixIt installers which also did not fix the problem.
From http://support.microsoft.com/kb/836941 I found out the error code means WU_E_PT_ECP_SUCCEEDED_WITH_ERRORS. Further searches on the named error pointed to a WindowsUpdate.log file (instructions for reading it are at http://support.microsoft.com/kb/902093).
I looked in the log file and it contained more error details like this:
1060 15a8 PT WARNING: ECP: Failed to validate cab file digest downloaded from http://www.download.windowsupdate.com/msdownload/update/software/svpk/2008/06/1319061_d1590aa04b224974f0cf46ee7937bda90a815268.cab with error 0x80246003
Great, now I was looking for a different error code, 0x80246003. A search on the error number on Internet didn’t find any solution. The only thing I could find is a KB page http://support.microsoft.com/kb/938205 where I learned the error code 0x80246003 is WU_E_DM_UNKNOWNALGORITHM “A download manager operation could not be completed because the file metadata requested an unrecognized hash algorithm.”
Further searches on the named error lead nowhere. I tried re-registering the cryptographic providers dlls, comparing with other machines where things were working, all to no avail.
I run ProcMon searching for failures (when in doubt, run Process Monitor), but again this didn’t help.
I searched the internal Corpnet site for the error code or named error, but that also didn’t lead to a solutions.
Ultimately, I searched the source code. The error code is returned from only one place, from a failed test checking whether test keys are allowed. This had 2 parts:
- checking whether I had a file AUTest.cab in %windir%\SoftwareDistribution folder
- checking whether HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Test\AllowSHA1ContentHash = (dword)1
ProcMon should have shown these as well (at least the first one, to begin with), probably I just missed the line between so many other failures. Anyway, I set easily the registry value, but I didn’t have the file on any other machine where things were working fine.
After more CorpNet searches I found on http://mswikis/wukipedia/Wiki%20Pages/What%20is%20autest.cab.aspx where to get this test cab file (I needed to obtain a latest version anyway, since the file is signed and expires every 2 weeks).
I copied it to SoftwareDistribution folder, stopped and restarted the Windows Update service (‘net stop wuauserv’/’net start wuauserv’), and next time I tried Windows Update the update finally succeeded! After that I deleted the test cab file, and after that the updates still seem to work fine.
I suspect some internal test qfe was installed on my laptop when I joined CorpNet a while ago (giving the old ‘svpk/2008/06’ date of the update, suggesting some Win7 pre-service pack timeframe), and it was causing trouble now.
Anyway, I’m glad the problem seems fixed, but just in case here is this article to remind me the solution in case I run into this ever again.