Search code examples
.netpowershellf#

Issue with Importing an F# PowerShell Module Due to Assembly Loading Errors On Fedora Linux


I am trying to create and import a PowerShell module written in F#. However, I am encountering issues when attempting to import the compiled DLL into PowerShell.

F# Code (Library.fs)

// Library.fs
namespace HiThereFsharp

open System
open System.Management.Automation

[<Cmdlet(VerbsCommon.Get, "Greeting")>]
type HelloWorld() =
    inherit PSCmdlet()

    let mutable name = ""

    [<Parameter(ValueFromPipeline = true)>]
    member this.Name
        with get () = name
        and set (value) = name <- value

    override this.ProcessRecord() =
        let whoDat =
            if String.IsNullOrEmpty(name) then
                "World"
            else
                name
        
        let greeting = "Hello " + whoDat
        this.WriteObject(greeting)

I built the project using:

PS ~/RiderProjects/HiThereFsharp> dotnet build

which completed successfully. The output DLL is located at:

/home/deca/RiderProjects/HiThereFsharp/HiThereFsharp/bin/Debug/net8.0/HiThereFsharp.dll

When I try to import the module:

PS ~/RiderProjects/HiThereFsharp> Import-Module /home/deca/RiderProjects/HiThereFsharp/HiThereFsharp/bin/Debug/net8.0/HiThereFsharp.dll

I get the error:

Import-Module: Could not load file or assembly 'FSharp.Core, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.

To resolve the missing FSharp.Core.dll, I ran:

dotnet publish -c Debug -o ./out -r linux-x64 --self-contained true

Now my out folder contains FSharp.Core.dll. However, when trying to import the module again:

PS ~/RiderProjects/HiThereFsharp/HiThereFsharp> Import-Module ./out/HiThereFsharp.dll

I get a different error:

Import-Module: Could not load file or assembly 'HiThereFsharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Assembly with same name is already loaded

I tried removing the module before re-importing it:

Remove-Module HiThereFsharp

This resulted in:

Remove-Module: No modules were removed. Verify that the specification of modules to remove is correct and those modules exist in the runspace.

Attempting to force import:

Import-Module -Force ./out/HiThereFsharp.dll

Results in the same error:

Import-Module: Could not load file or assembly 'HiThereFsharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Assembly with same name is already loaded

Environment Information

  • PowerShell Version: 7.5.0
  • F# Version: 8.0
  • PowerShellStandard.Library 5.1.1

My Csharp version works

namespace HiThere;
using System;
using System.Management.Automation;

[Cmdlet(VerbsCommon.Get, "Greeting")]
public class HelloWorld : PSCmdlet
{
    [Parameter(ValueFromPipeline = true)]
    public string Name { get; set;}
    protected override void ProcessRecord()
    {
    var whoDat = string.IsNullOrEmpty(Name) ? "World" : Name;
    var greeting = "Hello " + whoDat;
    WriteObject(greeting);
    }
}
PS ~/Documents/Programming/Csharp/HiThere> dotnet build
MSBuild version 17.8.5+b5265ef37 for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  HiThere -> /home/deca/Documents/Programming/Csharp/HiThere/bin/Debug/net8.0/HiThere.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.95
PS ~/Documents/Programming/Csharp/HiThere> Import-Module /home/deca/Documents/Programming/Csharp/HiThere/bin/Debug/net8.0/HiThere.dll           
PS ~/Documents/Programming/Csharp/HiThere> Get-Greeting -Name ""
Hello World

I'm not really sure what I'm doing wrong. Any insights would be greatly appreciated!


Solution

  • You cannot in .NET Core and beyond (generally) unload an assembly (you could in .NET Framework via AppDomains).

    Each test you run you need to start a new pwsh instance. When doing this I generally make use of the command line to run a script which does the loading and then leaves me at the new prompt.

    This also has the advantage of being in a consistent state (subject to bugs) each time making isolating issues much easier.

    (Unloading modules only works if it is purely PowserShell code.)