2

I am trying to write a PowerShellCmdlet in C#. It is a PowerShell command to make a REST API call. Here's a snippet of the important functions of the code -


    [Cmdlet(VerbsCommon.Get, "MXL3Firewall")]
    [OutputType(typeof(MXFirewallRule))]

    public class GetMXL3FirewallCommand : PSCmdlet
    {
        [Parameter(
            Mandatory = true,
            Position = 0,
            ValueFromPipeline = true,
            ValueFromPipelineByPropertyName = true)]
        public string Token { get; set; }

        [Parameter(
            Mandatory = true,
            Position = 1,
            ValueFromPipeline = true,
            ValueFromPipelineByPropertyName = true)]
        public string NetId { get; set; } 

        private static async Task<IList<MXFirewallRule>> GetFWRules(string Token, string NetId)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(
                    new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Add("X-Cisco-Meraki-API-Key", Token);

                // Created the request header above

                var streamTask = client.GetStreamAsync($"https://api.meraki.com/api/v0/networks/{NetId}/l3FirewallRules");

                // converting the serialized JSON response into a C# object
                return await JsonSerializer.DeserializeAsync<IList<MXFirewallRule>>(await streamTask);               
            }
        }

        private static IList<MXFirewallRule> ProcessRecordAsync(string Token, string NetId)
        {
            var task = GetFWRules(Token, NetId);
            task.Wait();
            return task.Result;
        }
        protected override void ProcessRecord()
        {
            WriteVerbose("Entering Get Firewall Rules Call");
            var list = ProcessRecordAsync(Token, NetId);
            WriteObject(list, true);
        }
    } 

I get the following error -

Get-MXL3Firewall : Could not load file or assembly 'System.Threading.Tasks.Extensions, Version=4.2.0.1,
Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file
specified.
At line:1 char:1
+ Get-MXL3Firewall -Token $token -NetId $netid
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-MXL3Firewall], FileNotFoundException
    + FullyQualifiedErrorId : System.IO.FileNotFoundException,RestToPSCommand.GetMXL3FirewallCommand

In the (.csproj) I have the following line -

    <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />

I tried updating the Nuget package as mentioned here, but it did not help. How can I fix this error?

Ankit Giri
  • 2,355
  • 2
  • 10
  • 15

3 Answers3

2

It is possible that what is happening is some other reference is trying to access version 4.2.0.1. of System.Threading.Tasks.Extensions. This is called DLL Hell and is often very difficult to fix. If this is the case, you are going to have to look at your references and try to figure out which one is referencing System.Threading.Tasks.Extensions version 4.2.0.1.

You can try to update your NuGet packages. It might solve the problem.

Good luck!!!

RustMan
  • 66
  • 4
1

The message Could not load file or assembly 'XYZ' or one of its dependencies. The system cannot find the file specified. is a notoriously bogus error message. It leads you to believe that assembly 'XYZ' was not found, and it may indeed be that assembly 'XYZ' is missing, but more often than not, what is in fact happening is that the assembly is there, but one of the dependencies is not.

For an assembly such as System.Threading.Tasks.Extensions, the most likely reason for one of its dependencies to be missing is a wrong DotNet version.

I have no direct solution for you, but I would recommend creating a host application that loads your assembly by making use of System.Management.Automation.Runspaces.InitialSessionState, so that you can troubleshoot the problem in its entirety from within a proper Visual Studio solution instead of from within PowerShell.

It will likely involve adding a HintPath or a BindingRedirect to your project file.

Once you get that host application to work, then your PowerShell script is likely to also work.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
1

I had this issue recently. You might need to review your web/app.config files, if you have them, where you need to have the dependentAssembly under Runtime setup correctly. Make sure the published version has this entry in it.

  <dependentAssembly>
    <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
  </dependentAssembly>
Daniel Lorenz
  • 4,178
  • 1
  • 32
  • 39