Как использовать пространства пространства в power shell с командами в списке строковых переменных

internal/functions/runspaces/Start-DbaRunspace.ps1

<#

    .SYNOPSIS

        Starts a managed runspace

 
    .DESCRIPTION

        Starts a runspace that was registered to dbatools

        Simply registering does not automatically start a given runspace. Only by executing this function will it take effect.

 
    .PARAMETER Name

        The name of the registered runspace to launch

 
    .PARAMETER Runspace

        The runspace to launch. Returned by Get-DbaRunspace

 
    .PARAMETER EnableException

        By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.

        This avoids overwhelming you with “sea of red” exceptions, but is inconvenient because it basically disables advanced scripting.

        Using this switch turns this “nice by default” feature off and enables you to catch exceptions with your own try/catch.

 
    .EXAMPLE

        PS C:\> Start-DbaRunspace -Name ‘mymodule.maintenance’

 
        Starts the runspace registered under the name ‘mymodule.maintenance’

    #>

In the context of using PowerShell commands with managed code a runspace is the operating environment for the commands invoked by the host application.

Powershell script with runspace

Max's user avatar

Powershell generating output in the error stream instead of output stream

Abhishek Sharma's user avatar

The code hangs my current session. How do I dispose the form and end the Runspace and Powershell session?

Fr. Eugene's user avatar

C# can’t convert from string to runspacemode?

user avatar

What’s the default PSHost implementation (for use in a RunspacePool)?

citelao's user avatar

Powershell GUI, GIF and Runspaces

iva hardy's user avatar

Powershell class can’t call its own methods when invoked from runspace

TXoC's user avatar

PowerShell Toggle Button for Background Job Report Generation

Myste Myzte's user avatar

How to use correct runspace in powershell?

Cheries's user avatar

Piping to Where-Object and Foreach.Object not working in module delayed loaded in $Profile

sirtao's user avatar

set timeout across domain for Test-NetConnection or 5985 in Powershell

shawnixer's user avatar

:/>  Редактирование реестра в командной строке

Updating button text on GUI from within runspace

Nawad-sama's user avatar

PowerShell Error: “No Runspace Available” in Windows PowerShell, but not in ISE

Quentin's user avatar

Powershell crashes, when GridView starts with empty table

Carsten's user avatar

PowerShell PictureBox Object in a New Runspace – Not Showing

AOEMilad's user avatar

Based on guessing, the cause of the issue is that you’re not passing $singlefunction as argument, to your runspace:

[void] $PowerShell.AddScript({
    # `$singlefunction` does not exist in this context
    Invoke-Expression -Command $singlefunction
})

If you want to pass that string as argument to Invoke-Expression you can use .AddArgument or .AddParameter or .AddParameters.

[void] $PowerShell.AddScript({
    Invoke-Expression -Command $args[0]
}).AddArgument($singlefunction)

However, if your intent is to execute the expression in that string this approach is just an over complication, .AddScript takes a string that will be evaluated as a expression, solving the issue could be as simple as:

[void] $PowerShell.AddScript($singlefunction)

using namespace System.Management.Automation.Runspaces

$cleanUpFunc = {
    param([switch] $All, $Foo, $Bar)

    "Called '$($MyInvocation.MyCommand.Name)' with parameters:",
    $PSBoundParameters
}

$iss = [initialsessionstate]::CreateDefault2()
$iss.Commands.Add([SessionStateFunctionEntry]::new(
        'CleanUp', $cleanUpFunc))

$singlefunction = 'CleanUp -All -Foo Hello -Bar World'
$rs = [runspacefactory]::CreateRunspace($iss)
$rs.Open()

$PowerShell = [PowerShell]::Create().
    AddScript($singlefunction)
$PowerShell.Runspace = $rs
$PowerShell.Invoke()

# Outputs:
#
# Called 'CleanUp' with parameters:
#
# Key Value
# --- -----
# All True
# Foo Hello
# Bar World

Experimenting with PowerShell Batching and Parallel Execution

Speed Up Processing of Large Numbers of Microsoft 365 Objects

Not being a professional PowerShell guy like Michel de Rooij, I hack merrily away at PowerShell to get stuff done without being too concerned about the finer points of code. Once I learn how to do something, I tend to keep on using that technique, which is why many of the scripts that I write have similarities. I suspect that I’m not the only one whose PowerShell journey has been a succession of learning experiences without the benefit of formal training. In any case, what I do works, and I enjoy grappling with PowerShell very much.

Как использовать пространства пространства в power shell с командами в списке строковых переменных

Batching HTTP Requests

In any case, the idea is that you can combine up to a maximum of twenty individual Graph requests into a single JSON object. The object is passed using a HTTP POST request to the batch endpoint, which takes care of processing the batches.

:/>  Как Сбросить SMC, PRAM и NVRAM на Mac

To speed things up even further, after preparing the batches, you can leverage the parallel processing capability of PowerShell 7 to submit the batches (Michel de Rooij discusses parallel processing in this article). Each batch uses a PowerShell runspace containing variables, modules, and functions. By default, PowerShell 7 creates five runspaces for parallel execution, so the work in the batches is divided over five runspaces to speed up execution. Obviously, this isn’t something that you would do for scripts that already run acceptably quickly, but it could make a real difference in other circumstances.

A batch looks like this:

Name                           Value
----                           -----
ContentType                    application/json
Uri                            https://graph.microsoft.com/v1.0/$batch
Body                           {…
Method                         Post

The requests that the batch asks the Graph to process is contained in a single JSON object in the body (hence the name “JSON batching.”. Each request has an identifier, method (in this case, GET because we want to retrieve some information), and the URL passed to the Graph.

{
  "requests": [
    {
      "Id": 0,
      "Method": "GET",
      "Url": "users/0a6b8952-baca-4019-bdaf-450536c6ece6?$select=id,displayname,assignedLicenses,country,city,jobtitle,officelocation,userprincipalname,businessphones,employeeid,employeehiredate"
    },
    {
      "Id": 1,
      "Method": "GET",
      "Url": "users/28f205c1-95cd-4d64-b998-e5324b4c032f?$select=id,displayname,assignedLicenses,country,city,jobtitle,officelocation,userprincipalname,businessphones,employeeid,employeehiredate"
    },
Running a query with the Graph Explorer.
Figure 1: Running a query with the Graph Explorer

PowerShell supports parallel execution across more than five runspaces. However, this isn’t something to plunge into unless you’re sure that the workstation running PowerShell has sufficient resources to cope with the demand created by parallel processing. More information about parallel PowerShell capabilities is available in this Microsoft blog.

Because individual runspaces need to spin up before they run a batch, their results must be collected in a thread-safe manner. You can’t use an array or normal list for this purpose, but a ConcurrentBag list works and can accept results from the threads as they run. After all the data is collected, it’s possible to convert the ConcurrentBag into a normal array, hash table, or whatever form is needed by a script.

Testing Parallel Batching

  • Find all user mailboxes.
  • Create batches to fetch user account information from the Graph list users API based on the external directory object id mailbox property (the link between a mailbox and the owning Entra ID account). The request fetches details such as the licenses assigned to the account and details like the city, country, and employee identifier and hire date.
  • Submit the batches.
  • Retrieve the responses and combine them in the ConcurrentBag.
  • Convert the ConcurrentBag to a hash table for quick keyed access to the user data.
  • Create a report combining the mailbox and user data, including the translation of the SKU identifiers for assigned licenses to product names. To do this, I use the technique explained in the article about creating a user licensing report to create a hash table from product information downloaded from Microsoft.
  • Output a CSV file and display the report through the Out-GridView cmdlet (Figure 2).
A mixture of mailbox and account data created using PowerShell parallel batches
Figure 2: A mixture of mailbox and account data created using PowerShell parallel batches

All in all, everything worked well, and I was pleased at the speed of data retrieval.

:/>  Windows old - что это за папка: зачем она нужна и как её правильно удалить

Как использовать пространства пространства в power shell с командами в списке строковых переменных

Just a Test

I don’t pretend that this example is anything other than a test to demonstrate how to use one kind of Microsoft 365 data to drive the retrieval of other information using parallel batch execution. However, learning through doing is a great way to become acquainted with new techniques and I enjoyed experimenting with batches. Will I remember to use parallel processing in the future – well, that all depends on the situation and whether I remember!

About the Author

Tony Redmond has written thousands of articles about Microsoft technology since 1996. He is the lead author for the Office 365 for IT Pros eBook, the only book covering Office 365 that is updated monthly to keep pace with change in the cloud. Apart from contributing to Practical365.com, Tony also writes at Office365itpros.com to support the development of the eBook. He has been a Microsoft MVP since 2004.

Оставьте комментарий