You might, for some reason, be building some XAML in code rather than markup. Starting with this XAML:
<!-- XAML markup -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
Here’s a flawed attempt to create the grid in code.
// C#
var autoWidth = new ColumnDefinition() { Width = GridLength.Auto };
var grid = new Grid() { ColumnDefinitions = { autoWidth, autoWidth } };
We create a column definition whose Width is Auto, and then create a grid whose ColumnDefinitions is two columns, namely two of our Auto columns.
This throws a confusing exception.
System.Runtime.InteropServices.COMException (0x800F1000): No installed components were detected.
What do you mean, no installed components were detected? Why does something need to be installed at all? Do I have to install a special component to be able to create XAML elements from code?
Okay, the first problem is an error code collision. The error message text is coming from error number 0x800F1000 which is SPAPI_ and belongs to the SETUPAPI facility. Unfortunately, XAML decided to put some of its error codes in the same facility, resulting in an error code collision. XAML defined error code number 0x800F1000 to mean “invalid operation” but gave it the same number as SPAPI_. Therefore, when various components try to decide the error code, they come up with the setup error instead of the XAML error.
Another XAML error code collision is “X is not a valid value for property Y” which has the numeric value 0x800F1001 and which collides with SPAPI_.
So the real problem has nothing to do with installed components. That’s just an unfortunate decode of the error code.
Fortunately, XAML provides a details string, which is easily overlooked because it’s two lines away and looks like part of another paragraph.
System.Runtime.InteropServices.COMException (0x800F1000): No installed components were detected.
Element is already the child of another element.
Source: Cannot evaluate the exception source.
The problem is that we are reusing the same ColumnDefinition object to describe two different columns. The markup creates two different ColumnDefinition objects, but our code version creates one object and inserts it twice.
To make our code equivalent to the markup, we have to create two ColumnDefinition objects, because that’s what the markup does.
// C#
var autoWidth1 = new ColumnDefinition() { Width = GridLength.Auto };
var autoWidth2 = new ColumnDefinition() { Width = GridLength.Auto };
var grid = new Grid() { ColumnDefinitions = { autoWidth1, autoWidth2 } };
And since we’re not reusing the column definition, we don’t need to give it a name.
// C#
var grid = new Grid() { ColumnDefinitions = {
new ColumnDefinition() { Width = GridLength.Auto },
new ColumnDefinition() { Width = GridLength.Auto }
} };
It’s convenient that this code does resemble the original XAML.
We thought we were doing the right thing by reusing an existing object with identical properties, but the XAML tree is a tree, and you can’t insert the same node into a tree in two different locations.
In this case, why not update the error code(s)? Whereas callers may attempt to handle specific error codes (one may suppose), one would still need to expect to handle… unexpected errors? I know there’s the historical compatibility with DOS file system error codes, but are returned error codes a contract with each API? Why not fix up the error facility issue?
The facility is part of the HRESULT error code, would probably have to wait for XAML to break ABI in another version first and even then it would be risky. Fixing it with a time machine is the best option.
@Raymond Chen The core problem here is Microsoft hiring fachidioten with egos larger than Mount Everest. Consider this example from another recent blog post:
<code>
Redefining common acronyms like that shows the full extent of someone's arrogance, hubris, and insularism -- not much different than your example of using same facility code for errors.
Worst part? They didn't stop at redefining them for the blog article, they used them in code:
<code>
Good luck explaining in the future what TCP means and filtering your searches.
Don’t worry, Microsoft will deprecate XAML in favor of some GUI Framework Next soon.