Windows Server AppX Installation Failures

We use Remote Desktop Services to provide our clients with SaaS access to our Windows desktop application.  An issue on one of our cloud servers running Windows Server 2019 has been plaguing me for a while.  Server performance was sluggish, and I noticed in Task Manager that wsappx was using high CPU.  That’s the AppX Deployment Service, which is responsible for installing UWP/Windows Store apps for each user.  Even though we don’t have Windows Store installed on the server, there are still certain system AppX packages that are installed for every user.  These are in the C:\Windows\SystemApps folder, and configuration of these apps is stored in the %localappdata%\Packages folder for each user.  I noticed that the Packages folder was empty for users added after a certain date.  Another symptom was that the Start menu did not function for these users.  Installation was failing and Windows continually retried the installation for these users.  Hence, the high CPU usage.  Running Get-AppXLog in Powershell revealed the following error:

Error 0x800705AA: While processing the request, the system failed to register the windows.stateExtension extension due to the following error: Insufficient system resources exist to complete the requested service.

Uh… okay.  It would be REALLY handy to know what that “insufficient resource” is! The most insufficient resource is this error message!  My ISP was stumped as well.  So, I started trying the usual things: DISM and SFC repairs, chkdsk, disabled firewall, etc.  I eventually copied an image of the server to my local machine and ran it in Hyper-V, so I could try more invasive things without affecting users on the live server.  I started uninstalling programs and even ran an in-place upgrade to Server 2022.  Nothing helped.  By now, many would have spun up a new server and called it a day.  In this case, that would disrupt the work of 200+ users, not to mention cause a bunch of support calls while these users tried to migrate to the new server.

One of the behaviors was that a folder for each app would be created in the Packages folder during installation, and then quickly deleted.  I needed to know if this was a symptom of the failure or the cause of it (maybe something else was deleting the folders during installation).  So, I loaded up Process Monitor (SysInternals) to do some forensics.  I filtered for events on the Packages folder and tried to install one of the AppX packages from Powershell.  I could see that wsappx was deleting the folder (not some other process), meaning the deletion was a symptom of the failure, not the cause.  Then, I changed the filtered on Command Line to capture all events of the wsappx service, which included all directories and registry access.  This was thousands of entries, so I found where the package folder was being deleted and started looking above it for clues to what caused the failure.  Lo and behold!  One nearby entry had the result INSUFFICIENT RESOURCES.  It occurred when attempting to add a value to the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Notifications.  I found that key in RegEdit and it took a while to open… a good sign I was on the right track.  I then tried to manually add a value to that key and got an error.  Bingo! Basically, that registry key was full and could not accept any more values. That led me to the following article:

Registry bloat causes slow logons or insufficient system resources error 0x800705AA in Windows 8.1 – Microsoft Support

That article points to a hotfix and a utility to clean up the registry bloat causing the problem.  Since it was designed for Windows 8.1, I did not feel comfortable installing it on my Windows Server 2019.  Fortunately, I found another utility that addresses the issue:

https://github.com/Lazy-256/clnotifications

I downloaded/unzipped clnotifications.zip then ran the fix.  It reduced the Notifications registry section from 256K entries to 500.  AppX package installations are now succeeding and wsappx is no longer hogging CPU. 

Maybe this article will help someone else that encounters the same error.  If this isn’t your exact problem, RegistrySizeLimit or excessive firewall entries could also be the culprit.  And if you get stuck, Process Monitor can help you find where the issue is.

ParallelFox 2.0 Released

ParallelFox 2.0 was featured in a session at Southwest Fox 2023 and provided to attendees in October 2023. It is now released to all FoxPro developers, and it contains the following new features:

  • In-process Workers
  • Single-command event handler
  • Reg-Free COM
  • Named Instances
  • Temporary Tables
  • Process Cancellation
  • Limited support for VFP Advanced

See the New in 2 and VFP Advanced Support pages for more details.

Installation

The easiest way to install ParallelFox 2.0 is to use Doug Hennig’s FoxGet Package Manager. FoxGet downloads only the files necessary to use ParallelFox, runs install.prg, and adds files to your project.

If you want to download all ParallelFox files, including the Help file and examples, follow the Manual Installation instructions on GitHub.

The Southwest Fox 2023 session video, white paper, and slides will be made available to all FoxPro developers at a later date.

Reg-Free COM with Out-of-Process Servers

Generally speaking, a COM object must be registered in the Windows registry to be used by applications. In the past, I have not had an issue with this, as it was just another step in the installation package. In recent years, we have been offering cloud services to our clients. On a single server, we now have multiple clients and dozens of users all relying on the same COM objects. This makes it more difficult to deploy updates to a COM object. It also prohibits having multiple versions of a COM object, because only one version can be registered at a time (AKA “DLL Hell”). These days, registration-free COM is looking a lot more attractive, as it enables multiple “side-by-side” versions of a COM object that can be managed independently. It also allows deployment without the admin elevation that is normally required to register a component.

For a while now, we have had the ability to use custom manifests that allow applications to make use of COM objects without registering them. Some Visual FoxPro devs might make use of tools by Craig Boyd to assist with this. Visual Studio provides tools for automating manifests as well. There’s one catch… this technique only works with in-process DLL COM servers. I often use out-of-process EXE COM servers for Visual FoxPro because they have fewer limitations than DLLs. Is there a way to use an EXE COM server without registering it first?

A cursory Google search might lead you to answer “No”, but Larry Osterman of Microsoft fame tells us otherwise. In his blog post from 2005, he points out a “clever trick” to accomplish this: “When COM tries to activate a COM object, before it looks in the registry, it looks to see if there’s a server already registered for that class.” In more detail… if the COM server EXE has already been launched and CoRegisterClassObject() was called BEFORE instantiating the COM object in a client application, the COM object can be used even though it is not in the Windows registry. Clear as mud?

First of all, we are talking about two different types of registration here. There’s the standard registration of a COM object into the Windows registry that we are all familiar with. Then there’s CoRegisterClassObject(), which registers out-of-process COM objects in memory with the Windows COM/OLE system (not the Windows registry). This is done from inside the COM server, and it is what allows the COM objects to be found by client applications. Okay… so how do we call CoRegisterClassObject()?

Good news! No Win32 API calls are necessary. Your out-of-process COM server already knows how to do this, you just have to tell it to do so. There is not a mandatory standard for all COM servers, but Microsoft convention is to include the following parameters when launching the EXE: “/automation -Embedding”. This convention is used for VFP COM EXEs, MS Office, and probably many others. Here’s some VFP code for launching the COM EXE:

Local lcRun
lcRun = [Run /n "] + FullPath("MyCOMServer.exe") + [" /automation -Embedding]
&lcRun

I have used FoxPro’s RUN command to launch the executable. Win32 API ShellExecute() could be used as well, although I should mention I did run into some timing issues that I didn’t bother to troubleshoot. CreateProcess() is another option.

If your COM server doesn’t use this convention, register and instantiate it normally on your dev machine. Then open Windows Task Manager, go to the Details tab, and enable the Command Line column. That will show you what parameters were included when the COM EXE was launched.

At this point, the COM EXE server is running and ready to be used by a client application. You should be able to use VFP’s CreateObject() to instantiate the object, right? Unfortunately, no. CoRegisterClassObject() has registered the object in memory using a “Class ID” (CLSID), which is a GUID. CreateObject() expects the more friendly “Program ID” (ProgID) that we are familiar with. Behind the scenes, CreateObject() calls CLSIDFromProgID() to lookup the ProgID in the Windows registry and return the corresponding CLSID, then it calls CoCreateInstance() using that CLSID. We want to avoid using the Windows registry for deployment, so job one is to find the CLSID for our COM object. To do that, you can look in the Windows registry on your development machine and find your ProgID under HKEY_CLASSES_ROOT. For VFP, there is also a VBR file in the project folder that you can open in a text editor and find an entry like this:

HKEY_CLASSES_ROOT\MyCOMServer.MyObject\CLSID = {12345678-90AB-CDEF-1234-567890ABCDEF}

Now that we have the CLSID, we are ready to instantiate the object. Again, VFP’s CreateObject() will not accept a CLSID, but CreateObjectEx() will!

#DEFINE MYCOMOBJECT_CLSID = "{12345678-90AB-CDEF-1234-567890ABCDEF}"
loMyComObject = CreateObjectEx(MYCOMOBJECT_CLSID, GetEnv("COMPUTERNAME"))

I should point out that this calls CoCreateInstanceEx() rather than CoCreateInstance() behind the scenes. This is typically used to instantiate a remote DCOM object on a different machine, but I have designated that it is on the current computer. I have not encountered any repercussions from doing this (performance or otherwise), but your mileage may vary. You could call CoCreateInstance() directly to instantiate the object as a “Local” out-of-process server instead.

We now have everything we need to instantiate an out-of-process COM object without registering it, but one caveat remains. FoxPro’s RUN command and ShellExecute() cause the client application to lose focus when the COM server EXE is launched. This doesn’t happen when instantiating a COM object that has been registered the normal way. You could probably prevent this by using CreateProcess() to launch the server, but it has a complex API. Using LockSetForegroundWindow() seems to avoid the unwanted behavior. Here’s the complete code:

#DEFINE MYCOMOBJECT_CLSID = "{12345678-90AB-CDEF-1234-567890ABCDEF}"
Local lcRun, loMyComObject 
DECLARE INTEGER LockSetForegroundWindow IN user32 INTEGER uLockCode
LockSetForegroundWindow(1) && lock	
lcRun = [Run /n "] + FullPath("MyCOMServer.exe") + [" /automation -Embedding]
&lcRun
loMyComObject = CreateObjectEx(MYCOMOBJECT_CLSID, GetEnv("COMPUTERNAME"))
LockSetForegroundWindow(2) && unlock

Double Trouble with COM Interop

I have been calling FoxPro code from C# via COM Interop (using DotNet2Fox) for several years, but I ran across an interesting issue last week. I have some FoxPro code that performs calculations and returns the results to .NET. I expected one of those values to be zero, but according to C#, it was -3.5527136788005e-15. Huh? After repeated tests, I got the same result.

I was assigning the FoxPro results to C# variables of type “decimal”. The C# compiler had already informed me that FoxPro was returning values with type “double” over COM. I have heard about the tension between binary and floating point math in computers before, but in practice, I have never run into an issue. I initially thought that the double-to-decimal conversion in C# was exposing this tension. As a test, I changed my C# variables to type double, but the problem persisted. I stepped through my code in FoxPro, and according to the debugger, the value was indeed zero. What the heck was going on?

I came up with a simpler calculation to reproduce the issue: 1.23 + 4.56. The result should be 5.79, right? Enter ? 1.23 + 4.56 in the FoxPro command window, and that’s what you’ll get. However, run the code below in C# and the result will be 5.790000000000001.

        dynamic vfp = Activator.CreateInstance(Type.GetTypeFromProgID("VisualFoxPro.Application", true));
        var result = vfp.Eval("1.23 + 4.56");
        vfp.Quit();
        return result;

Had I run across some glitch with COM interop? I needed to be certain that calculations done in FoxPro would come over to C# accurately. This was disconcerting.

Upon further thought… someone would have surely caught an issue like this with general COM interop, right? Maybe this was more on the FoxPro side. Then, I remembered a blog entry Christof wrote years ago on Significant digits in Visual FoxPro that mentions some oddities with 15-digit floating point calculations in VFP. Hmmmm… 15 digits. That’s the same precision of double types in C#. And look how many digits are after the decimal place in 5.790000000000001. So, I tried another test in the FoxPro command window:

SET DECIMALS TO 15
? 1.25 + 4.56

There it is! Now, FoxPro shows 5.790000000000001! Clearly, this is either some kind of binary-to-floating-point issue or something to do with that 15th digit, but SET DECIMALS masks that most of the time. SET DECIMALS is a mysterious command. It specifies the number of decimal places that will be displayed from calculations. It apparently also affects comparisons: ? 1.25 + 4.56 = 5.79 returns .T. when SET DECIMALS TO 2. But SET DECIMALS TO 15 and the same expression returns .F. Weird! SET DECIMALS appears to have no effect on calculated values returned over COM interop and always returns the full 15-digit precision of a double.

So, that explains why I had the issue when using COM interop. How do we fix it? Simple… round the calculated result to the desired number of decimals in FoxPro before returning the result, or in C# after the result is returned from FoxPro. In fact, I was able to resolve by rounding down to 14 digits (eliminating the troublesome 15th digit), but I can’t guarantee that would always work. By the way…if you want C# rounding to have the same behavior as FoxPro rounding, specify MidpointRounding.AwayFromZero:

    public static double FixDouble(double number, int roundDecimals = 14)
    {
        return Math.Round(number, roundDecimals, MidpointRounding.AwayFromZero);
    }

BindWinEvent and FoxTabs 1.3

Years ago, Greg Green reported that FoxTabs was conflicting with his custom VFP editors, due to VFP’s limitations binding to Win Msg events. Greg wrote this framework to deal with the limitation, and I made some modifications. I wrote about this on my blog, and BindWinEvent has been included with FoxTabs ever since.

More recently, I found that FoxTabs was conflicting with Doug Hennig’s ProjectExplorer for the same reason, so I implemented BindWinEvent in ProjectExplorer. Doug reported back with some fixes to issues he found. I then realized that BindWinEvent needed a separate repository of its own, so it is now a separate project and part of VFPX. If you have an IDE utility that binds to Win Msg events, I recommend using BindWinEvents to avoid conflicts with other utilities.

FoxTabs hasn’t had any love since 2014, so while I was in there, I figured I would investigate a long-standing issue where a label would disappear on some of the tabs. This turned out to be a compatibility issue with PEM Editor, because it sometimes changes the window title to include more information. Once I accounted for that, no more disappearing labels!

While working on that issue, I ran across some old code from Jim Nelson that used _EdGetEnv() from FoxTools.fll to determine the type of each window. I had never learned about that function before. I used it along with some other tricks to improve window type detection and the icons displayed for each type. Instead of a bunch of Fox heads, the tab icons are now a lot more informative and colorful.

You can get all these improvements in FoxTabs 1.3, available on GitHub or Thor Updater (coming soon if it’s not there already).

DotNet2Fox is now part of VFPX!

I’m happy to announce that DotNet2Fox has been accepted as part of the VFPX project.  “What is DotNet2Fox?”, you say?  Good question!  DotNet2Fox was first presented and released at Virtual Fox Fest 2021 (October), and I somehow failed to mention that here on my blog!  That is being rectified right now…

DotNet2Fox is an open-source library that simplifies calling Visual FoxPro code from .NET desktop and web applications. Have you tried your hand at COM interop only to be met with limitation after limitation? Did you find that exposing your existing FoxPro code over COM would require a major refactoring effort? DotNet2Fox provides a simplified interface for calling into existing real-world FoxPro code, and without all those limitations.

Over the past several years, I have been working to surface features from my desktop applications and make them available on the web via ASP.NET.  I found that the classic approach to COM interop recommended by Microsoft a couple of decades ago did not fit my needs. Over time, a library emerged to meet those needs: DotNet2Fox.

Geek Gatherings has graciously made recordings of Virtual Fox Fest sessions available to the entire FoxPro community on YouTube.

You can also get the whitepaper (documentation) and examples at the GitHub Wiki. Yes, full source code is on GitHub as well.  If you need help with DotNet2Fox, please start a Discussion or report an Issue. We’ll even accept Pull Requests.  I look forward to working with more folks  on this project.

COM Interop with .NET Core 3.x and .NET 5.0

I previously wrote about COM Interop with .NET Core 1.0 and .NET Core 2.0. I haven’t had a chance to write it about it since, so this discusses both .NET Core 3.x and .NET 5.0.  If it wasn’t obvious from the previous articles, this is about calling COM components from .NET.  I believe work was done using COM interop in the other direction (calling .NET from COM components), but it is not discussed here. If you need to call .NET from Visual FoxPro, wwDotNetBridge is much simpler than standard COM Interop and highly recommended.

.NET Core 3.x

.NET Core 3.0 was a big release.  Unlike ASP.NET Core 2.0, ASP.NET Core 3.0 removed the option to run on .NET Full Framework 4.x.  It only runs on .NET Core, meaning you can no longer fall back to 4.x for COM Interop support.  WinForms and WPF desktop applications were also brought into the Core fold for the first time, and some of those apps might rely on COM Interop.

Some progress was made in 3.0, but the overall COM Interop story is the same as .NET Core 2.0.  That is, COM Interop works, but late binding using the C# dynamic keyword still doesn’t function.

dynamic excel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application", true));
excel.Visible = true;
Console.WriteLine("Press Enter to close Excel.");
Console.ReadLine();
excel.Quit();

As with .NET Core 2.0, the above code will function in .NET Framework 4.x, but in .NET Core 3.x, an exception occurs:

‘System.__ComObject’ does not contain a definition for ‘Visible’

Microsoft had planned to bring full support for the dynamic keyword to .NET Core 3.0, but the job proved to be too large, so it was deferred. However, there are a couple of improvements.

In .NET Core 2.0, you had to jump through hoops to create an interop assembly for COM components.  In .NET 3.x projects with Visual Studio 2019, you can simply right-click on the project and select “Add COM Reference”.

In addition, some folks put together a workaround using a DynamicObject wrapper to access properties/methods on COM objects using the dynamic keyword, so you don’t have to use ugly reflection calls.  This may not work in every scenario, but you may find it meets your needs on .NET Core 3.x.

.NET 5.0

.NET 5.0 was just launched at .NET Conf on November 10, 2020. It represents the reunification of .NET Core and .NET Full Framework, hence the dropping of “Core” in the product name.  .NET 4.x remains a part of Windows and will continue to be supported indefinitely.  Some things are not coming over to .NET 5, such as Web Forms, WCF, and WWF… at least not by Microsoft. There are open-source projects to port WCF and WWF.  But what about COM Interop?  In my testing, it just works.  Indeed, Microsoft finished the work to support using the dynamic keyword with COM objects.  There’s not much more to say than that.  If incomplete COM Interop support has been keeping you on .NET Full Framework 4.x, now may be the time to take a look at .NET 5.0.

ParallelFox 1.3 Released

The last release of ParallelFox was over 8 years ago in January 2012.  Also, 3 years have somehow elapsed since CodePlex was shut down and VFPX moved to GitHub. Time most definitely flies!  I have been using Doug Hennig’s Project Explorer on some projects. I decided to implement it with my VFPX projects, as well as do some housekeeping on GitHub. In the process, I noticed there were several tweaks/fixes (things checked in years ago on CodePlex) that never made their way into an official release.  So, I packaged those changes up into a new release: ParallelFox 1.3.

POTENTIAL BREAKING CHANGE: This release includes and requires ParallelFox.exe version 2.0 dated March 5, 2012. If you are using a previous version, this version needs to be installed and registered. This release is otherwise backwards compatible with previous versions, and it should not require changes in your code.

NOTE: If you previously cloned/downloaded the GitHub repository, you already have the changes in this release, including the latest ParallelFox.exe.

COM Interop with .NET Core 2.0

We previously discussed that COM Interop does not function in .NET Core 1.0.  What about .NET Core 2.0?  The answer is YES… with limitations.

The first and most obvious is that COM Interop only works with Windows, not other platforms.

The second limitation is that the .NET Core implementation does not include IDispatch, which means that late binding is not supported.  Almost 10 years ago, Microsoft introduced the dynamic keyword in C# 4.0, which made late binding with COM and other platforms much easier.

dynamic excel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application", true));
excel.Visible = true;
Console.WriteLine("Press Enter to close Excel.");
Console.ReadLine();
excel.Quit();

The above code will function in .NET Framework, but in .NET Core 2.0, an exception occurs:

‘System.__ComObject’ does not contain a definition for ‘Visible’

If you look in Task Manager, you’ll see that Excel.exe has indeed started, but the object members cannot be access directly without IDispatch.  To work around this, you can use interop techniques that pre-date the dynamic keyword.

Interop assemblies are wrappers that enable .NET Core to interact with COM objects using early binding.  Microsoft provides interop assemblies for Office automation on NuGet and elsewhere.  Once the assemblies are installed, this code will work:

using Excel = Microsoft.Office.Interop.Excel;
...
var excel = new Excel.Application();
excel.Visible = true;
Console.WriteLine("Press Enter to close Excel.");
Console.ReadLine();
excel.Quit();

Aside: For web applications, Office automation is not recommended.  Check out the Open XML SDK.

What about your own COM objects? .NET Core projects do not provide a means to reference them directly.  However, you can create a .NET Framework 4.x project and add a reference to the COM object.  This will create an Interop.MyCOMObject.dll assembly in the obj/Debug folder, which you can then reference directly in the .NET Core project.

A COM object may return other objects that are not part of the type library, and early binding is not an option. This happens often in my Visual FoxPro interop code. You can use reflection to access the object members.

object excel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application", true));
excel.GetType().InvokeMember("Visible",BindingFlags.SetProperty, Type.DefaultBinder, excel, new object[] { true });
Console.WriteLine("Press Enter to close Excel.");
Console.ReadLine();
excel.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, excel, null);

The dynamic keyword makes for more natural code, but you can make reflection less cumbersome than above with your own wrapper methods.

For the adventurous, the Powershell team has created their own implementation of IDispatch. I don’t know how reusable this implementation is, but it may be worth a look.

If you’re using in-process (DLL) COM servers, be aware of 32-bit vs 64-bit issues. For web  applications, take a look a Rick Strahl’s post on STA components. I don’t know if these techniques are available in .NET Core.  In my experience, these issues do not apply with out-of-process (EXE) COM servers, but your mileage may vary.

Lastly, keep in mind that ASP.NET Core 2.0 continues to run on .NET Framework 4.x, in addition to .NET Core.  If you’re already restricted to Windows, there aren’t many reasons to prefer .NET Core over the full framework (yet), so it remains the best option for COM Interop.  That said, it’s good to know these possibilities exist with .NET Core.

Microsoft has been choosy about what they bring over to .NET Core.  Over time, they have been finding their way towards more parity with .NET Framework. It was recently announced that WinForms/WPF will be coming to .NET Core 3.0. They may find that a lot of existing code relies on late binding.  I would not be surprised if IDispatch makes a comeback.

Welcome to JoelLeach.net!

Nearly a decade ago, I started this blog on the Foxite.com Community Weblog, a free service made available to the FoxPro community by Eric den Doop.  I wanted more control on the admin side — especially for dealing with spam – so I have moved the blog to my own site: joelleach.net.

All posts/comments have been retained, and links to the old site should automatically redirect to the new site.  Please update your RSS readers to point to the new feed.

Special thanks to Eric for making this service available to the community and for hosting my blog all these years.