Subscribe: Rick Strahl's Web Log
http://feeds.feedburner.com/RickStrahl
Added By: Feedage Forager Feedage Grade A rated
Language: English
Tags:
application  browser control  code  control  core  dictionaries  iis  net core  net standard  net  sdk  web browser  web  windows 
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: Rick Strahl's Web Log

Rick Strahl's Web Log



Life, Surf, Code and everything in between



 



WPF Slow Window Loading due to Invalid SpellChecking Dictionaries

Mon, 25 Sep 2017 17:54:30 GMT

File this one into the Mr. Murpy Loves Me category: I ran into a nasty issue yesterday with Markdown Monster, which is a WPF application, by innocently adding an SpellCheck.IsEnabled=true attribute to one of my text boxes on the Weblog Publishing form: That's simple enough, and it works: Figure 1 - WPF Spellchecking is easy to add with a simple property on a TextBox control Why so slow??? But... on my dev machine there was a major problem: With that code in place the simple form that contains the spell check now took 3+ seconds to load. Say what? So I tried to track this down. I removed the spell check code and immediately the form popped up instantly. Add the spell check back in - 3+ seconds load time. Next, I tried this on another computer - a low end convertible no less - and guess what: No slowdown even with the spell check code in place. WTF? A quick look at the Visual Studio Profiler Analysis on my machine quickly pointed me at InitializeComponent() block of code after which the Profiler disappears into native code, so the issue is something internal to WPF. Dictionaries, Dictionaries It turns out WPF spell checking uses Windows dictionaries and these dictionaries are globally referenced in the registry. When I took a look at the global dictionary registration key in the registry at: HKEY_CURRENT_USER\Software\Microsoft\Spelling\Dictionaries Key: _Global_ I immediately found my problem: Figure 2 - Global dictionaries registered had a bunch of temporary non-existant files. Ugh! There were about 15 temporary dictionaries referenced in this section and sure enough these were the cause of my slow down. Once I removed all the temp dictionaries and left just the legit Office dictionary my form now just pops again immediately. The slowdown was caused by the errand dictionaries. I'm not sure why this is so incredibly slow. Given that the files referenced don't exist, there can't be any parsing happening. I also double checked to see that there weren't massive files in these folders which would make the look up really slow, but that's also not the case. Just having bad entries slows down the spell checker something fierce. Temporary Dictionaries? I also have no idea where these errand spell check dictionaries came from. I've been keeping an eye on this registry key and haven't seen temporary dictionaries returning. Clearly some application was writing out these files that subsequently get killed when my TMPFILES folder gets cleaned up by a daily scheduled task. But unfortunately I have no idea which one. I'll keep an eye on this key and see if it returns after more use. Moral of the Story At the end of the day, if you should run into a problem with slow spell checking code - check your registry and make sure the dictionaries in use are legit. It's definitely not something you are very likely to run into, but it's one of those strange edge cases that when they bite you, it takes a lot of time to track down. If you're unlucky enough bitten by this particular issue you landed here and can fix your problem quickly - unlike me who wasted a few hours tracking this down... this post created and published with Markdown Monster © Rick Strahl, West Wind Technologies, 2005-2017Posted in WPF   [...]



Conditional TargetFrameworks for Multi-Targeted .NET SDK Projects on Cross-Platform Builds

Mon, 18 Sep 2017 18:07:57 GMT

This is a short post that addresses an issue I ran into today when converting a project to .NET Core 2.0. I've been upgrading a host of my existing tools to .NET Standard/Core 2.0 and most of these projects have existing .NET 4.5 (or later) targets that I want to continue pulling forward. The new SDK project type makes it relatively easy to create libraries that do multi-targeting in your SDK style .csproj file: netstandard2.0;net45 Assuming you can get your code to build on both platforms, this simple directive will build assemblies and NuGet packages (if you turn the option on) for both platforms which is very cool. It'll work, but... Cross Platform There's a problem however when you do this multi-targeting. It works just fine on my local Windows machine where the specified target platform (.NET 4.5 SDK in this case) is installed. However, if I now try to build on a Mac which doesn't have a net45 SDK I get: /usr/local/share/dotnet/sdk/2.0.0/Microsoft.Common.CurrentVersion.targets(1122,5): error MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.5" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will beused in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend. The problem is of course that when you're trying to build on a non-Windows platform, or even on Windows when the net45 build targeting is not installed, the build fails. Why not just target .NET Standard? Initially I thought I'd get away with just targeting .NET Standard and use that from full framework applications. That works as long as you can get all the features you need from NetStandard. In my case however I'm porting very old code and there are number of dependencies on things that are not in .NET Standard and either require a separate set of libraries or simply can't run. So targeting native net45 (or whatever) is a good way to provide existing functionality while moving forward and also supporting .NET Standard/Core with a slightly diminished or altered feature set. But how do you deal with that on multiple platforms? You can change this: netstandard2.0;net45 manually to: netstandard2.0 and that works. The project builds, but only for the single target. It works but it's a nasty hack and I know if I do this manually, it will be forgotten at one point. There's a better way though... Conditional TargetFrameworks I asked if there's an easy way to deal with detectecting targets, and while the immediate answer is, "not directly", I kindly got a response from @DamienEdwards that offered a conditional approach: After a bit of experimenting with the right MSBuild invokations - and a little help from @andrewlocknet and @jeremylikness - I ended up with some conditional MSBuild blocks that work to do the right thing on Windows and in this case the Mac to build the project: Old code netstandard2.0;net45 3.0.0-preview1-0 Rick Strahl ... New Code netstandard2.0 netstandard2.0;net45