Как получить доступ к другому пространству выполнения powershell без WPF-объекта - PullRequest
0 голосов
/ 27 ноября 2018

Я довольно много работал с пространствами выполнения PowerShell и знаю, что можно вызывать команды в другом пространстве выполнения с помощью диспетчера из объектов WPF.

Я создаю свои пространства выполнения следующим образом:

$global:A = [hashtable]::Synchronized(@{})
$global:initialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
# Add some functions to the ISS
$GuiRunspace =[runspacefactory]::CreateRunspace($initialSessionState)
$GuiRunspace.ApartmentState = "STA"
$GuiRunspace.Open()
$GuiRunspace.SessionStateProxy.SetVariable("A",$A)
$GuiRunspace.SessionStateProxy.SetVariable("B",$B) 
$GuiRunspace.Name = "GuiRunspace"

$Gui = [powershell]::Create()
[void]$Gui.addscript($GUILayerScript)
$Gui.Runspace = $GuiRunspace
$GuiThread = $Gui.beginInvoke()

И с помощью следующего кода я могу манипулировать этим пространством выполнения из других пространств выполнения:

$A.Window.Dispatcher.invoke({ *Do some crazy stuff that has nothing to do with the object from which you called the dispatcher* })

Это работает только потому, что окно является WPF-объектом с свойство dispatcher .

Вопрос в том, как вызвать команду в других пространствах выполнения без диспетчера WPF?

1 Ответ

0 голосов
/ 27 ноября 2018

Если вы хотите иметь общее состояние между вашим основным контекстом выполнения и отдельным пространством выполнения или пулом пространства выполнения, используйте переменную SessionStateProxy и назначьте синхронизированную коллекцию или словарь:

$sharedData = [hashtable]::Synchronized(@{})
$rs = [runspacefactory]::CreateRunspace()
$rs.Open()
$rs.SessionStateProxy.SetVariable('sharedData',$sharedData)

Теперь переменная $sharedDataотносится к одной и той же синхронизированной хэш-таблице как в вызывающем пространстве выполнения, так и внутри $rs

Ниже приведено основное описание использования областей выполнения


Вы можете прикрепитьпространство выполнения для свойства Runspace объекта PowerShell, и оно будет выполняться в этом пространстве:

$rs = [runspacefactory]::CreateNewRunspace()
$rs.Open()
$ps = { Get-Random }.GetPowerShell()
$ps.Runspace = $rs
$result = $ps.Invoke()

Вы также можете назначить RunspacePool нескольким PowerShell экземплярам и выполнять их выполнениеодновременно:

# Create a runspace pool
$rsPool = [runspacefactory]::CreateRunspacePool()
$rsPool.Open()

# Create and invoke bunch of "jobs"
$psInstances = 1..10 |ForEach-Object {
  $ps = {Get-Random}.GetPowerShell()
  $ps.RunspacePool = $rsPool
  [pscustomobject]@{
    ResultHandle = $ps.BeginInvoke()
    Instance = $ps
  }
}

# Do other stuff here

# Wait for the "jobs" to finish
do{
  Start-Sleep -MilliSeconds 100
} while(@($psInstances.ResultHandle.IsCompleted -eq $false).Count -gt 0)

# Time to collect our results
$results = $psInstances |ForEach-Object {
    if($_.Instance.HadErrors){
      # Inspect $_.Instance.Streams.Error in here
    }
    else {
      # Retrieve results
      $_.Instance.EndInvoke($_.ResultHandle)
    }
}

...