Cory Gehr
Cory Gehr

Reputation: 127

Cannot run PowerShell scripts in Azure Functions v2

I'm trying to write a Function App using .NET Core in Azure Functions v2. When using the Microsoft.Powershell.SDK package from Nuget (required for .NET Core PowerShell runtime) I cannot get Visual Studio to copy the System.Management.Automation library to the bin with my Function App.

This results in the following error:

System.Private.CoreLib: Exception while executing function: Function1. TestPowershellInFunction: Could not load file or assembly 'System.Management.Automation, Version=6.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified. System.Private.CoreLib: Could not load the specified file.

I've reproduced this in an existing Azure Function and a new Solution by simply creating a Timer function and adding the following snippet:

PowerShell shell = PowerShell.Create();
IEnumerable<PSObject> result = shell.AddScript("Write-Output 'Hello, World!'").Invoke();

foreach(PSObject line in result)
{
    log.LogInformation(line.ToString());
}

This works on a new Console App with the PowerShell Nuget installed, but when added to the Function App I get the error. I do notice that System.Management.Automation doesn't get put in the bin directory with a regular Console App but I'm not sure how to interpret this. I know it's a System library but I can't use it unless the Nuget is installed, so I don't know if this is a special case. In both scenarios I'm using v6.1.1 of the PowerShell Nuget.

Is this a known bug with Functions v2? Or am I missing something?

Upvotes: 1

Views: 750

Answers (1)

Jerry Liu
Jerry Liu

Reputation: 17790

It's a known issue that Function can't load runtime assemblies([FunctionProject]\bin\Debug\netcoreapp2.1\bin\runtimes) correctly.

The workaround is to move assemblies to output dir bin manually. Right click on your function project and Edit <FunctionProject>.csproj. Add following items to achieve our goal.

 <PropertyGroup>
    <SDKVersion>6.1.1</SDKVersion>
    <SDKPlatform>win-x86</SDKPlatform>
  </PropertyGroup>

  <ItemGroup>
    <None Include="
      $(USERPROFILE)\.nuget\packages\system.directoryservices\4.5.0\runtimes\win\lib\netcoreapp2.0\System.DirectoryServices.dll;
      $(USERPROFILE)\.nuget\packages\system.management\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Management.dll;
      $(USERPROFILE)\.nuget\packages\system.management.automation\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\System.Management.Automation.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes\win10-x86\lib\netstandard1.6\Microsoft.Management.Infrastructure.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Management.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.utility\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Utility.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.diagnostics\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Diagnostics.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.sdk\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.SDK.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.security\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Security.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.coreclr.eventing\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.CoreCLR.Eventing.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.consolehost\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.ConsoleHost.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.markdownrender\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.MarkdownRender.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.wsman.runtime\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Runtime.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.wsman.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Management.dll;
      ">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
  <Target Name="CopyRuntimeToBin" AfterTargets="Build">
    <Copy SourceFiles="
      $(USERPROFILE)\.nuget\packages\system.directoryservices\4.5.0\runtimes\win\lib\netcoreapp2.0\System.DirectoryServices.dll;
      $(USERPROFILE)\.nuget\packages\system.management\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Management.dll;
      $(USERPROFILE)\.nuget\packages\system.management.automation\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\System.Management.Automation.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes\win10-x86\lib\netstandard1.6\Microsoft.Management.Infrastructure.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Management.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.utility\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Utility.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.diagnostics\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Diagnostics.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.sdk\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.SDK.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.security\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Security.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.coreclr.eventing\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.CoreCLR.Eventing.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.consolehost\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.ConsoleHost.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.powershell.markdownrender\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.MarkdownRender.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.wsman.runtime\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Runtime.dll;
      $(USERPROFILE)\.nuget\packages\microsoft.wsman.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Management.dll;
      " DestinationFolder="$(OutputPath)\bin" />
  </Target>

Note that microsoft.management.infrastructure is set to win10-x86 on my side(Win10), you may need to change according to your pc platform. Assemblies are x86 as VS uses x86 Function CLi by default, we don't need to worry about it unless we need to work with x64.

Upvotes: 3

Related Questions