Запуск Powershell из .Net Core — не удалось загрузить файл или сборку Microsoft.Management.Infrastructure

Я пытался запустить сценарий powershell из веб-приложения .Net Core (здесь не обсуждаются лучшие практики;)) со следующим кодом:

    string command = @"& """c:\\my Folder\\myScript.ps1""";

    using (var ps = PowerShell.Create())
    {
        var results = ps.AddScript(command).Invoke();
    }

Он хорошо работает на моей машине разработки, но в продакшене при попытке выполнить эту функцию происходит сбой:

ps.AddScript(command).Invoke()

Я получаю следующее исключение:

System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Management.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified. File name: 'Microsoft.Management.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' at System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes) at System.Reflection.RuntimeAssembly.GetExportedTypes() at System.Management.Automation.Runspaces.PSSnapInHelpers.GetAssemblyTypes(Assembly assembly, String name) at System.Management.Automation.Runspaces.PSSnapInHelpers.AnalyzeModuleAssemblyWithReflection(Assembly assembly, String name, PSSnapInInfo psSnapInInfo, PSModuleInfo moduleInfo, Boolean isModuleLoad, Dictionary2& cmdlets, Dictionary2& aliases, Dictionary2& providers, String helpFile, Type& randomCmdletToCheckLinkDemand, Type& randomProviderToCheckLinkDemand) at System.Management.Automation.Runspaces.PSSnapInHelpers.AnalyzePSSnapInAssembly(Assembly assembly, String name, PSSnapInInfo psSnapInInfo, PSModuleInfo moduleInfo, Boolean isModuleLoad, Dictionary2& cmdlets, Dictionary2& aliases, Dictionary2& providers, String& helpFile) at System.Management.Automation.Runspaces.InitialSessionState.ImportPSSnapIn(PSSnapInInfo psSnapInInfo, PSSnapInException& warning) at System.Management.Automation.Runspaces.InitialSessionState.CreateDefault() at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(PSHost host) at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace() at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync) at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection1 input, PSDataCollection1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.CoreInvoke[TOutput](IEnumerable input, PSDataCollection`1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.Invoke(IEnumerable input, PSInvocationSettings settings)

Я не знаю, какой фреймворк/пакет я должен установить, чтобы он работал. Target Framework — это .Net Core 2.1, который установлен, поэтому приложение работает нормально, за исключением строки, упомянутой выше.

Файл deps.json содержит следующее:

    "Microsoft.Management.Infrastructure/1.0.0": {
        "dependencies": {
          "NETStandard.Library": "2.0.3",
          "System.Runtime.CompilerServices.VisualC": "4.3.0",
          "System.Runtime.Serialization.Xml": "4.3.0",
          "System.Security.SecureString": "4.3.0",
          "System.Threading.ThreadPool": "4.3.0"
        },
        "compile": {
          "ref/netstandard1.6/Microsoft.Management.Infrastructure.Native.dll": {},
          "ref/netstandard1.6/Microsoft.Management.Infrastructure.dll": {}
        }
      }

Установленные пакеты Nuget:

Microsoft.AspNetCore.App (2.1.1)
Microsoft.PowerShell.Commands.Diagnostics (6.0.5)
Microsoft.PowerShell.SDK (6.0.5)
Microsoft.PowerShell.WSMan.Management (6.0.5)

Редактировать Я также добавил Microsoft.Management.Infrastructure (1.0.0) но это не решило проблему

Редактировать2 Dev — это Windows 10 Pro, а Prod — это Windows Server 2016 Standard.

Редактировать3 Скрипт отлично работает на prod при прямом запуске через PowerShell. Показанная ошибка возникает, когда веб-приложение пытается запустить PowerShell.

Редактировать4 Учетная запись пула приложений имеет права администратора и является той же учетной записью, которую я использовал для запуска сценария вручную (не очень хорошая практика, но сейчас я просто пытаюсь запустить этот процесс).

Изменить5 Пробовал положить dll в папку приложения на сервере и перезапустить сайт + перезапустить пул приложений. Я пробовал каждую версию, которую мог найти на машине разработчика, и ничего не получалось :/

Редактировать6 Обновлены пакеты nuget с 6.0.5 до последней версии 6.2.1, та же проблема

Посмотрите этот предыдущий ответ: stackoverflow.com/a/47777636/303696

Den Delimarsky 29.05.2019 08:18

к сожалению, мой код такой же, и у меня те же пакеты Nuget (но версия 6.0.5 вместо 6.0.0-rc). На самом деле я нашел код для запуска powershell из этого ответа.

Sylvain Gantois 29.05.2019 08:28

Вы используете дословный идентификатор в string command = @"& """c:\\my Folder\\myScript.ps1""";. В этом случае вам не нужно экранировать обратную косую черту, измените код на string command = @"& ""c:\my Folder\myScript.ps1"" ";

Moerwald 29.05.2019 09:24

Какая у вас среда разработки и какая производственная среда?

Dhruv Murarka 01.06.2019 09:48

@DhruvMurarka Win 10 Pro для разработчиков и Win Server 2016 Standard для продуктов.

Sylvain Gantois 01.06.2019 10:47

Когда вы публикуете свое приложение, какой RID вы используете?

Bearcat9425 06.06.2019 21:56

@ Bearcat9425 Когда я публикую, варианты, которые я выбираю: Целевая платформа: netcoreapp2.1, Целевая среда выполнения: win-x64 (я могу выбирать только между win-x86, win-x64, win-arm, osx-x64, linux-x64, linux -arm), я использую VS 2019

Sylvain Gantois 06.06.2019 23:23

Я не могу выбрать «win10-x64» или «Win7-x64», как некоторые люди упоминают на github github.com/PowerShell/PowerShell/issues/8119. Я подозреваю, что это потому, что мой проект является веб-приложением...

Sylvain Gantois 07.06.2019 02:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
17
8
9 590
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете загрузить любую DLL из Powershell, поэтому одно решение, которое определенно должно работать, — это загрузка Microsoft.Management.Infrastructure DLL как части скрипта. Но перед этим давайте проверим разницу между тем, что загружено в сеансах powershell dev и prod.

Вы можете получить список загруженных в данный момент сборок в PowerShell, запустив [Threading.Thread]::GetDomain().GetAssemblies(). Добавьте эту строку в начало и конец сценария (в конец, поскольку PowerShell будет автоматически загружать сборки, на которые имеются ссылки, если это возможно, при их первом использовании в сценарии). Теперь запустите скрипт на dev и prod и сравните результаты. Скорее всего, Microsoft.Management.Infrastructure будет отсутствовать в prod.

Выходные данные списка сборок показывают расположение сборок. Из списка разработчиков возьмите Microsoft.Management.Infrastructure DLL-файл. Теперь у вас есть два варианта:

  1. Поместите файл в GAC рабочей машины. PowerShell теперь должен автоматически загружать DLL по мере необходимости.
  2. Сделайте загрузку этого DLL-файла частью сценария PowerShell. Добавьте [Reflection.Assembly]::LoadFile($fullPathToDLL) в начале вашего скрипта (или в любом месте перед использованием Microsoft.Management.Infrastructure).

Есть ли способ сделать это в Visual Studio?

rayray 03.06.2019 16:43

Сценарий работает нормально при прямом запуске в PowerShell. Ошибка отсутствия dll отображается в журналах .Net, поэтому я думаю, что dll требуется для .Net, а не для PowerShell.

Sylvain Gantois 04.06.2019 00:07

Я думал о добавлении dll Microsoft.Management.Infrastructure в GAC, но это не похоже на то, что вы можете просто перетащить файл, как он его использовал, поэтому не уверен, смогу ли я это сделать.

Sylvain Gantois 04.06.2019 00:11

Попробуйте добавить DLL в файлы проекта. По моему опыту, Visual Studio автоматически добавляет ссылки на библиотеки DLL в ваш проект, в противном случае вы можете добавить файл DLL вручную.

Dhruv Murarka 04.06.2019 14:58

@rayray какую часть делает в VS? Все это?

Dhruv Murarka 04.06.2019 14:59

@DhruvMurarka Да, потому что в моем случае мое приложение основано на VS

rayray 04.06.2019 15:49

Если добавление DLL в файлы вашего проекта не работает, я бы очень рекомендовал загрузить часть DLL скрипта, как описано в ответе. Это устранит зависимость от VS или чего-либо еще.

Dhruv Murarka 04.06.2019 17:01

@rayray это приложение также основано на VS, оно вызывает Powershell из проекта C# VS. Если ваш сценарий отличается, вы можете опубликовать отдельный вопрос?

Dhruv Murarka 04.06.2019 17:04

Загрузка dll в PowerShell дала мне ту же ошибку. dll требуется .Net для загрузки самой powershell, скрипт еще не вызывался.

Sylvain Gantois 05.06.2019 14:53

О, я вижу. Ну, последнее, что у меня есть, это разместить необходимую DLL в файлах вашего проекта. Либо VS автоматически обнаружит его и добавит ссылку, либо добавит ссылку в DLL вручную. Если это не сработает, я сдаюсь :P

Dhruv Murarka 05.06.2019 16:17

Проверьте пул удостоверений приложений для веб-приложений в пуле. Это может быть проблема с правами Используйте олицетворение личности или запускайте под учетной записью администратора. когда вы запускаете из консоли, вы запускаете свою личность, когда вы запускаете приложение, его пул идентификаторов приложений

да, это та же учетная запись администратора для пула приложений, которую я использовал для запуска скрипта :(

Sylvain Gantois 05.06.2019 14:22

Итак, вы говорите, что приложение dotnet запускает эту строку var results = ps.AddScript(command).Invoke(); не работает, но PS c:\\my Folder\\myScript.ps1 работает из командной строки ps

Jin Thakur 11.06.2019 23:45

Я работаю с идентификацией пула приложений, и мой код пытается убить некоторые процессы, так что это означает, что эти команды остановки процесса не будут работать при развертывании на сервере, верно?

Sibi John 07.10.2019 17:36
Ответ принят как подходящий

У меня была такая же проблема, Microsoft.Management.Infrastructure.dll (и связанные файлы) не были опубликованы. Решается путем указания непереносной RID в профиле публикации (*.pubxml, нет*.csproj):

<RuntimeIdentifier>win7-x64</RuntimeIdentifier>

Проблема, вероятно, вызвана тем, что под C:\Users\UserName\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes находятся только папки с непереносимыми RID; нет win-x86 и win-x64.

Спасибо, это было! Это означает, что запуск Powershell из .Net Core еще не совсем переносим.

Sylvain Gantois 28.06.2019 10:28

win10-x64 в моем случае для Windows Server 2016 в качестве цели

Sylvain Gantois 28.06.2019 10:32

Если вы выберете среди них «наименьший общий знаменатель», то есть win7-x64 или win7-x86, он должен быть переносим на все поддерживаемые версии Windows. Не уверен насчет unix. Он не упоминается на странице каталога RID: docs.microsoft.com/en-us/dotnet/core/rid-catalog.

George Chakhidze 05.07.2019 14:37

Добавьте это в свой csproj.

<PackageReference Include = "NETStandard.Library" Version = "1.6.1" />

У меня не сработало...

Rye bread 12.01.2022 16:34

Я использую это в своем проекте, и он работает, <PackageReference Include = "Microsoft.PowerShell.SDK" Version = "6.2.4" /> <PackageReference Include = "NETStandard.Library" Version = "1.6.1" />

Hugues Gauthier 13.01.2022 17:04

Другие вопросы по теме