System.InvalidOperationException with RadRichTextbox from Telerik in WPF

If you have an HTML document that you import into the RadRichTextbox that has images and you are hosting WPF within MFC (c++), then you are probably running into this issue. Right along with all the people who have a steering wheel on the right side of the car driving around in the States. Yeah, all 1 of us.

Anyway, it’s an issue for us but here is the work around since Telerik will probably be slow to fix it, if they do. Quick backstory, they  load the images using WebClient instead of loading from disk. Better yet, they use the async methods on the webclient with a callback. We all know how much WPF loves stuff from other threads.

Here is the fix.

Snippet

  {//.........some function some where in time.
  var formatter = new HtmlFormatProvider();//The thing you use to load your html
    formatter.ImportSettings.LoadImageFromUrl += ImportSettings_LoadImageFromUrl;
    var doc = formatter.Import(html);//html is your variable with your html....from whereever
    boxxy.Document = doc;//boxxy is my richtextbox instance
}
 //the meat and potato's 
void ImportSettings_LoadImageFromUrl(object sender, LoadImageEventArgs e)
{           
    using (var file = new FileStream(e.Url, FileMode.Open))
    {
        e.ImageElement.UriSource = null;//prevent them from trying to load in background
        e.ImageElement.Init(file, Path.GetExtension(e.Url));//load from our stream
        e.ImageElement.ImageSource.Freeze();//prevent cross thread issue by freezing it.
    }
    e.Handled = true;
}

 

Happy Coding!

The dreaded VBA Ignore error in Excel Automation from .NET, and how to deal with it easily….0x800AC472

I have been dealing with automating Excel for quite some time, and it is not always very friendly. It gets much much worse when automating from .NET due to the COM interactions.  The project I was working on kept getting “random” errors which after debugging where VBA Ignore errors from COM. They simply meant that Excel was busy right this second, come back later.

Well, in code, they just blew up since who would expect it to tell you that. Normal people would think the call could just wait until it wasn’t busy and continue.

I wrote a class that will help you out a bit in automating Excel. Just throw this utility into one of your base assemblies.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace Seekford.CommonLibrary
{
    /// <summary>
    /// The delegate to use for the HandleExcelStatement inline delegates
    /// Just cast against an inline delegate.
    /// </summary>
    public delegate void ExcelAutomationStatement();

    /// <summary>
    /// Excel Helper Class for the VBA IGNORE HRESULT Error
    ///
    /// This class is designed to help minimize the coding required to handle the VBA IGNORE error that Excel can generate when it
    /// is in an unknown state. Excel does not use the proper COM notification mechanism to let the COM consumer know that Excel is in
    /// a state that the COM call will is not feasible. This state can be anything from a spell check popup to a cell being edited.
    /// It is very difficult to know when this error will occur and even occurs with no user interaction. (Possibly slow or asynchronous state changes?)
    /// Instead of writing a try loop with retry logic for every line of code that calls Excel automation, you can use this class
    /// to wrap the related lines call the HandleExcelStatement function.
    /// Brian Seekford
    /// </summary>
    /// <example>
    ///
    ///    ExcelAutomationHelperUtility.HandleExcelStatement((ExcelAutomationHelperUtility.ExcelAutomationStatement )delegate()
    ///                {
    ///                    if (askAboutMacros)
    ///                        excelApp.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityByUI;
    ///                    else
    ///                        excelApp.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityLow;
    ///                });
    ///
    /// </example>
    public sealed class ExcelAutomationHelperUtility
    {

        private static int defaultExcelAutomationVBAIgnoreMaximumRetries = 3;
        private static int defaultExcelAutomationSleepTime = 1000;
        private static bool defaultAllowUserDialog = true;
        private const string VBA_IGNORE_HRESULT = "0x800AC472"; //error code for the unknown state HRESULT. COM VBA_IGNORE flag

        /// <summary>
        /// By default, the number of times to retry before user prompt or rethrowing the error
        /// </summary>
        public static int DefaultExcelAutomationVbaIgnoreMaximumRetries
        {
            get { return defaultExcelAutomationVBAIgnoreMaximumRetries; }
            set { defaultExcelAutomationVBAIgnoreMaximumRetries = value; }
        }

        /// <summary>
        /// The number of milliseconds to wait between each retry
        /// </summary>
        public static int DefaultExcelAutomationSleepTime
        {
            get { return defaultExcelAutomationSleepTime; }
            set { defaultExcelAutomationSleepTime = value; }
        }

        /// <summary>
        /// The default value for showing the User the Retry Cancel dialog.
        /// </summary>
        public static bool DefaultAllowUserDialog
        {
            get { return defaultAllowUserDialog; }
            set { defaultAllowUserDialog = value; }
        }

        /// <summary>
        /// Processes a statement block with appropriate handling for the VBA ignore error. Uses default sleeptime, max retries, and default UI value
        /// </summary>
        /// <param name="excelStatement">Code block to execute (use an inline delegate)</param>
        public static void HandleExcelStatement(ExcelAutomationStatement excelStatement)
        {
            HandleExcelStatement(excelStatement, defaultExcelAutomationVBAIgnoreMaximumRetries, defaultExcelAutomationSleepTime, defaultAllowUserDialog);
        }
        /// <summary>
        /// Processes a statement block with appropriate handling for the VBA ignore error. Uses default sleeptime and max retries
        /// </summary>
        /// <param name="excelStatement">Code block to execute (use an inline delegate)</param>
        /// <param name="AllowUserDialog">Should the user be allowed to retry the operation?</param>
        public static void HandleExcelStatement(ExcelAutomationStatement excelStatement, bool allowUserDialog)
        {
            HandleExcelStatement(excelStatement, defaultExcelAutomationVBAIgnoreMaximumRetries, defaultExcelAutomationSleepTime, allowUserDialog);
        }

        /// <summary>
        /// Processes a statement block by executing the passed delegate.
        /// </summary>
        /// <param name="excelStatement">Code block to execute (Use a case inline delegate)</param>
        /// <param name="MaximumRetries">Number of time to rety the code statement</param>
        /// <param name="SleepTime">Total milliseconds to wait between retries</param>
        /// <param name="AllowUserDialog">Allow the user to retry the operation? Possibly letting them close and screens that may have popped up.</param>
        public static void HandleExcelStatement(ExcelAutomationStatement excelStatement, int maximumRetries, int sleepTime, bool allowUserDialog)
        {
            int retryCounter = 0; //number of time to try
            while (retryCounter < maximumRetries) //can we try again? (Could have just put a 1=1 here, but bad form).
            {
                try
                {
                    if (excelStatement != null) //if able, lets execute the code block
                        excelStatement();
                    return;
                }
                catch (Exception ex) //handle all exceptions
                {
                    retryCounter++;
                    if ((!ex.Message.Contains(VBA_IGNORE_HRESULT))) //if not our error, no retries. Just fail.
                        throw;

                    if ((retryCounter >= maximumRetries)) //if past retries
                    {
                        if (allowUserDialog) //can we ask the user to retry?
                        {
                            if (MessageBox.Show(ExcelAutomationHelperResources.ExcelUserWaitPrompt, ExcelAutomationHelperResources.ExcelUserWaitPromptCaption, MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, 0) == DialogResult.Retry)
                            {
                                retryCounter = 0;
                                continue;                                       // reloop here so that we don't need to wait another second
                            }
                            else
                                throw;
                        }
                        else
                            throw;
                    }
                    System.Threading.Thread.Sleep(sleepTime); //wait and try again.
                }
            }
        }

        ExcelAutomationHelperUtility()
        { }
    }
}

In order to use this class in your code, just follow the example. Basically, wrap your code in the delegate handler.

Example:

     ExcelAutomationHelperUtility.HandleExcelStatement((ExcelAutomationHelperUtility.ExcelAutomationStatement )delegate()
                    {
                        if (askAboutMacros)
                            excelApp.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityByUI;
                        else
                            excelApp.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityLow;
                    });

Visual C++, Precompiled Headers and Windows 7

I upgraded to Windows 7 and I really am enjoying the new interface….but….. I went to compile my ActiveX toolset projects that are all written in C++ and I started getting  precompiled header errors.

So I rebuilt and rebuilt and still got the error:

Error    1    fatal error C1859: ‘.Release/HTTP Wizard.pch’ unexpected precompiled header error, simply rerunning the compiler might fix this problem    d:SSIC++v3HTTP Wizard v3HTTPAccess.cpp    5    HTTP Wizard

So I rebuilt and rebuilt. No avail. I turned off Precompiled headers and then everything worked fine. What a pain.

It turned out the reason is due to the virtual tables being rebased by Windows 7 for security which totally screws up the precompiled header logic, which requires the headers to be in the same memory locations.

Apparently the development team at Microsoft knows about the issue and will eventually fix it. So, lets hope that service pack comes out soon.

I guess I am lucky my build machine is really beefy, but for active development having the precompiled header is nice.

So, go have a Margarita and the  compiler errors won’t bother you as much…..

Visual Studio 2008 toolbox loads slowly on large projects…

I am working on a very large project that has 70+ assemblies and dozens of different user controls. Every time I open up the Forms designer to work on a Form, it takes a ridiculously long time to do so. I just assumed this was my machine being underweight for the project.

So fast forward to today. I happen to have reset my workspace so my toolbox wasn’t set to auto-hide. As I opened up my Form to work on it,  I notice the Toolbox start flickering and loading all the controls in the project. Hmmm….Looks like we found why the Form load is so slow. Why on earth it takes up to minutes to read all the controls in the application is mind boggling, but now I know it does it sets me on the path to fix it.

After researching the settings in Visual Studio, I find this little hidden gem.

Tools->Options->Windows Forms Designer->General->AutoToolboxPopulate

Set this bad boy to False and you get rid of the annoying lag.  You will not get the controls to appear automatically in your toolbox now though, so be aware of that. You will need to add them manually. Oh, the horror. The horror……. Ha.

Enjoy the savings of time and hair pulling.

Autopopulate option

Windows 7, Cassini and Firefox run slow as molasses together…..

I have been developing on Windows 7 64-bit for a couple of weeks now and really like the Windows 7, but wow have my web applications run slow. I figured I would debug the issue later as maybe it was my data layer running slow. Each time I would execute a page refresh, load, navigate, whatever, it would take 2 seconds. Doesn’t seem like much, but when you click a button on a page 2 seconds is a very long time to watch it hang.

So, after getting sufficiently annoyed and impatient I was able to find that it was my app but was Firefox. Apparently Firefox has some sort of issue with IPv6.

The fix is amazingly simple.

  • In the address bar type ‘about:config’
  • Filter by ‘v6’
  • Disable ipv6 support.
Screenshot of option to disable/enable
Screenshot of option to disable/enable

Thanks to Peter Gregory for the help.

ASP.NET State server won’t start on Windows 7 64 bit. File is missing?

I went to launch my state server for ASP.NET to handle my local sites state information, in preparation for production, and the service just wouldn’t play nice. I tried to start it and it says the file doesn’t even exist.

Good times, right? So I went into the registry to see where it was pointing..%SystemRoot%Microsoft.NETFrameworkv2.0.50727aspnet_state.exe  (Yes, the path is visible on the service control properties as well)

I checked the disk and surprise surprise, it actually wasn’t there. However, there is this suspiciously obvious looking folder called Framework64. AHAH! You look in there and voila! It is in there.

Looks like the framework installer sucks. So I fixed the key and it magically started working. Amazing how when you point to the actual file it works,eh?

The fix is to change this:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesaspnet_state
key: ImagePath
%SystemRoot%Microsoft.NETFrameworkv2.0.50727aspnet_state.exe
to this:
%SystemRoot%Microsoft.NETFramework64v2.0.50727aspnet_state.exe

Happy coding!

XP decides opening new windows is no fun….

I happen to do a lot of multi-tasking. I have 4 copies of Visual Studio 2008 open with Management Studio for 2008 open plus a number of different browser windows and explorer folders. I eventually run into this invisible wall where no new windows get created. No new tabs, links stop working, applications won’t launch etc. Whats the temporary fix? I start closing windows and boom, I can now open up new ones.

It seems Windows has a very unfriendly bouncer that says the club is full and until people decide to leave, no one gets in.

I get these awesome event log entries:

Application popup: ftpit.exe – Application Error : The application failed to initialize properly (0xc0000142). Click on OK to terminate the application.

So, what is the fix? Disclaimer, changes to your system can cause inoperability if done improperly. Advice is without warranty 🙂

The system seems to allocate memory to the desktop heap by certain system boot parameters. All handles GDI object and User objects seem to use this 48mb desktop heap.

The solution I tried and sitting around to see if works well is to change these boot params.

I am changing the reg key:

HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerSubSystemsWindows
From : %SystemRoot%system32csrss.exe ObjectDirectory=Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16
To: %SystemRoot%system32csrss.exe ObjectDirectory=Windows SharedSection=1024,8192,2048 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off MaxRequestThreads=16
You can read more about it on MSDN.
If this solves your problem, let me know.

How to view an exception that wasn’t explicitly caught in C#?

So, you decided to do that catch statement without actually declaring the Exception err variable. Sure, code analysis said you weren’t using it. You didn’t want to log it, and you just thought you wanted to swallow the error whole and never see it again. Until…..

Wow, it keeps crashing in the Try block and you have no access to the error when it hits the catch now. What to do? Never fear.

Open your immediate window. Debug->Immediate.
Type $exception then hit enter.
Yep, there is your exception staring at you in all its glory.

Enjoy!

Entity Framework and Views.. Too many keys on the keychain…

I am currently working pretty heavily with the Microsoft Entity Framework for .NET. I just ran into a nice quirk in the Model Wizard for Views.

Well, it seems the model wizard is not able to intelligently determine the primary keys for a view so it resorts to deciding that any NON NULLABLE field must be a primary key. Retarded…yes.

So how to fix this? Well, as long as you don’t mind never using the wizard again you can go in and remove the entity key flag off the conceptual model fields and then delete the key references on the storage model. This all in the XML editor naturally, because of course you can’t do anything useful int the modeler.

Note: Once you fix your keys, if you rerun the Model Wizard to import/refresh tables, you will have the pleasure of hand editing the file again for all your views.

Will this be fixed in 4.0? We will wait and see

System.Diagnostics.Stopwatch is no longer my friend….

So..I have been thinking for quite some time, “Gee, wouldn’t it be nice to have a nice and easy to use timer class built right into the framework?”. I decided to go and use the lovely Stopwatch class to start building a lot of timing routines into my applications for debugging and logging purposes. The syntax was so easy and beautiful.


var sw = new System.Diagnostics.Stopwatch()
sw.Start();
DoWork();
sw.Stop();

Can’t get much simpler than that, right? Well…..that is if the stopwatch returned reliable results….

It seems on one our computers we run this code and a 23 second process returns 10.5 seconds…Yeah, same thing I thought.. What a bunch of crap!

So, I read something about Processor Affinity and CPU clock stepping that may be causing the issue. Either way, I don’t want to have to set the threads processor affinity or try and manage the CPU’s frequency just to take a simple time measurement……Back to the old


DateTime start = DateTime.Now();
DoWork();
TimeSpan elapsed = DateTime.Now() - start;

I know…not much difference, but didn’t the Stopwatch look so much cooler?