Почему моя переменная ведет себя так внутри задания? - PullRequest
1 голос
/ 07 мая 2020

Я сталкиваюсь со странным поведением XmlElements внутри заданий в моем Powershell-Script. $CommandConfiguration - это XML -элемент с вложенными элементами внутри. Эти элементы существуют в сценарии за пределами области задания, это было протестировано и отлажено. Рассмотрим этот фрагмент кода:

if($CommandConfiguration.ChildNodes.Name -contains "DomainCheck"){
    Write-Host ChildNode exists                            # this is executed
}
$Jobs += Start-Job -Name "WMI-Job" -ScriptBlock {
    $th = $Using:TargetHost
    $cc = $Using:CommandConfiguration                     
    $creds = $Using:Creds

    if($cc.ChildNodes.Name -contains "DomainCheck"){
        Write-Host ChildNode exists                        # this is NOT executed
    }

...

Очевидно, почему дочерний узел существует вне задания, но не внутри него? Я что-то упускаю?

Спасибо за помощь!

1 Ответ

0 голосов
/ 07 мая 2020

tl; dr

Как указано в Jeroen Mostert , вы должны ссылаться на элементы XML из области действия вызывающего как строки в ваше фоновое задание и снова проанализируйте их в XML DOM.

Start-Job -Name 'WMI-Job' -ScriptBlock {
  # ...
  # Use .OuterXml to get the XML element's string representation
  # from the caller's scope, and parse it into an XML document,
  # which makes $cc.ChildNodes work as expected.
  [xml] $cc = $Using:CommandConfiguration.OuterXml
  # ...
}

Ваша попытка напрямую сослаться на System.Xml.XmlElement из области действия вызывающего объекта в задании привела к потере идентичность типа из-за сериализации, при которой значения, передаваемые между сеансами через границы процессов, должны быть ниже go, а десериализованные эмуляции входных объектов XmlElement не имеют свойства ChildNodes - подробнее читайте *. 1019 *


Контекст

Обычно, когда данные передаются в и из внепроцессных сеансов, таких как фоновые задания, запущенные с Start-Job, только несколько хорошо известных типов десериализуется с верностью типа.

Экземпляры всех других типов не требуют методов эмуляции исходных объектов, эффективно [pscustomobject] с c копиями ориги значения свойств объекта и с именем типа PowerShell ETS (расширенная система типов), которое отражает полное имя исходного типа с префиксом Deserialized.

См. этот ответ для получения дополнительной информации.


Возможно, что удивительно,

Обратите внимание, что в случае XmlElement только так называемые адаптированные свойства исходного экземпляра отражаются в свойстве Deserialized.System.Xml.XmlElement (pscustomobject).

То есть эмуляция имеет только свойств, которые PowerShell добавила в исходный экземпляр, а именно свойства, которые непосредственно отображают дочерние элементы и атрибуты базового XML DOM, который позволяет удобно использовать обычную точечную нотацию - см. этот ответ .

Истинные свойства типа. NET XmlElement, такие как ChildNodes, не присутствуют в десериализованной эмуляции, поэтому ваш код не работает.

Обходной путь, как показано вверху, состоит в том, чтобы передать строку представление экземпляров XmlElement фоновому заданию - доступному через свойство OuterXml - и повторно проанализировать эту строку в XML DOM там (обратите внимание, что, строго говоря, приведение к [xml] создает экземпляр System.Xml.XmlDocument, но в отношении того, что вы пытаетесь сделать, это не имеет значения).

...