2025-11-28 00:35:46 +09:00

222 lines
10 KiB
C#

// <copyright file="RemotingDisconnectConnect01.cs" company="Microsoft Corporation">
// Copyright (c) 2011 Microsoft Corporation. All rights reserved.
// </copyright>
// DISCLAIMER OF WARRANTY: The software is licensed “as-is.” You
// bear the risk of using it. Microsoft gives no express warranties,
// guarantees or conditions. You may have additional consumer rights
// under your local laws which this agreement cannot change. To the extent
// permitted under your local laws, Microsoft excludes the implied warranties
// of merchantability, fitness for a particular purpose and non-infringement.
namespace Microsoft.Samples.PowerShell.Runspaces
{
using System;
using System.Threading;
using System.Management.Automation; // Windows PowerShell namespace.
using System.Management.Automation.Runspaces; // Windows PowerShell namespace.
/// <summary>
/// This class contains the Main enrty point for the application.
/// </summary>
internal class RemotingDisconnectConnect01
{
/// <summary>
/// This sample shows how to use the PowerShell Runspace and Pipeline classes to
/// start a long running script on a remote server, disconnect from the server
/// while the script continues to run, and then reconnect to the server to obtain
/// status information on the running script and to retrieve output data.
/// </summary>
/// <param name="args">This parameter is not used.</param>
public static void Main(string[] args)
{
RunspaceState rsState = RunspaceState.BeforeOpen;
PipelineState plState = PipelineState.NotStarted;
// Create the connection object that defines a WSMan/WinRM connection.
// The default constructor will create a WSMan connection object for
// the localhost.
WSManConnectionInfo connectionInfo = new WSManConnectionInfo();
//
// Scenario 1
//
// In this scenario a remote runspace object and a pipeline object are created to
// invoke a long running script on the remote (localhost) server.
// While the script is running the remoterunspace and pipeline objects are
// disconnected. The same remote runspace and pipeline objects are then
// *reconnected* here to the (localhost) server to obtain status information and
// output data generated by the script.
//
// Create a remote runspace with the connection information.
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
// Open the remote runspace, which will establish the connection.
runspace.Open();
// Create a pipeline object to run a "long running" PowerShell script
// that will run for 60 seconds and output data.
using (Pipeline pipeline = runspace.CreatePipeline(@"1..60 | foreach {sleep 1; 'Output ' + $_}"))
{
// Start the script running in a remote session on the localhost. This
// is an asynchronous invoke so the call will return immediately while
// the script runs in the remote session.
pipeline.InvokeAsync();
// Let the script run for a while.
Thread.Sleep(2000);
// Disconnect the runspace and pipeline objects. The script continues to
// run in the remote (localhost) session.
runspace.Disconnect();
// Check that the runspace object is disconnected.
rsState = runspace.RunspaceStateInfo.State;
// Check that the pipeline object is disconnected.
plState = pipeline.PipelineStateInfo.State;
// Let the script run on the server for a while.
Thread.Sleep(2000);
// Reconnect the pipeline back to the server asynchronously. This call will return
// immediately and the status of the running script can be checked. Note that the
// associated runspace object is also reconnected implicitly.
pipeline.ConnectAsync();
// Allow time for connection operation to complete.
Thread.Sleep(2000);
// Check that the runspace object is reconnected (Opened state).
rsState = runspace.RunspaceStateInfo.State;
// Check that the pipeline object is reconnected and running.
plState = pipeline.PipelineStateInfo.State;
// Get all available output from the pipeline, and continue getting output data
// until the pipeline running script completes.
while (!pipeline.Output.EndOfPipeline)
{
pipeline.Output.WaitHandle.WaitOne();
while (pipeline.Output.Count > 0)
{
PSObject psObject = pipeline.Output.Read();
// Write output object data.
Console.WriteLine(psObject.ToString());
}
}
}
}
//
// Scenario 2
//
// In this scenario a new pipeline object is created on the runspace and the
// same long running script is invoked. Again the remote runspace and pipeline
// objects are disconnected while the script runs on the localhost.
// This time we will dispose the remote runspace and pipeline objects while they
// are in the disconnected state. The remote runspace and pipeline objects are
// then *reconstructed* based on information from the localhost remote session.
// The remote runspace and pipeline objects are connected to the server to obtain
// status information and output data from the running command.
//
Guid runspaceInstanceId;
// Create a remote runspace with the connection information.
using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
// Open the remote runspace, which will establish the connection.
runspace.Open();
// Save the runspace instance Id for later referral.
runspaceInstanceId = runspace.InstanceId;
// Create a script pipeline.
using (Pipeline pipeline = runspace.CreatePipeline(@"1..60 | foreach {sleep 1; 'Output ' + $_}"))
{
// Start the script running on the (localhost) server.
pipeline.InvokeAsync();
// Let the script run for a while.
Thread.Sleep(2000);
// Disconnect the remote runspace and pipeline objects. The script continues to
// run on the (localhost) server.
runspace.Disconnect();
// Check that the runspace object is disconnected.
rsState = runspace.RunspaceStateInfo.State;
// Check that the pipeline object is disconnected.
plState = pipeline.PipelineStateInfo.State;
// Let the script run on the server for a while.
Thread.Sleep(2000);
}
}
// Both the runspace and pipeline objects are disconnected from this PowerShell
// client but still running in the remote session. We can reconstruct new
// client runspace and pipeline objects from the original runspace instance Id,
// which uniquely identifies the disconnected session running on the localhost.
// Query the localhost server for runspaces with running script/commands.
Runspace runspace1 = null;
Runspace[] runspaces = Runspace.GetRunspaces(connectionInfo);
foreach (Runspace rs in runspaces)
{
if (rs.InstanceId == runspaceInstanceId)
{
runspace1 = rs;
break;
}
}
if (runspace1 != null)
{
// This is a new runspace object in the Disconnected state that contains information
// about the script running in this runspace on the remote session.
using (runspace1)
{
// Create a new pipeline object for the script running on the server in this runspace.
// The pipeline object is created in a disconnected state.
using (Pipeline pipeline = runspace1.CreateDisconnectedPipeline())
{
// Check the state of the pipeline.
plState = pipeline.PipelineStateInfo.State;
// Connect the pipeline object asynchronously.
// Note that this method also connects the runspace implicitly.
pipeline.ConnectAsync();
// Allow time for connection operation to complete.
Thread.Sleep(2000);
// Check that the runspace is connected and in the Opened state.
rsState = runspace1.RunspaceStateInfo.State;
// Check that the pipeline object is reconnected and running.
plState = pipeline.PipelineStateInfo.State;
// Get all available output from the pipeline, and continue getting output data
// until the pipeline script completes.
while (!pipeline.Output.EndOfPipeline)
{
pipeline.Output.WaitHandle.WaitOne();
while (pipeline.Output.Count > 0)
{
PSObject psObject = pipeline.Output.Read();
// Write output object data.
Console.WriteLine(psObject.ToString());
}
}
}
}
}
}
}
}