Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeConverter (registration) throws NullRefException in PowerShell

Tags:

powershell

I have a PowerShell class, which I want to automatically be convertable from string.

So I defined a TypeConverter like this:

    class StringToAcmeStateConverter : System.Management.Automation.PSTypeConverter {
    [bool] CanConvertFrom([object] $object, [Type] $destinationType) {
        if($object -is [string]) {
            return Test-Path ([string]$object);
        }

        return $false;
    }

    [bool] CanConvertTo([object] $object, [Type] $destinationType) {
        return $false
    }

    [object] ConvertFrom([object] $sourceValue, [Type] $destinationType,
        [IFormatProvider] $formatProvider, [bool] $ignoreCase)
    {
        if($null -eq $sourceValue) { return $null; }

        if(-not $this.CanConvertFrom($sourceValue, $destinationType)) {
            throw [System.InvalidCastException]::new();
        }

        $paths = [AcmeStatePaths]::new($sourceValue);
        return [AcmeDiskPersistedState]::new($paths, $false, $true);
    }

    [object] ConvertTo([object] $sourceValue, [Type] $destinationType,
        [IFormatProvider] $formatProvider, [bool] $ignoreCase)
    {
        throw [System.NotImplementedException]::new();
    }
}

[System.ComponentModel.TypeConverter([StringToAcmeStateConverter])]
<# abstract #> class AcmeState {
    AcmeState() {
        if ($this.GetType() -eq [AcmeState]) {
            throw [System.InvalidOperationException]::new("This is intended to be abstract - inherit To it.");
        }
    }

    <# omitted #>
}

(Full code listing here: https://raw.githubusercontent.com/PKISharp/ACMESharpCore-PowerShell/deep-state/ACME-PS/internal/classes/AcmeState.ps1)

But PowerShell now throws a NullRefException from inside the pipeline. How would I make PS use the Converter correctly.

Update

Since this question did not contain enough information for a full repro, I created a gist containing the current (failing) code of the module: gist.github.com/glatzert/ba32f291b9155e6d19c29fbe9594a7c5

like image 379
TGlatzer Avatar asked Apr 19 '26 06:04

TGlatzer


1 Answers

TypeConversion with PowerShell classes has some non-obvious issues.

My first approach with the TypeConverter-Attribute fails with either an NullRefException or UnknownTypeException (this depends on the order of the classes in your *.ps1).

I dug into the Types.ps1xml and created the following xml:

<Types>
  <Type>
    <Name>AcmeState</Name>
      <TypeConverter>
        <TypeName>StringToAcmeStateConverter</TypeName>
      </TypeConverter>
  </Type>
</Types>

and added TypesToProcess to the .psd1 pointing to the aforementioned ps1xml.
This will fail, stating the Converter is not known, which probably means, that PowerShell will process that file either in another context as the module or prior to loading the module.

To fix that problem, I removed the TypesToProcess from the .psd1 and added Update-TypeData Types.ps1xml as last line to my module, thus it will be run automatically during module import - and voila! This works.

TLDR: If you want to register a TypeConverter defined in a PowerShell class, you need to use Update-TypeData

like image 144
TGlatzer Avatar answered Apr 21 '26 20:04

TGlatzer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!