Reputation: 860
I'm having trouble importing a module that contains a manifest, binary (root module), and a type file that defines a type converter or code property that references a type identified in the binary.
When I try to import the module, I can see from verbose output that the types files are loaded before the binary module's classes are imported:
VERBOSE: Loading module from path '...\bin\Debug\Module\manifest.psd1'.
VERBOSE: Loading 'TypesToProcess' from path '...\bin\Debug\Module\Type.PS1XML'.
Before the root module is loaded, I get the following error:
Import-Module : The following error occurred while loading the extended type data file: , ...\bin\Debug\Module\Type.PS1XML(64) :
Error: Unable to find type [MyRootModule.MyItemConverter].
At line:1 char:128
+ ... odule\Manifest.psd1 | Import-Module -verbose ; $Debu ...
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Import-Module], RuntimeException
+ FullyQualifiedErrorId : FormatXmlUpdateException,Microsoft.PowerShell.Commands.ImportModuleCommand
The question is, how can I load types after the root module is imported (without turning the entire module into a script that loads everything by calling Import-Module
and Update-TypeData
for every item in the module directory)? Or what other way would I have to get around this error and import the module and types at the same time?
Here's a quick example. This module (concocted on-the-spot as an example only) has the following items:
module\manifest.psd1
module\root.dll
module\type.ps1xml
This is the content of root.dll
namespace MyRootModule {
public class MyTestItem {
public string Name {get; set;}
public int Id {get; set;}
}
public class MyItemConverter : PSTypeConverter {
// code omitted for brevity
// effectively creates a 'MyTestItem' with id '1' for string input 'one', and vice versa.
}
}
This is the relevant content of manifest.psd1
@{
RootModule = 'root.dll'
TypesToProcess = 'type.ps1xml'
}
This is the content of type.ps1xml
<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>MyRootModule.MyTestItem</Name>
<TypeConverter>
<TypeName>MyRootModule.MyItemConverter</TypeName>
<TypeConverter>
</Type>
</Types>
If I load the binary module first, and then force-load the manifest or use update-typedata -PrependPath $pathToTypeFile
, everything works and I can use the converter as I'd expect to be able to (i.e. [MyRootModule.MyTestItem]1
returns a new instance of [MyRootModule.MyTestItem]
), which indicates that the problem has nothing to do with the converter itself.
TLDR; The powershell module is loading the types file before the binary, and since a type defined in the binary is not found at that time the import fails.
Upvotes: 2
Views: 671
Reputation: 860
Took me some time but I'll mark the answer here in case anyone else runs into this problem. There's a member of the module manifest that I had forgotten about/never paid much attention to, RequiredAssemblies. You can mark your dll as a required assembly as well as the root module to import it before types files are loaded. (Note: it still needs listed as the root or a nested module to import cmdlets.)
As an example, updating the manifest listed above to the following fixes the issue:
@{
RootModule = 'root.dll'
TypesToProcess = 'type.ps1xml'
RequiredAssemblies = 'root.dll'
}
Upvotes: 3