简体   繁体   中英

How to make a C# method using PowerShell object constructed with runspace argument asynchronous

Here is an example of some C# code opening a runspace from a remote connection, then invoking PowerShell.

        PSCollection<PSObject> Test(string remoteServerFullName, PSCredential mySuperSecretCredentials)
        {
            using Runspace runspace = RunspaceFactory
                .CreateRunspace(new WSManConnectionInfo(new Uri($"http://{remoteServerFullName}:5985/WSMAN")) { Credential = mySuperSecretCredentials, AuthenticationMechanism = AuthenticationMechanism.NegotiateWithImplicitCredential });
            runspace.Open();
            using PowerShell powerShell = PowerShell.Create(runspace);
            return powerShell
                .AddCommand("dir")
                .Invoke();
        }

I would like to make this asynchronous.

Options I've already tried:

  1. Converting runspace.Open() to runspace.OpenAsync() throws the exception System.Management.Automation.Runspaces.InvalidRunspaceStateException: The runspace state is not valid for this operation. ---> System.Management.Automation.Runspaces.InvalidRunspacePoolStateException: Cannot perform the operation because the runspace pool is not in the 'Opened' state. The current state is 'Opening'. System.Management.Automation.Runspaces.InvalidRunspaceStateException: The runspace state is not valid for this operation. ---> System.Management.Automation.Runspaces.InvalidRunspacePoolStateException: Cannot perform the operation because the runspace pool is not in the 'Opened' state. The current state is 'Opening'.
  2. Making the appropriate changes to the signature to make the method async and placing an await before PowerShell.Create(runspace) leads to build error CS1061: PowerShell does not contain a definition for GetAwaiter , etc.

Is there a way to properly ensure that the creation of the PowerShell object here waits for the runspace to be open before executing?

The quick way is to wrap it with Task.Run :

PSCollection<PSObject> Test(string remoteServerFullName, PSCredential mySuperSecretCredentials)
{
    return Task.Run(() =>
        {
            using Runspace runspace = RunspaceFactory
                .CreateRunspace(new WSManConnectionInfo(new Uri($"http://{remoteServerFullName}:5985/WSMAN")) { Credential = mySuperSecretCredentials, AuthenticationMechanism = AuthenticationMechanism.NegotiateWithImplicitCredential });
            runspace.Open();
            using PowerShell powerShell = PowerShell.Create(runspace);
            return powerShell
                .AddCommand("dir")
                .Invoke();
        });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM