Remove src\Microsoft.PowerShell.Workflow.ServiceCore (#4589)

This commit is contained in:
Dongbo Wang
2017-08-16 17:34:03 -07:00
committed by Aditya Patwardhan
parent 33adef28f9
commit 1605a98d75
44 changed files with 0 additions and 32420 deletions
@@ -1,27 +0,0 @@
using System.Reflection;
using System.Security.Permissions;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Diagnostics.CodeAnalysis;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyInformationalVersionAttribute (@"10.0.10011.16384")]
[assembly: ReliabilityContractAttribute(Consistency.MayCorruptAppDomain, Cer.MayFail)]
[assembly: AssemblyTitle("Microsoft.PowerShell.Workflow.ServiceCore")]
[assembly: AssemblyDescription("Microsoft.PowerShell.Workflow.ServiceCore")]
[assembly:AssemblyFileVersionAttribute("3.0.0.0")]
[assembly:AssemblyVersion("3.0.0.0")]
[module: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant")]
[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope="resource", Target="Resources.resources", MessageId="InlineScript")]
[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope="resource", Target="Resources.resources", MessageId="foreach")]
[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope="resource", Target="Resources.resources", MessageId="suspendable")]
[assembly:InternalsVisibleTo("M3PTestAutomation,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly:InternalsVisibleTo("M3PTestCommon,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly:InternalsVisibleTo("VSTS.M3PUnitTest,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly:InternalsVisibleTo("VSTS.ActivityTests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly:InternalsVisibleTo("ActivityTests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100eb57e8072e5fa11a7783bde0003e38bec8272f81d965c161b33b2f45404c9c9177a682ee7049400723fc456ea69b638514943375f7c594027477f9d17e8c3535e6491f382308fbf1c7795413456ac88c0c9881ef49ab9789919f5eeabc9149ccb800bbef8f04103ea24b9be1fb923006b0a272c0d8d928bfdbe947a0f3df4a99")]
[assembly:InternalsVisibleTo("WorkflowCoreTest,PublicKey=0024000004800000940000000602000000240000525341310004000001000100eb57e8072e5fa11a7783bde0003e38bec8272f81d965c161b33b2f45404c9c9177a682ee7049400723fc456ea69b638514943375f7c594027477f9d17e8c3535e6491f382308fbf1c7795413456ac88c0c9881ef49ab9789919f5eeabc9149ccb800bbef8f04103ea24b9be1fb923006b0a272c0d8d928bfdbe947a0f3df4a99")]
[assembly:InternalsVisibleTo("WorkflowJobsTest,PublicKey=0024000004800000940000000602000000240000525341310004000001000100eb57e8072e5fa11a7783bde0003e38bec8272f81d965c161b33b2f45404c9c9177a682ee7049400723fc456ea69b638514943375f7c594027477f9d17e8c3535e6491f382308fbf1c7795413456ac88c0c9881ef49ab9789919f5eeabc9149ccb800bbef8f04103ea24b9be1fb923006b0a272c0d8d928bfdbe947a0f3df4a99")]
@@ -1,99 +0,0 @@
using System;
using System.Activities;
using System.ComponentModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.ComponentModel.Design;
using Microsoft.PowerShell.Workflow;
namespace Microsoft.PowerShell.Activities
{
/// <summary>
/// Category attribute for "Activity-Specific Parameters"
/// </summary>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class ParameterSpecificCategoryAttribute : CategoryAttribute
{
/// <summary>
/// Creates the attribute.
/// </summary>
public ParameterSpecificCategoryAttribute() : base("") { }
/// <summary>
/// Gets a localized version of the attribute description.
/// </summary>
/// <param name="value">Not used.</param>
/// <returns>A localized version of the attribute description</returns>
protected override string GetLocalizedString(string value)
{
return Resources.ActivityParameterGroup;
}
}
/// <summary>
/// Category attribute for "Input and Output"
/// </summary>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class InputAndOutputCategoryAttribute : CategoryAttribute
{
/// <summary>
/// Creates the attribute.
/// </summary>
public InputAndOutputCategoryAttribute() : base("") { }
/// <summary>
/// Gets a localized version of the attribute description.
/// </summary>
/// <param name="value">Not used.</param>
/// <returns>A localized version of the attribute description</returns>
protected override string GetLocalizedString(string value)
{
return Resources.InputAndOutputGroup;
}
}
/// <summary>
/// Category attribute for "Behavior"
/// </summary>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class BehaviorCategoryAttribute : CategoryAttribute
{
/// <summary>
/// Creates the attribute.
/// </summary>
public BehaviorCategoryAttribute() : base("") { }
/// <summary>
/// Gets a localized version of the attribute description.
/// </summary>
/// <param name="value">Not used.</param>
/// <returns>A localized version of the attribute description</returns>
protected override string GetLocalizedString(string value)
{
return CategoryAttribute.Behavior.Category;
}
}
/// <summary>
/// Category attribute for "Connectivity"
/// </summary>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class ConnectivityCategoryAttribute : CategoryAttribute
{
/// <summary>
/// Creates the attribute.
/// </summary>
public ConnectivityCategoryAttribute() : base("") { }
/// <summary>
/// Gets a localized version of the attribute description.
/// </summary>
/// <param name="value">Not used.</param>
/// <returns>A localized version of the attribute description</returns>
protected override string GetLocalizedString(string value)
{
return Resources.ConnectivityGroup;
}
}
}
@@ -1,673 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.Management.Automation;
using Microsoft.PowerShell.Activities;
using System.Management.Automation.Tracing;
using System.Activities;
using System.Management.Automation.PerformanceData;
using System.Management.Automation.Remoting;
namespace Microsoft.PowerShell.Workflow
{
internal class ConnectionAsyncResult : IAsyncResult
{
#region Private Members
private readonly object _state;
private readonly AsyncCallback _callback;
private bool _isCompleted;
private ManualResetEvent _completedWaitHandle;
private readonly object _syncObject = new object();
private Exception _exception;
private readonly Guid _ownerId;
#endregion Private Members
#region Internal
internal ConnectionAsyncResult(object state, AsyncCallback callback, Guid ownerId)
{
_state = state;
_ownerId = ownerId;
_callback = callback;
}
internal Object State
{
get { return _state; }
}
internal AsyncCallback Callback
{
get { return _callback; }
}
internal ActivityInvoker Invoker { get; set; }
/// <summary>
/// this method is not thread safe
/// </summary>
internal void SetAsCompleted(Exception exception)
{
if (_isCompleted) return;
lock (_syncObject)
{
if (_isCompleted) return;
_isCompleted = true;
_exception = exception;
if (_completedWaitHandle != null) _completedWaitHandle.Set();
}
// invoke callback if available
if (null != _callback)
_callback(this);
}
internal Guid OwnerId
{
get { return _ownerId; }
}
internal void EndInvoke()
{
AsyncWaitHandle.WaitOne();
AsyncWaitHandle.Close();
_completedWaitHandle = null; // allow early GC
if (null != _exception) throw _exception;
}
#endregion Internal
#region Overrides
/// <summary>
/// Whether the operation represented by this method is
/// completed
/// </summary>
public bool IsCompleted
{
get { return _isCompleted; }
}
/// <summary>
/// Wait Handle for the operation
/// </summary>
public WaitHandle AsyncWaitHandle
{
get
{
if(null == _completedWaitHandle)
{
lock(_syncObject)
{
if (null == _completedWaitHandle)
{
_completedWaitHandle = new ManualResetEvent(_isCompleted);
}
}
}
return _completedWaitHandle;
}
}
/// <summary>
/// Optional user specified state
/// </summary>
public object AsyncState
{
get { return _state; }
}
/// <summary>
/// Whether this operation completed synchronously
/// </summary>
public bool CompletedSynchronously
{
get { return _completedSynchronously; }
set { _completedSynchronously = value; }
}
private bool _completedSynchronously;
#endregion Overrides
}
/// <summary>
/// Activity Host Manager which will spawn a set of activity
/// host processes until all of them are used after which
/// it will start queueing requests
/// </summary>
/// <remarks>Whether this class needs to remain public should be
/// evaluated</remarks>
internal sealed class PSOutOfProcessActivityController : PSActivityHostController
{
#region Private Members
/// <summary>
/// Stack of available host processes
/// </summary>
private readonly Collection<ActivityHostProcess> _hostProcesses = new Collection<ActivityHostProcess>();
/// <summary>
/// Queue of requests
/// </summary>
private readonly ConcurrentQueue<ActivityInvoker> _requests =
new ConcurrentQueue<ActivityInvoker>();
private int _isServicing;
private const int Servicing = 1;
private const int NotServicing = 0;
private const int MinActivityHosts = 1;
private int _busyHosts;
private readonly Tracer _structuredTracer = new Tracer();
private readonly PSWorkflowConfigurationProvider _configuration;
private static readonly PSPerfCountersMgr PerfCountersMgr = PSPerfCountersMgr.Instance;
/// <summary>
/// List of requests that need to be invoked again due to process crash
/// </summary>
private readonly ConcurrentQueue<ActivityInvoker> _failedRequests = new ConcurrentQueue<ActivityInvoker>();
#endregion Private Members
#region Internal Methods
internal void RunPowerShellInActivityHost(System.Management.Automation.PowerShell powershell, PSDataCollection<PSObject> input,
PSDataCollection<PSObject> output, PSActivityEnvironment policy, ConnectionAsyncResult asyncResult)
{
ActivityInvoker invoker =
new ActivityInvoker
{
Input = input,
Output = output,
Policy = policy,
PowerShell = powershell,
AsyncResult = asyncResult
};
_requests.Enqueue(invoker);
CheckAndStartServicingThread();
}
/// <summary>
/// This is a helper method which should only be called
/// from test code to reset stuff
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This method is called from the tests")]
internal void Reset()
{
foreach (ActivityHostProcess process in _hostProcesses)
{
process.Dispose();
}
_hostProcesses.Clear();
InitializeActivityHostProcesses();
}
#endregion Internal Methods
#region Constructors
internal PSOutOfProcessActivityController(PSWorkflowRuntime runtime)
: base(runtime)
{
if (runtime == null)
throw new ArgumentNullException("runtime");
Debug.Assert(runtime.Configuration != null, "For now only expecting PSWorkflowConfigurationProvider");
this._configuration = runtime.Configuration;
InitializeActivityHostProcesses();
}
#endregion Constructors
#region Private Methods
private void InitializeActivityHostProcesses()
{
// create the minimum number of hosts
for (int i = 0; i < MinActivityHosts; i++)
{
ActivityHostProcess process = CreateNewActivityHostProcess();
_hostProcesses.Add(process);
}
}
private ActivityHostProcess CreateNewActivityHostProcess()
{
ActivityHostProcess process = new ActivityHostProcess(_configuration.ActivityProcessIdleTimeoutSec, _configuration.LanguageMode);
process.ProcessCrashed += ProcessCrashed;
process.Finished += ProcessFinished;
process.OnProcessIdle += ProcessIdle;
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrProcessesPoolSize);
return process;
}
private void ProcessCrashed(object sender, ActivityHostCrashedEventArgs e)
{
// the process crashed, we need to not use it anymore
ActivityHostProcess process = sender as ActivityHostProcess;
Debug.Assert(process != null, "ActivityHostProcess did not raise event correctly");
Debug.Assert(process.Busy, "When ProcessCrashed is raised busy should not be reset");
process.MarkForRemoval = true;
if (e.FailureOnSetup)
{
// the request needs to be processed again
_failedRequests.Enqueue(e.Invoker);
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrFailedRequestsPerSec);
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrFailedRequestsQueueLength);
}
// Below call is added to fix the race condition:
// When OOP host process is crashed, ProcessCrashed() method sets the process as MarkForRemoval, context switch happened at this time
// and another process has finished and started the servicing thread, which checks the above process as MarkForRemoval and disposes it.
// ProcessFinished event handler is unregistered from the process and ActivityHostProcess.HandleTransportError will not be able to raise
// process finished event, resulting inconsistent _busyHost count.
//
DecrementHostCountAndStartThreads();
}
private void ProcessFinished(object sender, EventArgs e)
{
DecrementHostCountAndStartThreads();
}
private void DecrementHostCountAndStartThreads()
{
Interlocked.Decrement(ref _busyHosts);
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrBusyProcessesCount,
-1);
CheckAndStartServicingThread();
}
private void ProcessIdle(object sender, EventArgs e)
{
// Only service thread should access the hostProcess collection
// Start servicing thread if it is not running already
//
CheckAndStartServicingThread();
}
/// <summary>
/// Handler method which runs a specific command in the specified process
/// </summary>
/// <param name="state"></param>
private static void RunPowerShellInActivityHostWorker(object state)
{
// Tuple object with HostProcess and ActivityInvoker is added to ThreadPool.QueueUserWorkItem as part of RunInProcess()
// Back reference on ActivityHostProcess in ActivityInvoker is removed
//
Tuple<ActivityHostProcess, ActivityInvoker> tupleProcessAndInvoker = state as Tuple<ActivityHostProcess, ActivityInvoker>;
tupleProcessAndInvoker.Item1.PrepareAndRun(tupleProcessAndInvoker.Item2);
}
/// <summary>
/// Checks to see if a thread is servicing requests. If not
/// starts one
/// </summary>
private void CheckAndStartServicingThread()
{
if (Interlocked.CompareExchange(ref _isServicing, Servicing, NotServicing) == NotServicing)
{
ThreadPool.QueueUserWorkItem(ServiceRequests);
}
}
/// <summary>
/// Method which performs the actual servicing of requests
/// </summary>
/// <param name="state"></param>
private void ServiceRequests(object state)
{
bool isFailedRequest = false;
while (Interlocked.CompareExchange(ref _busyHosts, _configuration.MaxActivityProcesses, _configuration.MaxActivityProcesses) < _configuration.MaxActivityProcesses)
{
// if there are any processes marked for removal
// remove them
List<ActivityHostProcess> toRemove = _hostProcesses.Where(process => process.MarkForRemoval).ToList();
foreach(var process in toRemove)
{
SafelyDisposeProcess(process);
}
ActivityInvoker invoker;
// first service previously failed request
// and then a queued request
if (_failedRequests.Count > 0)
{
_failedRequests.TryDequeue(out invoker);
isFailedRequest = true;
}
else
{
_requests.TryDequeue(out invoker);
isFailedRequest = false;
}
if (invoker == null) break;
if (invoker.IsCancelled) continue;
if (isFailedRequest)
{
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrFailedRequestsQueueLength,
-1);
}
else
{
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrPendingRequestsQueueLength,
-1);
}
bool processed = false;
foreach (ActivityHostProcess process in _hostProcesses.Where(process => !process.Busy))
{
// we have found the first free process available use it
processed = true;
RunInProcess(invoker, process);
break;
}
// if there weren't enough processes, then we create one more
if (processed) continue;
ActivityHostProcess hostProcess = CreateNewActivityHostProcess();
_hostProcesses.Add(hostProcess);
RunInProcess(invoker, hostProcess);
}
// we are all done, set servicing to false
Interlocked.CompareExchange(ref _isServicing, NotServicing, Servicing);
// Try to start the servicing thread again if there are any pending requests and activity host processes are available.
// This is required to fix the race condition between CheckAndStartServicingThread() and ServiceRequests() methods.
//
if((_failedRequests.Count > 0 || _requests.Count > 0) &&
Interlocked.CompareExchange(ref _busyHosts, _configuration.MaxActivityProcesses, _configuration.MaxActivityProcesses) < _configuration.MaxActivityProcesses)
{
CheckAndStartServicingThread();
}
}
/// <summary>
/// Unregisters all wait handles and disposes a process
/// </summary>
/// <param name="process"></param>
private void SafelyDisposeProcess(ActivityHostProcess process)
{
process.Finished -= ProcessFinished;
process.ProcessCrashed -= ProcessCrashed;
process.OnProcessIdle -= ProcessIdle;
process.Dispose();
_hostProcesses.Remove(process);
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrProcessesPoolSize,
-1);
}
/// <summary>
/// Method called by servicing thread. This method will run the command in the
/// specified process on a separate thread
/// </summary>
/// <param name="invoker"></param>
/// <param name="process"></param>
private void RunInProcess(ActivityInvoker invoker, ActivityHostProcess process)
{
if (invoker.IsCancelled)
{
return;
}
process.Busy = true;
Interlocked.Increment(ref _busyHosts);
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrBusyProcessesCount);
// Adding Tuple object with HostProcess and ActivityInvoker to ThreadPool.QueueUserWorkItem
// Back reference on ActivityHostProcess in ActivityInvoker is removed
//
Tuple<ActivityHostProcess, ActivityInvoker> tupleProcessAndInvoker = new Tuple<ActivityHostProcess, ActivityInvoker>(process, invoker);
ThreadPool.QueueUserWorkItem(RunPowerShellInActivityHostWorker, tupleProcessAndInvoker);
}
#endregion Private Methods
#region PSActivityHostManager Overrides
/// <summary>
/// Begin invocation of command specified in activity
/// </summary>
/// <param name="command">pipeline of command to execute</param>
/// <param name="input">input collection</param>
/// <param name="output">output collection</param>
/// <param name="policy">policy to use for the activity</param>
/// <param name="callback">optional callback</param>
/// <param name="state">optional caller specified state</param>
/// <returns>IAsyncResult</returns>
internal IAsyncResult BeginInvokePowerShell(System.Management.Automation.PowerShell command,
PSDataCollection<PSObject> input, PSDataCollection<PSObject> output, PSActivityEnvironment policy,
AsyncCallback callback, object state)
{
if (command == null)
{
throw new ArgumentNullException("command");
}
ConnectionAsyncResult result = new ConnectionAsyncResult(state, callback, command.InstanceId);
_structuredTracer.OutOfProcessRunspaceStarted(command.ToString());
ActivityInvoker invoker =
new ActivityInvoker
{
Input = input,
Output = output,
Policy = policy,
PowerShell = command,
AsyncResult = result
};
result.Invoker = invoker;
_requests.Enqueue(invoker);
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrIncomingRequestsPerSec);
PerfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrPendingRequestsQueueLength);
CheckAndStartServicingThread();
return result;
}
/// <summary>
/// Block until operation is complete on the current thread
/// </summary>
/// <param name="asyncResult">IAsyncResult to block on</param>
internal void EndInvokePowerShell(IAsyncResult asyncResult)
{
ConnectionAsyncResult result = asyncResult as ConnectionAsyncResult;
if (result == null)
{
throw new PSInvalidOperationException(Resources.AsyncResultNotValid);
}
result.EndInvoke();
}
/// <summary>
/// Cancels an already started execution
/// </summary>
/// <param name="asyncResult">async result to cancel</param>
internal void CancelInvokePowerShell(IAsyncResult asyncResult)
{
ConnectionAsyncResult result = asyncResult as ConnectionAsyncResult;
if (result != null)
{
result.Invoker.StopPowerShell();
}
}
#endregion PSActivityHostManager Overrides
}
#region ActivityInvoker
internal class ActivityInvoker
{
internal PSDataCollection<PSObject> Input { get; set; }
internal PSDataCollection<PSObject> Output { get; set; }
internal System.Management.Automation.PowerShell PowerShell { get; set; }
internal PSActivityEnvironment Policy { get; set; }
internal ConnectionAsyncResult AsyncResult { get; set; }
private readonly object _syncObject = new object();
private bool _invoked;
private bool _cancelled;
private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
internal void InvokePowerShell(Runspace runspace)
{
IAsyncResult result = null;
if (_cancelled)
return;
Exception invokeException = null;
try
{
// Acquiring sync object to fix a race condition between BeginInvoke() and Stop() operations on powershell object.
// Invoked flag is set only when begin invoke is succeeded, so that if this activity is cancelled, powershell needs to be stopped in StopPowerShell().
//
lock (_syncObject)
{
if (_cancelled)
return;
_tracer.WriteMessage("State of runspace passed to invoker ", runspace.RunspaceStateInfo.State.ToString());
// at this point we assume we have a clean runspace to
// run the command
// if the runspace is broken then the invocation will
// result in an error either ways
PowerShell.Runspace = runspace;
// Temporary fix:
// If we are about to run this out of proc, we need to complete any open
// input. Otherwise, the out-of-proc PowerShell will hang expecting input.
// However, this has a bug that it will break a third command trying to
// use the same input collection. Nana to resolve with final fix.
if ((Input != null) && Input.EnumeratorNeverBlocks && Input.IsOpen)
{
Input.Complete();
}
_tracer.WriteMessage("BEGIN invocation of command out of proc");
result = Output == null
? PowerShell.BeginInvoke(Input)
: PowerShell.BeginInvoke(Input, Output);
// _invoked should bet set here as powershell object can be disposed before runspace assignment due to cancelling an activity
//
_invoked = true;
} // end of lock
// wait until PowerShell Execution Completes
PowerShell.EndInvoke(result);
_tracer.WriteMessage("END invocation of command out of proc");
}
catch (Exception exception)
{
// Since the callback is internally handled there should
// not be any exceptions. Fix the same
// ignore any exceptions caused in the callback invocation
_tracer.WriteMessage("Running powershell in activity host threw exception");
_tracer.TraceException(exception);
invokeException = exception;
// transport errors are centrally handled for queue and process management
if (exception is PSRemotingTransportException) throw;
}
finally
{
AsyncResult.SetAsCompleted(invokeException);
}
}
internal void StopPowerShell()
{
bool needToStop = false;
lock (_syncObject)
{
_cancelled = true;
if (_invoked)
{
needToStop = true;
}
}
if (needToStop)
{
PowerShell.Stop();
}
AsyncResult.SetAsCompleted(null);
}
internal bool IsCancelled
{
get
{
lock (_syncObject)
{
return _cancelled;
}
}
}
}
#endregion ActivityInvoker
}
@@ -1,564 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Remoting;
using System.Management.Automation.Tracing;
using System.Management.Automation.PerformanceData;
using System.Timers;
using Timer = System.Timers.Timer;
using System.Globalization;
namespace Microsoft.PowerShell.Workflow
{
internal class ActivityHostCrashedEventArgs : EventArgs
{
internal bool FailureOnSetup { get; set; }
internal ActivityInvoker Invoker { get; set; }
}
/// <summary>
/// Encapsulates an out of process activity host
/// </summary>
/// <remarks>This class is not thread safe. Caller has to
/// ensure thread safety of accessing internal properties</remarks>
internal class ActivityHostProcess : IDisposable
{
#region Private Members
private static PSPerfCountersMgr _perfCountersMgr = PSPerfCountersMgr.Instance;
private Runspace _runspace;
private static readonly WSManConnectionInfo ActivityHostConnectionInfo;
private const string ActivityHostShellUri = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell.Workflow.ActivityHost";
private static readonly string[] ActivitiesTypesFiles = new[] {
@"%windir%\system32\windowspowershell\v1.0\modules\psworkflow\PSWorkflow.types.ps1xml"
};
private static readonly TypeTable ActivitiesTypeTable;
private const int WSManLocalPort = 47001;
private bool _busy;
private readonly object _syncObject = new object();
private readonly PowerShellProcessInstance _processInstance;
private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
private ActivityInvoker _currentInvoker;
/// <summary>
/// This the period of time for which the process will
/// remain inactive. Afterwards it will be killed
/// </summary>
private const int TimeOut = 5*60*1000;
private readonly Timer _timer;
/// <summary>
/// Use this flag to flip between IPC process and
/// WSMan process in localhost
/// </summary>
private readonly bool _useJobIPCProcess;
private readonly PSLanguageMode? _languageMode;
/// <summary>
/// Creating a _PSSetVariable to set multiple variables in a single call --> PERF
/// Naming it _PSSetVariable to avoid name collision with Set-Variable cmdlet
/// </summary>
private const string SetVariableFunction = @"function _PSSetVariable
{
[CmdletBinding()]
param(
[Parameter(Position=0)]
[string[]]
$Name,
[Parameter(Position=1)]
[object[]]
$Value
)
for($i=0; $i -lt $Name.Count; $i++)
{
microsoft.powershell.utility\set-variable -name $Name[$i] -value $Value[$i] -scope global
}
Set-StrictMode -Off
}";
private bool _isDisposed;
#endregion Private Members
#region Constructors
/// <summary>
/// Initialize a connection info object in the static constructor
/// It can be reused for all connections
/// </summary>
static ActivityHostProcess()
{
ActivityHostConnectionInfo = new WSManConnectionInfo { Port = WSManLocalPort, ShellUri = ActivityHostShellUri };
List<String> typefiles = TypeTable.GetDefaultTypeFiles();
typefiles.AddRange(ActivitiesTypesFiles.Select(Environment.ExpandEnvironmentVariables));
ActivitiesTypeTable = new TypeTable(typefiles);
}
internal ActivityHostProcess(int activityHostTimeoutSec, PSLanguageMode? languageMode)
{
_languageMode = languageMode;
_useJobIPCProcess = true;
_tracer.WriteMessage("BEGIN Creating new PowerShell process instance");
_processInstance = new PowerShellProcessInstance();
_tracer.WriteMessage("END Creating new PowerShell process instance ");
_runspace = CreateRunspace();
_tracer.WriteMessage("New runspace created ", _runspace.InstanceId.ToString());
_timer = new Timer {AutoReset = false, Interval = TimeOut};
_timer.Elapsed += TimerElapsed;
_timer.Interval = activityHostTimeoutSec > 0 ? activityHostTimeoutSec*1000 : TimeOut;
_perfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrCreatedProcessesCount);
}
#endregion Constructors
#region Private Methods
/// <summary>
/// Get the runspace corresponding to this process
/// </summary>
/// <param name="createNew">indicates if a new runspace
/// needs to be created</param>
/// <returns>runspace object</returns>
private Runspace GetRunspace(bool createNew)
{
if (_runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)
{
// if the runspace is not opened, open it and return
OpenRunspace(_runspace);
}
else
{
if (_useJobIPCProcess)
{
// dispose the existing runspace and create a new one
CloseAndDisposeRunspace();
_runspace = CreateRunspace();
_tracer.WriteMessage("New runspace created ", _runspace.InstanceId.ToString());
OpenRunspace(_runspace);
}
}
return _runspace;
}
private void CloseAndDisposeRunspace()
{
try
{
// Close and dispose the existing runspace
//
_runspace.Close();
_runspace.Dispose();
}
catch (Exception e)
{
// RemoteRunspace.Close can throw exceptions when Server process has exited or runspace is invalid.
// Ignoring all exceptions as this runspace was used for previous OOP activity execution.
//
_tracer.TraceException(e);
// do nothing
}
}
/// <summary>
/// Depending on the option return an Out-of-proc
/// or remoting runspace on localhost
/// </summary>
/// <returns>runspace object for use</returns>
private Runspace CreateRunspace()
{
return _useJobIPCProcess ? RunspaceFactory.CreateOutOfProcessRunspace(ActivitiesTypeTable, _processInstance) : RunspaceFactory.CreateRunspace(ActivityHostConnectionInfo, null, ActivitiesTypeTable);
}
/// <summary>
/// Opens the specified runspace. If there are any errors in
/// opening the runspace, the method just eats them so that
/// an unhandled exception in the background thread in which this
/// method is invoked does not lead to a process crash
/// </summary>
/// <param name="runspace">runspace to open</param>
private void OpenRunspace(Runspace runspace)
{
// a runspace open can fail for a variety of reasons
// eat the exceptions
try
{
_tracer.WriteMessage("Opening runspace " , _runspace.InstanceId.ToString());
runspace.Open();
_tracer.WriteMessage("Runspace opened successfully ", _runspace.InstanceId.ToString());
if (_languageMode != null && _languageMode.HasValue)
{
using (System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create())
{
ps.Runspace = runspace;
string langScript = "$ExecutionContext.SessionState.LanguageMode = '" + _languageMode.Value.ToString() + "'";
ps.AddScript(langScript);
ps.Invoke();
}
}
}
catch (PSRemotingTransportRedirectException)
{
// we should not be getting this exception
// in the normal case
_tracer.WriteMessage("Opening runspace threw PSRemotingTransportRedirectException", _runspace.InstanceId.ToString());
Debug.Assert(false, "We should not get a redirect exception under normal circumstances");
}
catch (PSRemotingTransportException transportException)
{
_tracer.WriteMessage("Opening runspace threw PSRemotingTransportException", _runspace.InstanceId.ToString());
_tracer.TraceException(transportException);
// throwing PSRemotingTransportException exception as it will be handled at single place in PrepareAndRun() method.
throw;
}
catch(PSRemotingDataStructureException)
{
// just eat the exception
_tracer.WriteMessage("Opening runspace threw PSRemotingDataStructureException", _runspace.InstanceId.ToString());
Debug.Assert(false, "We should not get a protocol exception under normal circumstances");
}
}
/// <summary>
/// Import all the specified modules in the specified runspace
/// </summary>
/// <param name="runspace">runspace in which to import the modules</param>
/// <param name="modules">collection of modules to import</param>
/// <returns>true if setting up of runspace from policy succeeded</returns>
private void ImportModulesFromPolicy(Runspace runspace, ICollection<string> modules)
{
// If any modules are specified, load them into the runspace.
// In general, autoloading should be preferred to explicitly loading a module
// at startup time...
if (modules.Count <= 0)
return;
using (System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create())
{
ps.Runspace = runspace;
// Setting erroraction to stop for import-module since they are required modules. If not present, stop the execution
ps.AddCommand("Import-Module").AddArgument(modules).AddParameter("ErrorAction",ActionPreference.Stop).AddParameter("Force");
ps.Invoke();
}
}
/// <summary>
/// Set the specified variables in the runspace
/// </summary>
/// <param name="runspace">runspace in which the variables need
/// to be set</param>
/// <param name="variables">collection of variables that need to be set</param>
private void SetVariablesFromPolicy(Runspace runspace, IDictionary<string, object> variables)
{
using (System.Management.Automation.PowerShell ps = System.Management.Automation.PowerShell.Create())
{
ps.Runspace = runspace;
ps.AddScript(SetVariableFunction);
ps.Invoke();
ps.Commands.Clear();
ps.AddCommand("_PSSetVariable").AddParameter("Name", variables.Keys).AddParameter("Value", variables.Values);
ps.Invoke();
// Remove the temporary function _PSSetVariable after its use is done.
ps.Commands.Clear();
ps.AddCommand("Remove-Item").AddParameter("Path", "function:\\_PSSetVariable").AddParameter("Force");
ps.Invoke();
}
}
/// <summary>
/// Set the busy flag since the process is being used.
/// Stop the idle timer
/// </summary>
private void SetBusy()
{
lock(_syncObject)
{
_busy = true;
// stop the idle timer
_timer.Stop();
}
}
/// <summary>
/// Reset the busy flag and start the idle timer
/// </summary>
private void ResetBusy()
{
lock(_syncObject)
{
// Process state should not be set to false if it is already marked for removal
// Process is marked for removal in two cases:
// 1) When PSRemotingTransportException is received in PrepareAndRun, in this case Server process is already crashed/exited.
// If busy state is set to false, this process can be assigned to another activity by the servicing thread.
// Instead of adding separate boolean variable in PrepareAndRun to call ResetBusy we are checking for not marked for removal here.
// 2) When idle time of 5 min elapsed, process is marked for removal so that server process can be killed. After this, ResetBusy is never called.
//
if (_busy && !_markForRemoval)
{
_busy = false;
// enable the idle timer
_timer.Enabled = true;
this.RaiseProcessFinishedEvent();
}
}
}
/// <summary>
/// Idle timeout has occured. If the runspace is not being used
/// just close it
/// </summary>
/// <param name="sender">sender of this event</param>
/// <param name="e">unused</param>
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
lock (_syncObject)
{
if (_busy) return;
// Mark this process for removal and set it as busy so that this process will not be assigned to any new activity.
// Marking for removal will ensure that servicing thread will remove this object from host process collection.
//
_busy = true;
_markForRemoval = true;
}
if (OnProcessIdle != null)
OnProcessIdle(this, new EventArgs());
}
/// <summary>
/// Handles a transport error since it is most likely that
/// the process crash
/// </summary>
/// <param name="transportException">the transport exception
/// that was raised</param>
/// <param name="onSetup">true indicates that the crash was
/// encountered when setting up the process and not when the
/// command was run</param>
private void HandleTransportError(PSRemotingTransportException transportException, bool onSetup)
{
_tracer.TraceException(transportException);
if (ProcessCrashed != null)
{
ActivityHostCrashedEventArgs eventArgs = new ActivityHostCrashedEventArgs
{FailureOnSetup = onSetup,
Invoker = _currentInvoker};
ProcessCrashed(this, eventArgs);
}
}
internal void RaiseProcessFinishedEvent()
{
if (Finished != null)
Finished(this, new EventArgs());
}
#endregion Private Methods
#region Internal Methods
internal static String ActivityHostConfiguration
{
get { return ActivityHostShellUri; }
}
internal event EventHandler Finished;
internal event EventHandler OnProcessIdle;
internal event EventHandler<ActivityHostCrashedEventArgs> ProcessCrashed;
/// <summary>
/// Prepare the environment based on the policy and run the powershell
/// </summary>
/// <param name="invoker"></param>
/// <remarks>It is assumed that the caller of this method will spawn appropriate
/// thread and so it is fine for us to call the callback on the same thread</remarks>
internal void PrepareAndRun(ActivityInvoker invoker)
{
bool setupSucceeded = false;
try
{
// Transport (PSRemotingTransportException) error can happen during setup/prepare phase, so it is getting assigned before setup phase.
//
_currentInvoker = invoker;
Runspace runspace = null;
// Retry for 10 times if runspace is in Broken state
//
// Runspace can be broken, when a remote runspace is getting closed during the next activity execution,
// the close ack is getting timedout and that close ack is received by the newly created remote runspace for
// the next activity since stdoutput stream of server process is not cleared/discarded,
// that is why during new runspace is in broken state while it is being opened.
//
for (int i = 1; (i <= 10) && !invoker.IsCancelled; i++)
{
// prepare the runspace with the necessary
// modules and variables here
runspace = GetRunspace(true);
if (runspace.RunspaceStateInfo.State == RunspaceState.Opened)
break;
System.Threading.Thread.Sleep(i*200);
}
if (invoker.IsCancelled)
{
return;
}
Debug.Assert((runspace.RunspaceStateInfo.State == RunspaceState.Opened), "Runspace is not in Opened state for running an OOP activity");
if (invoker.Policy.Variables.Count > 0)
{
// set the variables in the specified runspace
_tracer.WriteMessage("BEGIN Setting up variables in runspace ", _runspace.InstanceId.ToString());
SetVariablesFromPolicy(runspace, invoker.Policy.Variables);
_tracer.WriteMessage("END Setting up variables in runspace ", _runspace.InstanceId.ToString());
}
if (invoker.Policy.Modules.Count > 0)
{
// attempt loading the modules in the specified runspace
_tracer.WriteMessage("BEGIN Setting up runspace from policy ", _runspace.InstanceId.ToString());
ImportModulesFromPolicy(runspace, invoker.Policy.Modules);
_tracer.WriteMessage("END Setting up runspace from policy ", _runspace.InstanceId.ToString());
}
// Prepare phase is completed without any issues.
// setupSucceeded flag is used in HandleTransportError method to enqueue the current activity for retry.
// If there is any PSRemotingTransportException during InvokePowershell current activity will not be enqueued to setup failed requests in ActivityHostManager.
//
setupSucceeded = true;
// at this point we assume we have a clean runspace to
// run the command
// if the runspace is broken then the invocation will
// result in an error either ways
invoker.InvokePowerShell(runspace);
}
catch (PSRemotingTransportException transportException)
{
HandleTransportError(transportException, !setupSucceeded);
}
catch (Exception e)
{
// at this point there is an exception other than a
// transport exception that is caused by trying to
// setup the runspace. Release the asyncresult
// accordingly
_tracer.TraceException(e);
invoker.AsyncResult.SetAsCompleted(e);
}
finally
{
_currentInvoker = null;
ResetBusy();
}
}
/// <summary>
/// If the process represented by this object is busy
/// </summary>
internal bool Busy
{
get
{
lock (_syncObject)
{
return _busy;
}
}
set
{
if (value) SetBusy();
else ResetBusy();
}
}
/// <summary>
/// Indicates that the associated process crashed and this object
/// needs to be removed by ActivityHostManager
/// </summary>
internal bool MarkForRemoval {
get
{
// _processInstance.HasExited can not be used to tell as marked for removal
// as it will cause inconsistent busy host count
//
return _markForRemoval;
}
set
{
_markForRemoval = value;
}
}
private bool _markForRemoval = false;
#endregion Internal Methods
#region IDisposable
/// <summary>
/// Dispose
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// dispose of managed resources
/// </summary>
/// <param name="disposing">true if being disposed</param>
protected void Dispose(bool disposing)
{
if (!disposing) return;
if (_isDisposed) return;
lock (_syncObject)
{
if (_isDisposed) return;
_isDisposed = true;
}
Debug.Assert(_runspace != null, "Runspace is already null");
CloseAndDisposeRunspace();
_processInstance.Dispose();
_currentInvoker = null;
_tracer.Dispose();
_perfCountersMgr.UpdateCounterByValue(
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterIds.ActivityHostMgrDisposedProcessesCount);
}
#endregion IDisposable
}
}
@@ -1,116 +0,0 @@
using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Remoting;
using System.Management.Automation.Runspaces;
using Microsoft.PowerShell.Workflow;
namespace Microsoft.PowerShell.Activities
{
static class ActivityUtils
{
// Extension method to add IsNullOrEmpty to arrays.
internal static bool IsNullOrEmpty(this System.Collections.ICollection c)
{
return (c == null || c.Count == 0);
}
private static int DefaultMaximumConnectionRedirectionCount = 5;
internal static List<WSManConnectionInfo> GetConnectionInfo(string[] PSComputerName, string[] PSConnectionUri,
string PSCertificateThumbprint, string PSConfigurationName,
bool? PSUseSsl, uint? PSPort, string PSApplicationName,
PSCredential PSCredential, AuthenticationMechanism PSAuthentication,
bool PSAllowRedirection, System.Management.Automation.Remoting.PSSessionOption options)
{
List<WSManConnectionInfo> connections = new List<WSManConnectionInfo>();
string[] machineList = null;
bool connectByComputerName = false;
// Connect by computername
if ((! PSComputerName.IsNullOrEmpty()) && (PSConnectionUri.IsNullOrEmpty()))
{
machineList = PSComputerName;
connectByComputerName = true;
}
else if ((PSComputerName.IsNullOrEmpty()) && (! PSConnectionUri.IsNullOrEmpty()))
{
machineList = PSConnectionUri;
}
else
{
throw new ArgumentException(Resources.CannotSupplyUriAndComputername);
}
// Go through each machine in the list an update its properties
foreach (string machine in machineList)
{
if (!string.IsNullOrEmpty(machine))
{
WSManConnectionInfo connectionInfo = new WSManConnectionInfo();
if (PSPort.HasValue)
{
connectionInfo.Port = (int)PSPort.Value;
}
if (PSUseSsl.HasValue && (PSUseSsl.Value))
{
connectionInfo.Scheme = WSManConnectionInfo.HttpsScheme;
}
if (!String.IsNullOrEmpty(PSConfigurationName))
{
connectionInfo.ShellUri = PSConfigurationName;
}
if (!String.IsNullOrEmpty(PSApplicationName))
{
connectionInfo.AppName = PSApplicationName;
}
if (connectByComputerName)
{
connectionInfo.ComputerName = machine;
}
else
{
connectionInfo.ConnectionUri = (Uri)LanguagePrimitives.ConvertTo(machine, typeof(Uri), System.Globalization.CultureInfo.InvariantCulture);
}
if (PSCredential != null)
{
connectionInfo.Credential = PSCredential;
}
if (!String.IsNullOrEmpty(PSCertificateThumbprint))
{
connectionInfo.CertificateThumbprint = PSCertificateThumbprint;
}
if (PSAuthentication != AuthenticationMechanism.Default)
{
connectionInfo.AuthenticationMechanism = PSAuthentication;
}
connectionInfo.MaximumConnectionRedirectionCount = PSAllowRedirection ? DefaultMaximumConnectionRedirectionCount : 0;
if (options != null)
{
connectionInfo.SetSessionOptions(options);
}
connections.Add(connectionInfo);
}
else
{
// add a null connection to account for "" or $null in PSComputerName parameter
connections.Add(null);
}
}
return connections;
}
}
}
@@ -1,91 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Globalization;
namespace Microsoft.PowerShell.Workflow
{
internal static class Constants
{
internal const string AsJob = "AsJob";
// Remoting-related constants
internal const string ComputerName = "PSComputerName";
internal const string Credential = "PSCredential";
internal const string Port = "PSPort";
internal const string UseSSL = "PSUseSSL";
internal const string ConfigurationName = "PSConfigurationName";
internal const string ApplicationName = "PSApplicationName";
internal const string ConnectionURI = "PSConnectionURI";
internal const string AllowRedirection = "PSAllowRedirection";
internal const string SessionOption = "PSSessionOption";
internal const string Authentication = "PSAuthentication";
internal const string AuthenticationLevel = "PSAuthenticationLevel";
internal const string CertificateThumbprint = "PSCertificateThumbprint";
internal const string PSParameterCollection = "PSParameterCollection";
internal const string PSInputCollection = "PSInputCollection";
internal const string InputObject = "InputObject";
internal const string PSSenderInfo = "PSSenderInfo";
internal const string PSCurrentDirectory = "PSCurrentDirectory";
internal const string PSSuspendOnError = "PSSuspendOnError";
// PowerShell-common constants
internal const string Verbose = "Verbose";
internal const string Debug = "Debug";
internal const string ErrorAction = "ErrorAction";
internal const string WarningAction = "WarningAction";
internal const string InformationAction = "InformationAction";
internal const string ErrorVariable = "ErrorVariable";
internal const string WarningVariable = "WarningVariable";
internal const string InformationVariable = "InformationVariable";
internal const string OutVariable = "OutVariable";
internal const string OutBuffer = "OutBuffer";
internal const string PipelineVariable = "PipelineVariable";
// Retry policy constants
internal const string ConnectionRetryCount = "PSConnectionRetryCount";
internal const string ActionRetryCount = "PSActionRetryCount";
internal const string ConnectionRetryIntervalSec = "PSConnectionRetryIntervalSec";
internal const string ActionRetryIntervalSec = "PSActionRetryIntervalSec";
internal const string PrivateMetadata = "PSPrivateMetadata";
internal const string WorkflowTakesPrivateMetadata = "WorkflowTakesPrivateMetadata";
internal const string WorkflowJobCreationContext = "WorkflowJobCreationContext";
// Timers
internal const string PSRunningTime = "PSRunningTimeoutSec";
internal const string PSElapsedTime = "PSElapsedTimeoutSec";
internal const string Int32MaxValueDivideByThousand = "2147483";
internal const string ModulePath = "PSWorkflowRoot";
internal const string JobName = "JobName";
internal const string DefaultComputerName = "localhost";
// Job Metadata constants
internal const string JobMetadataInstanceId = "InstanceId";
internal const string JobMetadataSessionId = "Id";
internal const string JobMetadataName = "Name";
internal const string JobMetadataCommand = "Command";
internal const string JobMetadataStateReason = "Reason";
internal const string JobMetadataParentName = "ParentName";
internal const string JobMetadataParentCommand = "ParentCommand";
internal const string JobMetadataParentInstanceId = "ParentInstanceId";
internal const string JobMetadataParentSessionId = "ParentSessionId";
internal const string JobMetadataLocation = "Location";
internal const string JobMetadataStatusMessage = "StatusMessage";
internal const string JobMetadataUserName = "UserName";
internal const string JobMetadataPid = "ProcessId";
internal const string JobMetadataFilterState = "State";
internal const string Persist = "PSPersist";
internal const string PSRequiredModules = "PSRequiredModules";
internal const string PSWorkflowErrorAction = "PSWorkflowErrorAction";
internal const int MaxAllowedPersistencePathLength = 120;
}
}
@@ -1,126 +0,0 @@
/********************************************************************++
* Copyright (c) Microsoft Corporation. All rights reserved.
* --********************************************************************/
using System.Collections.ObjectModel;
using System.IO;
using System.Management.Automation.Remoting;
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.Management.Automation.Tracing;
using System.Globalization;
using Microsoft.PowerShell.Commands;
namespace Microsoft.PowerShell.Workflow
{
/// <summary>
/// Configuration for the M3P endpoint
/// </summary>
public class PSWorkflowSessionConfiguration : PSSessionConfiguration
{
/// <summary>
/// IsWorkflowTypeEndpoint
/// </summary>
internal static bool IsWorkflowTypeEndpoint;
#region Overrides of PSSessionConfiguration
/// <summary>
///
/// </summary>
/// <param name="senderInfo"></param>
/// <exception cref="NotImplementedException"></exception>
/// <returns></returns>
public override InitialSessionState GetInitialSessionState(PSSenderInfo senderInfo)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <param name="sessionConfigurationData"></param>
/// <param name="senderInfo"></param>
/// <param name="configProviderId"></param>
/// <returns></returns>
public override InitialSessionState GetInitialSessionState(PSSessionConfigurationData sessionConfigurationData, PSSenderInfo senderInfo, string configProviderId)
{
Tracer structuredTracer = new Tracer();
structuredTracer.Correlate();
if (sessionConfigurationData == null)
throw new ArgumentNullException("sessionConfigurationData");
if (senderInfo == null)
throw new ArgumentNullException("senderInfo");
if (string.IsNullOrEmpty(configProviderId))
throw new ArgumentNullException("configProviderId");
if (Interlocked.CompareExchange(ref _modulesLoaded, ModulesLoaded, ModulesNotLoaded) == ModulesNotLoaded)
{
// it is sufficient if Populate() is called the first time and
// modules are loaded once
try
{
IsWorkflowTypeEndpoint = true;
PSWorkflowConfigurationProvider workflowConfiguration = WorkflowJobSourceAdapter.GetInstance().GetPSWorkflowRuntime().Configuration;
if (workflowConfiguration == null)
throw new InvalidOperationException("PSWorkflowConfigurationProvider is null");
workflowConfiguration.Populate(sessionConfigurationData.PrivateData, configProviderId, senderInfo);
// now get all the modules in the specified path and import the same
if (sessionConfigurationData.ModulesToImport != null)
{
foreach (var module in sessionConfigurationData.ModulesToImport)
{
ModuleSpecification moduleSpec = null;
if (ModuleSpecification.TryParse(module, out moduleSpec))
{
var modulesToImport = new Collection<ModuleSpecification> { moduleSpec };
InitialSessionState.ImportPSModule(modulesToImport);
}
else
{
InitialSessionState.ImportPSModule(new[] { Environment.ExpandEnvironmentVariables(module) });
}
}
}
// Start the workflow job manager, if not started, to add an event handler for zero active sessions changed events
// This is required to auto shutdown the workflow type shared process when no workflow jobs have scheduled/inprogress and when no active sessions
WorkflowJobSourceAdapter.GetInstance().GetJobManager();
}
catch(Exception)
{
// if there is an exception in either Populate() or Importing modules
// we consider that it is not loaded
Interlocked.CompareExchange(ref _modulesLoaded, ModulesNotLoaded, ModulesLoaded);
throw;
}
}
if (configProviderId.ToLower(CultureInfo.InvariantCulture).Equals("http://schemas.microsoft.com/powershell/microsoft.windows.servermanagerworkflows"))
{
PSSessionConfigurationData.IsServerManager = true;
}
return InitialSessionState;
}
private static readonly InitialSessionState InitialSessionState =
InitialSessionState.CreateRestricted(SessionCapabilities.WorkflowServer | SessionCapabilities.RemoteServer | SessionCapabilities.Language);
private static int _modulesLoaded = ModulesNotLoaded;
private const int ModulesNotLoaded = 0;
private const int ModulesLoaded = 1;
#endregion
}
}
@@ -1,608 +0,0 @@
//
// Copyright (C) Microsoft. All rights reserved.
//
using System;
using System.Activities;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Tracing;
using Microsoft.PowerShell.Commands;
using System.Reflection;
namespace Microsoft.PowerShell.Workflow
{
internal sealed class DefinitionCache
{
#region Privates
internal struct WorkflowDetails
{
internal Activity ActivityTree;
internal string CompiledAssemblyPath;
internal string CompiledAssemblyName;
internal bool IsWindowsActivity;
};
private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
/// <summary>
/// Cache of workflow details. This is unbounded
/// </summary>
private readonly Dictionary<WorkflowJobDefinition, WorkflowDetails> _workflowDetailsCache =
new Dictionary<WorkflowJobDefinition, WorkflowDetails>(new CompareBasedOnInstanceId());
/// <summary>
/// this is the cache of compiled activities which will be bounded
/// </summary>
/// <remarks>this is separate since Opalis will not use our cache</remarks>
private readonly ConcurrentDictionary<WorkflowJobDefinition, Activity> _cachedActivities =
new ConcurrentDictionary<WorkflowJobDefinition, Activity>(new CompareBasedOnInstanceId());
private System.Timers.Timer _cleanupTimer;
private int activitiesCleanupIntervalMSec;
private static readonly DefinitionCache _instance = new DefinitionCache();
private DefinitionCache()
{
activitiesCleanupIntervalMSec = WorkflowJobSourceAdapter.GetInstance().GetPSWorkflowRuntime().Configuration.ActivitiesCacheCleanupIntervalMSec;
_cleanupTimer = new System.Timers.Timer(activitiesCleanupIntervalMSec);
_cleanupTimer.Elapsed += HandleCleanupTimerElapsed;
_cleanupTimer.AutoReset = false;
_cleanupTimer.Start();
}
private void HandleCleanupTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
List<WorkflowJobDefinition> activitiesToRemove = new List<WorkflowJobDefinition>();
Activity activity;
foreach (var workflowJobDefinition in _cachedActivities.Keys)
{
if ((GetRuntimeAssemblyPath(workflowJobDefinition) == null) &&
(DateTime.Now - workflowJobDefinition.LastUsedDateTime > TimeSpan.FromMilliseconds(activitiesCleanupIntervalMSec)))
{
activitiesToRemove.Add(workflowJobDefinition);
}
}
foreach (var wfJobDefinition in activitiesToRemove)
{
_cachedActivities.TryRemove(wfJobDefinition, out activity);
}
// Schedule the next cleanup
_cleanupTimer.Start();
}
/// <summary>
/// Cache size
/// </summary>
private const int _cacheSize = 1000;
/// <summary>
/// Path to Windows folder
/// </summary>
private const string WindowsPath = "%windir%\\system32";
#endregion Privates
#region Internal
internal int CacheSize
{
get { return _cacheSize; }
}
/// <summary>
/// Return the singleton instance.
/// </summary>
internal static DefinitionCache Instance
{
get
{
return _instance;
}
}
internal JobDefinition GetDefinition(Guid instanceId)
{
return _workflowDetailsCache.Keys.FirstOrDefault(def => def.InstanceId == instanceId);
}
internal string GetWorkflowXaml(WorkflowJobDefinition definition)
{
return definition.Xaml;
}
internal string GetRuntimeAssemblyPath(WorkflowJobDefinition definition)
{
WorkflowDetails workflowDetail;
return _workflowDetailsCache.TryGetValue(definition, out workflowDetail) ? workflowDetail.CompiledAssemblyPath : null;
}
internal string GetRuntimeAssemblyName(WorkflowJobDefinition definition)
{
WorkflowDetails workflowDetail;
return _workflowDetailsCache.TryGetValue(definition, out workflowDetail) ? workflowDetail.CompiledAssemblyName : null;
}
internal bool AllowExternalActivity;
/// <summary>
/// Compiles the activity and adds it to the cache before returning it.
/// </summary>
/// <param name="definition">WorkflowJobDefinition defined to represent a compiled activity.</param>
/// <param name="activityTree">Activity Tree used for external activities</param>
/// <param name="requiredAssemblies"></param>
/// <param name="windowsWorkflow">indicates if the specified xaml is a Windows workflow</param>
/// <param name="rootWorkflowName">Optional, once assigned, only root Workflow will be compiled</param>
/// <returns>Activity compiled from xaml given, or retrieved from cache.
/// Null if not found.</returns>
internal Activity CompileActivityAndSaveInCache(WorkflowJobDefinition definition, Activity activityTree, Dictionary<string, string> requiredAssemblies, out bool windowsWorkflow, string rootWorkflowName = null)
{
WorkflowDetails workflowDetail = new WorkflowDetails();
Activity activity = null;
// initialize windows workflow to false
windowsWorkflow = false;
string resultingCompiledAssemblyPath = definition.DependentAssemblyPath;
string modulePath = definition.ModulePath;
string[] dependentWorkflows = definition.DependentWorkflows.ToArray();
Assembly resultingCompiledAssembly = null;
string resultingCompiledAssemblyName = null;
string xaml = definition.Xaml;
if (activityTree != null)
{
_tracer.WriteMessage(string.Format(CultureInfo.InvariantCulture,
"DefinitionCache: Caching activity for definition with instance ID: {0}. The activity Tree is passed.",
definition.InstanceId));
workflowDetail.ActivityTree = activityTree;
activity = activityTree;
}
else if (!String.IsNullOrEmpty(xaml))
{
// we need to read the xaml from the specified path and compile the same
_tracer.WriteMessage(string.Format(CultureInfo.InvariantCulture,
"DefinitionCache: Caching activity for definition with instance ID: {0}. Xaml is passed",
definition.InstanceId));
workflowDetail.ActivityTree = null;
// check if specified workflow is a windows workflow
if (!string.IsNullOrEmpty(modulePath))
{
string resolvedPath = Environment.ExpandEnvironmentVariables(modulePath);
string resolvedWindowsPath = Environment.ExpandEnvironmentVariables(WindowsPath);
if (resolvedPath.IndexOf(resolvedWindowsPath, StringComparison.CurrentCultureIgnoreCase) != -1)
{
windowsWorkflow = true;
}
}
if (definition.DependentAssemblyPath == null && dependentWorkflows.Length == 0)
{
activity = ImportWorkflowCommand.ConvertXamlToActivity(xaml);
}
else
{
if (rootWorkflowName == null || (definition.Command == rootWorkflowName))
{
activity = ImportWorkflowCommand.ConvertXamlToActivity(xaml, dependentWorkflows,
requiredAssemblies,
ref resultingCompiledAssemblyPath,
ref resultingCompiledAssembly,
ref resultingCompiledAssemblyName);
}
else
{
activity = ImportWorkflowCommand.ConvertXamlToActivity(xaml);
}
}
}
if (activity != null)
{
workflowDetail.IsWindowsActivity = windowsWorkflow;
workflowDetail.CompiledAssemblyPath = resultingCompiledAssemblyPath;
workflowDetail.CompiledAssemblyName = resultingCompiledAssemblyName;
lock (_syncObject)
{
WorkflowJobDefinition definitionToRemove =
_workflowDetailsCache.Keys.FirstOrDefault(item => item.InstanceId == definition.InstanceId);
if (definitionToRemove != null)
_workflowDetailsCache.Remove(definition);
_workflowDetailsCache.Add(definition, workflowDetail);
}
// If cached activity count reaches _cacheSize,
// Removing the cached activity at index 0 and adding the new activity to the activity cache,
// Old logic was to clear 1000 cached activities and recompiling them again when needed.
//
if (_cachedActivities.Count == _cacheSize)
{
Activity removedActivity;
_cachedActivities.TryRemove(_cachedActivities.Keys.ElementAt<WorkflowJobDefinition>(0), out removedActivity);
}
_cachedActivities.TryAdd(definition, activity);
return activity;
}
// we should never hit this point under normal course of operations
return null;
}
/// <summary>
///
/// </summary>
/// <param name="definition"></param>
/// <param name="windowsWorkflow"></param>
/// <returns></returns>
internal Activity GetActivityFromCache(WorkflowJobDefinition definition, out bool windowsWorkflow)
{
Activity activity = null;
WorkflowDetails workflowDetail;
// initialize windowsWorkflow to false
windowsWorkflow = false;
if (_workflowDetailsCache.TryGetValue(definition, out workflowDetail))
{
// if there is a workflow activity we would have already computed whether it is a
// Windows workflow, set the same
windowsWorkflow = workflowDetail.IsWindowsActivity;
if (workflowDetail.ActivityTree != null)
{
if (!AllowExternalActivity)
{
Debug.Assert(false, "Product code should not contain passing an activity to definition cache");
}
activity = workflowDetail.ActivityTree;
}
// if a cached value is available return the same
_cachedActivities.TryGetValue(definition, out activity);
if (activity == null)
{
// if activity is not available in cache recompile using info in
// definition cache
activity = CompileActivityAndSaveInCache(definition, null, null, out windowsWorkflow);
}
definition.LastUsedDateTime = DateTime.Now;
}
return activity;
}
/// <summary>
///
/// </summary>
/// <param name="xaml"></param>
/// <param name="workflowJobDefinition"></param>
/// <returns></returns>
internal Activity GetActivityFromCache(string xaml, out WorkflowJobDefinition workflowJobDefinition)
{
workflowJobDefinition = null;
foreach (var definition in
_workflowDetailsCache.Keys.Where(definition => string.Equals(definition.Xaml, xaml, StringComparison.OrdinalIgnoreCase)))
{
bool windowsWorkflow;
workflowJobDefinition = definition;
return GetActivityFromCache(definition, out windowsWorkflow);
}
return null;
}
private readonly object _syncObject = new object();
#endregion Internal
#region Test Helpers
internal Dictionary<WorkflowJobDefinition, WorkflowDetails> WorkflowDetailsCache
{
get { return _workflowDetailsCache; }
}
internal ConcurrentDictionary<WorkflowJobDefinition, Activity> ActivityCache
{
get { return _cachedActivities; }
}
internal void ClearAll()
{
_workflowDetailsCache.Clear();
_cachedActivities.Clear();
}
// only called from test
internal Activity GetActivity(Guid instanceId)
{
WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(typeof(WorkflowJobSourceAdapter),
string.Empty, string.Empty,
string.Empty,
WorkflowJobDefinition.EmptyEnumerable,
string.Empty, null, string.Empty) { InstanceId = instanceId };
bool windowsWorkflow;
Activity activity = GetActivityFromCache(workflowJobDefinition, out windowsWorkflow) ??
CompileActivityAndSaveInCache(workflowJobDefinition, null, null, out windowsWorkflow);
return activity;
}
//only called from test
internal Activity GetActivity(JobDefinition definition, string xaml)
{
bool windowsWorkflow;
WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(definition, string.Empty,
WorkflowJobDefinition.EmptyEnumerable,
string.Empty,
xaml);
Activity activity = GetActivityFromCache(workflowJobDefinition, out windowsWorkflow) ??
CompileActivityAndSaveInCache(workflowJobDefinition, null, null, out windowsWorkflow);
return activity;
}
//only called from test
internal Activity GetActivity(JobDefinition definition, string xaml, string[] dependentWorkflows)
{
bool windowsWorkflow;
WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(definition, string.Empty,
dependentWorkflows ?? WorkflowJobDefinition.EmptyEnumerable,
string.Empty,
xaml);
Activity activity = GetActivityFromCache(workflowJobDefinition, out windowsWorkflow) ??
CompileActivityAndSaveInCache(workflowJobDefinition, null, null, out windowsWorkflow);
return activity;
}
internal Activity GetActivity(JobDefinition definition, out bool windowsWorkflow)
{
WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(definition);
Activity activity = GetActivityFromCache(workflowJobDefinition, out windowsWorkflow) ??
CompileActivityAndSaveInCache(workflowJobDefinition, null, null, out windowsWorkflow);
return activity;
}
/// <summary>
/// Remove a cached definition. Needed when functions are removed to release resources.
/// </summary>
/// <param name="definition">Xaml definition to remove.</param>
/// <returns>True if succeeded.</returns>
internal bool RemoveCachedActivity(JobDefinition definition)
{
Debug.Assert(definition != null);
WorkflowJobDefinition workflowJobDefinition = new WorkflowJobDefinition(definition);
Activity activity;
_cachedActivities.TryRemove(workflowJobDefinition, out activity);
lock (_syncObject)
{
if (_workflowDetailsCache.ContainsKey(workflowJobDefinition))
{
return _workflowDetailsCache.Remove(workflowJobDefinition);
}
}
return false;
}
internal bool RemoveCachedActivity(Guid instanceId)
{
var definition = new JobDefinition(null, null, null);
definition.InstanceId = instanceId;
return RemoveCachedActivity(definition);
}
#endregion Test Helpers
}
internal class CompareBasedOnInstanceId : IEqualityComparer<WorkflowJobDefinition>
{
#region IEqualityComparer<JobDefinition> Members
public bool Equals(WorkflowJobDefinition x, WorkflowJobDefinition y)
{
return x.InstanceId == y.InstanceId;
}
public int GetHashCode(WorkflowJobDefinition obj)
{
return obj.InstanceId.GetHashCode();
}
#endregion
}
internal class CompareBasedOnCommand : IEqualityComparer<WorkflowJobDefinition>
{
#region IEqualityComparer<JobDefinition> Members
public bool Equals(WorkflowJobDefinition x, WorkflowJobDefinition y)
{
bool returnValue = false;
if (String.Equals(y.ModulePath, x.ModulePath, StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(y.Command, x.Command, StringComparison.OrdinalIgnoreCase))
{
returnValue = true;
}
}
return returnValue;
}
public int GetHashCode(WorkflowJobDefinition obj)
{
int hashCode = 0;
string moduleQualifiedCommand = string.Empty;
if (!string.IsNullOrEmpty(obj.ModulePath))
moduleQualifiedCommand += obj.ModulePath;
if (!string.IsNullOrEmpty(obj.Command))
moduleQualifiedCommand += obj.Command;
hashCode = moduleQualifiedCommand.GetHashCode();
return hashCode;
}
private static readonly CompareBasedOnCommand Comparer = new CompareBasedOnCommand();
internal static bool Compare(WorkflowJobDefinition x, WorkflowJobDefinition y)
{
return Comparer.Equals(x, y);
}
#endregion
}
internal class WorkflowJobDefinition : JobDefinition
{
/// <summary>
///
/// </summary>
/// <param name="jobSourceAdapterType"></param>
/// <param name="command"></param>
/// <param name="name"></param>
public WorkflowJobDefinition(Type jobSourceAdapterType, string command, string name) : base(jobSourceAdapterType, command, name)
{
IsScriptWorkflow = false;
}
internal WorkflowJobDefinition(Type jobSourceAdapterType, string command, string name, string modulePath,
IEnumerable<string> dependentWorkflows, string dependentAssemblyPath, Dictionary<string, string> requiredAssemblies, string xaml)
: this(jobSourceAdapterType, command, name)
{
_modulePath = modulePath;
_dependentAssemblyPath = dependentAssemblyPath;
_dependentWorkflows.AddRange(dependentWorkflows);
_requiredAssemblies = requiredAssemblies;
_xaml = xaml;
_lastUsedDateTime = DateTime.Now;
}
internal WorkflowJobDefinition(JobDefinition jobDefinition, string modulePath,
IEnumerable<string> dependentWorkflows, string dependentAssemblyPath, string xaml)
: this(jobDefinition.JobSourceAdapterType, jobDefinition.Command, jobDefinition.Name, modulePath, dependentWorkflows, dependentAssemblyPath, null, xaml)
{
InstanceId = jobDefinition.InstanceId;
}
internal WorkflowJobDefinition(JobDefinition jobDefinition)
:this(jobDefinition, string.Empty, EmptyEnumerable, string.Empty, string.Empty)
{
}
private readonly string _modulePath;
internal string ModulePath
{
get { return _modulePath; }
}
private readonly List<string> _dependentWorkflows = new List<string>();
internal List<string> DependentWorkflows
{
get { return _dependentWorkflows; }
}
private readonly string _dependentAssemblyPath;
internal string DependentAssemblyPath
{
get { return _dependentAssemblyPath; }
}
private readonly Dictionary<string, string> _requiredAssemblies;
internal Dictionary<string, string> RequiredAssemblies
{
get { return _requiredAssemblies; }
}
private readonly string _xaml;
internal string Xaml
{
get { return _xaml; }
}
internal bool IsScriptWorkflow { get; set; }
internal static IEnumerable<string> EmptyEnumerable = new Collection<string>();
private DateTime _lastUsedDateTime;
internal DateTime LastUsedDateTime
{
get { return _lastUsedDateTime; }
set { _lastUsedDateTime = value; }
}
/// <summary>
/// Returns the same object is the specified job definition is a
/// WorkflowJobDefinition. If not creates a new one and assigns
/// the same
/// </summary>
/// <param name="definition">job definition to check</param>
/// <returns>WorkflowJobDefinition equivalent</returns>
internal static WorkflowJobDefinition AsWorkflowJobDefinition(JobDefinition definition)
{
return definition as WorkflowJobDefinition ??
(DefinitionCache.Instance.GetDefinition(definition.InstanceId) as WorkflowJobDefinition ??
new WorkflowJobDefinition(definition));
}
/// <summary>
///
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
base.GetObjectData(info, context);
throw new NotImplementedException();
}
/// <summary>
/// Workflow script file name or null if no associated file.
/// </summary>
internal string WorkflowScriptFile
{
get;
set;
}
/// <summary>
/// Full workflow script source.
/// </summary>
internal string WorkflowFullScript
{
get;
set;
}
}
}
@@ -1,174 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Diagnostics;
using System.Threading;
/// <summary>
/// A generic base class for IAsyncResult implementations
/// that wraps a ManualResetEvent.
/// </summary>
abstract class FileStoreAsyncResult : IAsyncResult
{
AsyncCallback callback;
object state;
bool completedSynchronously;
bool endCalled;
Exception exception;
bool isCompleted;
ManualResetEvent manualResetEvent;
object thisLock;
protected FileStoreAsyncResult(AsyncCallback callback, object state)
{
this.callback = callback;
this.state = state;
this.thisLock = new object();
}
public object AsyncState
{
get
{
return state;
}
}
public WaitHandle AsyncWaitHandle
{
get
{
if (manualResetEvent != null)
{
return manualResetEvent;
}
lock (ThisLock)
{
if (manualResetEvent == null)
{
manualResetEvent = new ManualResetEvent(isCompleted);
}
}
return manualResetEvent;
}
}
public bool CompletedSynchronously
{
get
{
return completedSynchronously;
}
}
public bool IsCompleted
{
get
{
return isCompleted;
}
}
object ThisLock
{
get
{
return this.thisLock;
}
}
// Call this version of complete when your asynchronous operation is complete. This will update the state
// of the operation and notify the callback.
protected void Complete(bool completedSynchronously)
{
if (isCompleted)
{
// It is a bug to call Complete twice.
throw new InvalidOperationException(Resources.AsyncResultAlreadyCompleted);
}
this.completedSynchronously = completedSynchronously;
if (completedSynchronously)
{
// If we completedSynchronously, then there is no chance that the manualResetEvent was created so
// we do not need to worry about a race condition.
Debug.Assert(this.manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult.");
this.isCompleted = true;
}
else
{
lock (ThisLock)
{
this.isCompleted = true;
if (this.manualResetEvent != null)
{
this.manualResetEvent.Set();
}
}
}
// If the callback throws, there is a bug in the callback implementation
if (callback != null)
{
callback(this);
}
}
// Call this version of complete if you raise an exception during processing. In addition to notifying
// the callback, it will capture the exception and store it to be thrown during AsyncResult.End.
protected void Complete(bool completedSynchronously, Exception exception)
{
this.exception = exception;
Complete(completedSynchronously);
}
// End should be called when the End function for the asynchronous operation is complete. It
// ensures the asynchronous operation is complete, and does some common validation.
protected static TAsyncResult End<TAsyncResult>(IAsyncResult result)
where TAsyncResult : FileStoreAsyncResult
{
if (result == null)
{
throw new ArgumentNullException("result");
}
TAsyncResult asyncResult = result as TAsyncResult;
if (asyncResult == null)
{
throw new ArgumentException(Resources.InvalidAsyncResult);
}
if (asyncResult.endCalled)
{
throw new InvalidOperationException(Resources.AsyncResultAlreadyEnded);
}
asyncResult.endCalled = true;
if (!asyncResult.isCompleted)
{
asyncResult.AsyncWaitHandle.WaitOne();
}
if (asyncResult.manualResetEvent != null)
{
asyncResult.manualResetEvent.Close();
}
if (asyncResult.exception != null)
{
throw asyncResult.exception;
}
return asyncResult;
}
}
}
@@ -1,225 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Runtime.DurableInstancing;
using System.Activities.DurableInstancing;
using System.Collections.Generic;
using System.Xml.Linq;
using System.IO;
using System.Xml;
using System.Management.Automation.Tracing;
using System.Activities.Persistence;
internal class FileInstanceStore : InstanceStore
{
private static readonly Tracer StructuredTracer = new Tracer();
private readonly PSWorkflowFileInstanceStore _stores;
internal FileInstanceStore(PSWorkflowFileInstanceStore stores)
{
_stores = stores;
}
protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
{
StructuredTracer.Correlate();
try
{
if (command is SaveWorkflowCommand)
{
return new TypedCompletedAsyncResult<bool>(SaveWorkflow(context, (SaveWorkflowCommand)command), callback, state);
}
else if (command is LoadWorkflowCommand)
{
return new TypedCompletedAsyncResult<bool>(LoadWorkflow(context, (LoadWorkflowCommand)command), callback, state);
}
else if (command is CreateWorkflowOwnerCommand)
{
return new TypedCompletedAsyncResult<bool>(CreateWorkflowOwner(context, (CreateWorkflowOwnerCommand)command), callback, state);
}
else if (command is DeleteWorkflowOwnerCommand)
{
return new TypedCompletedAsyncResult<bool>(DeleteWorkflowOwner(context, (DeleteWorkflowOwnerCommand)command), callback, state);
}
return new TypedCompletedAsyncResult<bool>(false, callback, state);
}
catch (Exception e)
{
return new TypedCompletedAsyncResult<Exception>(e, callback, state);
}
}
protected override bool EndTryCommand(IAsyncResult result)
{
StructuredTracer.Correlate();
TypedCompletedAsyncResult<Exception> exceptionResult = result as TypedCompletedAsyncResult<Exception>;
if (exceptionResult != null)
{
throw exceptionResult.Data;
}
return TypedCompletedAsyncResult<bool>.End(result);
}
private bool SaveWorkflow(InstancePersistenceContext context, SaveWorkflowCommand command)
{
if (context.InstanceVersion == -1)
{
context.BindAcquiredLock(0);
}
if (command.CompleteInstance)
{
context.CompletedInstance();
}
else
{
string instanceType = "";
const string InstanceTypeXName = "{urn:schemas-microsoft-com:System.Runtime.DurableInstancing/4.0/metadata}InstanceType";
InstanceValue instanceTypeInstanceValue;
if (command.InstanceMetadataChanges.TryGetValue(InstanceTypeXName, out instanceTypeInstanceValue))
{
instanceType = instanceTypeInstanceValue.Value.ToString();
}
Dictionary<string, object> fullInstanceData = new Dictionary<string, object>();
fullInstanceData.Add("instanceId", context.InstanceView.InstanceId);
fullInstanceData.Add("instanceOwnerId", context.InstanceView.InstanceOwner.InstanceOwnerId);
fullInstanceData.Add("instanceData", SerializeablePropertyBag(command.InstanceData));
fullInstanceData.Add("instanceMetadata", SerializeInstanceMetadata(context, command));
foreach (KeyValuePair<XName, InstanceValue> property in command.InstanceMetadataChanges)
{
context.WroteInstanceMetadataValue(property.Key, property.Value);
}
context.PersistedInstance(command.InstanceData);
_stores.Save(WorkflowStoreComponents.Definition
| WorkflowStoreComponents.Metadata
| WorkflowStoreComponents.Streams
| WorkflowStoreComponents.TerminatingError
| WorkflowStoreComponents.Timer
| WorkflowStoreComponents.ActivityState
| WorkflowStoreComponents.JobState,
fullInstanceData);
}
return true;
}
private bool LoadWorkflow(InstancePersistenceContext context, LoadWorkflowCommand command)
{
if (command.AcceptUninitializedInstance)
{
return false;
}
if (context.InstanceVersion == -1)
{
context.BindAcquiredLock(0);
}
Guid instanceId = context.InstanceView.InstanceId;
Guid instanceOwnerId = context.InstanceView.InstanceOwner.InstanceOwnerId;
IDictionary<XName, InstanceValue> instanceData = null;
IDictionary<XName, InstanceValue> instanceMetadata = null;
Dictionary<string, object> fullInstanceData = _stores.LoadWorkflowContext();
instanceData = this.DeserializePropertyBag((Dictionary<XName, object>)fullInstanceData["instanceData"]);
instanceMetadata = this.DeserializePropertyBag((Dictionary<XName, object>)fullInstanceData["instanceMetadata"]);
context.LoadedInstance(InstanceState.Initialized, instanceData, instanceMetadata, null, null);
return true;
}
private bool CreateWorkflowOwner(InstancePersistenceContext context, CreateWorkflowOwnerCommand command)
{
Guid instanceOwnerId = Guid.NewGuid();
context.BindInstanceOwner(instanceOwnerId, instanceOwnerId);
context.BindEvent(HasRunnableWorkflowEvent.Value);
return true;
}
private bool DeleteWorkflowOwner(InstancePersistenceContext context, DeleteWorkflowOwnerCommand command)
{
return true;
}
private Dictionary<XName, object> SerializeablePropertyBag(IDictionary<XName, InstanceValue> source)
{
Dictionary<XName, object> scratch = new Dictionary<XName, object>();
foreach (KeyValuePair<XName, InstanceValue> property in source)
{
bool writeOnly = (property.Value.Options & InstanceValueOptions.WriteOnly) != 0;
if (!writeOnly && !property.Value.IsDeletedValue)
{
scratch.Add(property.Key, property.Value.Value);
}
}
return scratch;
}
private Dictionary<XName, object> SerializeInstanceMetadata(InstancePersistenceContext context, SaveWorkflowCommand command)
{
Dictionary<XName, object> metadata = null;
foreach (var property in command.InstanceMetadataChanges)
{
if (!property.Value.Options.HasFlag(InstanceValueOptions.WriteOnly))
{
if (metadata == null)
{
metadata = new Dictionary<XName, object>();
// copy current metadata. note that we must rid of InstanceValue as it is not properly serializeable
foreach (var m in context.InstanceView.InstanceMetadata)
{
metadata.Add(m.Key, m.Value.Value);
}
}
if (metadata.ContainsKey(property.Key))
{
if (property.Value.IsDeletedValue) metadata.Remove(property.Key);
else metadata[property.Key] = property.Value.Value;
}
else
{
if (!property.Value.IsDeletedValue) metadata.Add(property.Key, property.Value.Value);
}
}
}
if (metadata == null)
metadata = new Dictionary<XName, object>();
return metadata;
}
private IDictionary<XName, InstanceValue> DeserializePropertyBag(Dictionary<XName, object> source)
{
Dictionary<XName, InstanceValue> destination = new Dictionary<XName, InstanceValue>();
foreach (KeyValuePair<XName, object> property in source)
{
destination.Add(property.Key, new InstanceValue(property.Value));
}
return destination;
}
}
}
@@ -1,68 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.IO;
using System.Security.Cryptography;
using System.Management.Automation.Tracing;
/// <summary>
/// This class implements the encrypt and decrypt functionality.
/// </summary>
internal class InstanceStoreCryptography
{
/// <summary>
/// Tracer initialization.
/// </summary>
private static readonly PowerShellTraceSource Tracer = PowerShellTraceSourceFactory.GetTraceSource();
/// <summary>
/// The additional entry for security 'POWERSHELLWORKFLOW'
/// </summary>
private static byte[] s_additionalEntropy = { (byte)'P', (byte)'O', (byte)'W', (byte)'E', (byte)'R', (byte)'S', (byte)'H', (byte)'E', (byte)'L', (byte)'L', (byte)'W', (byte)'O', (byte)'R', (byte)'K', (byte)'F', (byte)'L', (byte)'O', (byte)'W' };
/// <summary>
/// Protect the data.
/// </summary>
/// <param name="data">The input data for encryption.</param>
/// <returns>Returns encrypted data.</returns>
internal static byte[] Protect(byte[] data)
{
try
{
// Encrypt the data using DataProtectionScope.CurrentUser. The result can be decrypted
// only by the same current user.
return ProtectedData.Protect(data, s_additionalEntropy, DataProtectionScope.CurrentUser);
}
catch (CryptographicException e)
{
Tracer.TraceException(e);
throw e;
}
}
/// <summary>
/// Unprotect data the encrypted data.
/// </summary>
/// <param name="data">Encrypted data.</param>
/// <returns>Returns decrypted data.</returns>
internal static byte[] Unprotect(byte[] data)
{
try
{
return ProtectedData.Unprotect(data, s_additionalEntropy, DataProtectionScope.CurrentUser);
}
catch (CryptographicException e)
{
Tracer.TraceException(e);
throw e;
}
}
}
}
@@ -1,44 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.IO;
using System.Security.Cryptography;
using System.Management.Automation.Tracing;
using System.Security.AccessControl;
using System.Security.Principal;
/// <summary>
/// This class implements the encrypt and decrypt functionality.
/// </summary>
internal class InstanceStorePermission
{
internal static void SetDirectoryPermissions(string folderName)
{
string account = WindowsIdentity.GetCurrent().Name;
RemoveInheritablePermissions(folderName);
AddDirectorySecurity(folderName, account, FileSystemRights.Modify, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow);
}
private static void AddDirectorySecurity(string folderName, string account, FileSystemRights rights, InheritanceFlags inheritance, PropagationFlags propagation, AccessControlType controlType)
{
DirectoryInfo info = new DirectoryInfo(folderName);
DirectorySecurity dSecurity = info.GetAccessControl();
dSecurity.AddAccessRule(new FileSystemAccessRule(account, rights, inheritance, propagation, controlType));
info.SetAccessControl(dSecurity);
}
private static void RemoveInheritablePermissions(string folderName)
{
DirectoryInfo info = new DirectoryInfo(folderName);
DirectorySecurity dSecurity = info.GetAccessControl();
const bool IsProtected = true;
const bool PreserveInheritance = false;
dSecurity.SetAccessRuleProtection(IsProtected, PreserveInheritance);
info.SetAccessControl(dSecurity);
}
}
}
@@ -1,41 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Diagnostics;
using System.Threading;
/// <summary>
/// A strongly typed AsyncResult.
/// </summary>
/// <typeparam name="T"></typeparam>
abstract class TypedAsyncResult<T> : FileStoreAsyncResult
{
T data;
protected TypedAsyncResult(AsyncCallback callback, object state)
: base(callback, state)
{
}
public T Data
{
get { return data; }
}
protected void Complete(T data, bool completedSynchronously)
{
this.data = data;
Complete(completedSynchronously);
}
public static T End(IAsyncResult result)
{
TypedAsyncResult<T> typedResult = FileStoreAsyncResult.End<TypedAsyncResult<T>>(result);
return typedResult.Data;
}
}
}
@@ -1,35 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Diagnostics;
using System.Threading;
/// <summary>
/// A strongly typed AsyncResult that completes as soon as it is instantiated.
/// </summary>
/// <typeparam name="T"></typeparam>
class TypedCompletedAsyncResult<T> : TypedAsyncResult<T>
{
public TypedCompletedAsyncResult(T data, AsyncCallback callback, object state)
: base(callback, state)
{
Complete(data, true);
}
public new static T End(IAsyncResult result)
{
TypedCompletedAsyncResult<T> completedResult = result as TypedCompletedAsyncResult<T>;
if (completedResult == null)
{
throw new ArgumentException(Resources.InvalidAsyncResult);
}
return TypedAsyncResult<T>.End(completedResult);
}
}
}
@@ -1,930 +0,0 @@
/*
* Copyright (c) 2010 Microsoft Corporation. All rights reserved
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Xml;
using System.Diagnostics.CodeAnalysis;
using System.Security.Principal;
using Microsoft.PowerShell.Commands;
using System.Activities;
using System.Collections.Concurrent;
using Microsoft.PowerShell.Activities;
using System.Management.Automation.Remoting;
namespace Microsoft.PowerShell.Workflow
{
/// <summary>
/// PSWorkflowConfigurationProvider
/// </summary>
public class PSWorkflowConfigurationProvider
{
#region Public Methods
/// <summary>
/// Default constructor
/// </summary>
public PSWorkflowConfigurationProvider()
{
_wfOptions = new PSWorkflowExecutionOption();
LoadFromDefaults();
}
#endregion
#region Private Members
private string _configProviderId;
private String _privateData;
private readonly object _syncObject = new object();
private bool _isPopulated;
private const string PrivateDataToken = "PrivateData";
private const string NameToken = "Name";
private const string ParamToken = "Param";
private const string ValueToken = "Value";
internal const string PSDefaultActivities = "PSDefaultActivities";
private PSWorkflowExecutionOption _wfOptions;
internal const string TokenPersistencePath = "persistencepath";
internal static readonly string DefaultPersistencePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\Windows\PowerShell\WF\PS");
internal const string TokenPersistWithEncryption = "persistwithencryption";
internal static readonly bool DefaultPersistWithEncryption = false;
internal const string TokenMaxPersistenceStoreSizeGB = "maxpersistencestoresizegb";
internal static readonly long DefaultMaxPersistenceStoreSizeGB = 10; // In GB
internal const string TokenMaxRunningWorkflows = "maxrunningworkflows";
internal static readonly int DefaultMaxRunningWorkflows = 30;
internal const int MinMaxRunningWorkflows = 1;
internal const int MaxMaxRunningWorkflows = int.MaxValue;
internal const string TokenAllowedActivity = "allowedactivity";
internal static readonly IEnumerable<string> DefaultAllowedActivity = new string[] { PSDefaultActivities };
internal const string TokenOutOfProcessActivity = "outofprocessactivity";
internal static readonly IEnumerable<string> DefaultOutOfProcessActivity = new string[] { "InlineScript" };
internal const string TokenEnableValidation = "enablevalidation";
internal static readonly bool DefaultEnableValidation = false;
internal const string TokenMaxDisconnectedSessions = "maxdisconnectedsessions";
internal static readonly int DefaultMaxDisconnectedSessions = 1000;
internal const int MinMaxDisconnectedSessions = 1;
internal const int MaxMaxDisconnectedSessions = int.MaxValue;
internal const string TokenMaxConnectedSessions = "maxconnectedsessions";
internal static readonly int DefaultMaxConnectedSessions = 100;
internal const int MinMaxConnectedSessions = 1;
internal const int MaxMaxConnectedSessions = int.MaxValue;
internal const string TokenMaxSessionsPerWorkflow = "maxsessionsperworkflow";
internal static readonly int DefaultMaxSessionsPerWorkflow = 5;
internal const int MinMaxSessionsPerWorkflow = 1;
internal const int MaxMaxSessionsPerWorkflow = int.MaxValue;
internal const string TokenMaxSessionsPerRemoteNode = "maxsessionsperremotenode";
internal static readonly int DefaultMaxSessionsPerRemoteNode = 5;
internal const int MinMaxSessionsPerRemoteNode = 1;
internal const int MaxMaxSessionsPerRemoteNode = int.MaxValue;
internal const string TokenMaxActivityProcesses = "maxactivityprocesses";
internal static readonly int DefaultMaxActivityProcesses = 5;
internal const int MinMaxActivityProcesses = 1;
internal const int MaxMaxActivityProcesses = int.MaxValue;
internal const string TokenActivityProcessIdleTimeoutSec = "activityprocessidletimeoutsec";
internal static readonly int DefaultActivityProcessIdleTimeoutSec = 60;
internal const int MinActivityProcessIdleTimeoutSec = 1;
internal const int MaxActivityProcessIdleTimeoutSec = int.MaxValue;
internal const string TokenWorkflowApplicationPersistUnloadTimeoutSec = "workflowapplicationpersistunloadtimeoutsec";
internal static readonly int DefaultWorkflowApplicationPersistUnloadTimeoutSec = 5;
internal const int MinWorkflowApplicationPersistUnloadTimeoutSec = 0;
internal const int MaxWorkflowApplicationPersistUnloadTimeoutSec = int.MaxValue;
internal const string TokenWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = "wsmanpluginreportcompletiononzeroactivesessionswaitintervalmsec";
internal static readonly int DefaultWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = 30 * 1000;
internal const int MinWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = 100;
internal const int MaxWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = int.MaxValue;
internal const string TokenActivitiesCacheCleanupIntervalMSec = "activitiescachecleanupintervalmsec";
internal static readonly int DefaultActivitiesCacheCleanupIntervalMSec = 5 * 60 * 1000;
internal const int MinActivitiesCacheCleanupIntervalMSec = 100;
internal const int MaxActivitiesCacheCleanupIntervalMSec = int.MaxValue;
internal const string TokenRemoteNodeSessionIdleTimeoutSec = "remotenodesessionidletimeoutsec";
internal static readonly int DefaultRemoteNodeSessionIdleTimeoutSec = 60;
internal const int MinRemoteNodeSessionIdleTimeoutSec = 30;
internal const int MaxRemoteNodeSessionIdleTimeoutSec = 30000;
private int _remoteNodeSessionIdleTimeoutSec;
internal const string TokenSessionThrottleLimit = "sessionthrottlelimit";
internal static readonly int DefaultSessionThrottleLimit = 100;
internal const int MinSessionThrottleLimit = 1;
internal const int MaxSessionThrottleLimit = int.MaxValue;
internal const string TokenValidationCacheLimit = "validationcachelimit";
internal static readonly int DefaultValidationCacheLimit = 10000;
private int _validationCacheLimit;
internal const string TokenCompiledAssemblyCacheLimit = "compiledassemblycachelimit";
internal static readonly int DefaultCompiledAssemblyCacheLimit = 10000;
private int _compiledAssemblyCacheLimit;
internal const string TokenOutOfProcessActivityCacheLimit = "outofprocessactivitycachelimit";
internal static readonly int DefaultOutOfProcessActivityCacheLimit = 10000;
private int _outOfProcessActivityCacheLimit;
internal static readonly int DefaultPSPersistInterval = 30; // in seconds
internal const string TokenWorkflowShutdownTimeoutMSec = "workflowshutdowntimeoutmsec";
internal static readonly int DefaultWorkflowShutdownTimeoutMSec = 500; // 0.5 secs
internal const int MinWorkflowShutdownTimeoutMSec = 0;
internal const int MaxWorkflowShutdownTimeoutMSec = 5 * 1000; // 5 secs
internal const string TokenMaxInProcRunspaces = "maxinprocrunspaces";
internal static readonly int DefaultMaxInProcRunspaces = DefaultMaxRunningWorkflows * 2;
private int _maxInProcRunspaces = DefaultMaxInProcRunspaces;
private readonly ConcurrentDictionary<Type, bool> outOfProcessActivityCache = new ConcurrentDictionary<Type, bool>();
#endregion Private Members
#region Private Methods
internal static PSWorkflowExecutionOption LoadConfig(string privateData, PSWorkflowConfigurationProvider configuration)
{
PSWorkflowExecutionOption target = new PSWorkflowExecutionOption();
if (String.IsNullOrEmpty(privateData))
{
return target;
}
XmlReaderSettings readerSettings = new XmlReaderSettings
{
CheckCharacters = false,
IgnoreComments = true,
IgnoreProcessingInstructions = true,
MaxCharactersInDocument = 10000,
XmlResolver = null,
ConformanceLevel = ConformanceLevel.Fragment
};
using (XmlReader reader = XmlReader.Create(new StringReader(privateData), readerSettings))
{
// read the header <PrivateData>
if (reader.ReadToFollowing(PrivateDataToken))
{
HashSet<string> assignedParams = new HashSet<string>();
bool found = reader.ReadToDescendant(ParamToken);
while (found)
{
if (!reader.MoveToAttribute(NameToken))
{
throw new PSArgumentException(Resources.NameNotSpecifiedForParam);
}
string optionName = reader.Value;
if (!reader.MoveToAttribute(ValueToken))
{
throw new PSArgumentException(Resources.ValueNotSpecifiedForParam);
}
if (assignedParams.Contains(optionName.ToLower(CultureInfo.InvariantCulture)))
{
throw new PSArgumentException(Resources.ParamSpecifiedMoreThanOnce, optionName);
}
string optionValue = reader.Value;
Update(optionName, optionValue, target, configuration);
assignedParams.Add(optionName.ToLower(CultureInfo.InvariantCulture));
found = reader.ReadToFollowing(ParamToken);
}
}
}
return target;
}
/// <summary>
///
/// </summary>
public PSWorkflowRuntime Runtime
{
get;
internal set;
}
private bool? _powerShellActivitiesAreAllowed;
internal bool PSDefaultActivitiesAreAllowed
{
get
{
if (_powerShellActivitiesAreAllowed == null)
{
lock (_syncObject) {
if (_powerShellActivitiesAreAllowed == null)
{
bool allowed = (AllowedActivity ?? new string[0]).Any(a => string.Equals(a, PSDefaultActivities, StringComparison.OrdinalIgnoreCase));
_powerShellActivitiesAreAllowed = allowed;
}
}
}
return _powerShellActivitiesAreAllowed.Value;
}
}
/// <summary>
/// Using optionName and optionValue updates the current object
/// </summary>
/// <param name="optionName"></param>
/// <param name="value"></param>
/// <param name="target"></param>
/// <param name="configuration"></param>
private static void Update(string optionName, string value, PSWorkflowExecutionOption target, PSWorkflowConfigurationProvider configuration)
{
switch (optionName.ToLower(CultureInfo.InvariantCulture))
{
case TokenWorkflowApplicationPersistUnloadTimeoutSec:
target.WorkflowApplicationPersistUnloadTimeoutSec = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec:
target.WSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = (int)LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenActivitiesCacheCleanupIntervalMSec:
target.ActivitiesCacheCleanupIntervalMSec = (int)LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenActivityProcessIdleTimeoutSec:
target.ActivityProcessIdleTimeoutSec = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenAllowedActivity:
string[] activities = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
target.AllowedActivity = activities.Select(activity => activity.Trim()).ToArray();
break;
case TokenEnableValidation:
bool enableValidation;
if (bool.TryParse(value, out enableValidation))
{
target.EnableValidation = enableValidation;
}
break;
case TokenPersistencePath:
target.PersistencePath = Environment.ExpandEnvironmentVariables(value);
break;
case TokenMaxPersistenceStoreSizeGB:
target.MaxPersistenceStoreSizeGB = (long)LanguagePrimitives.ConvertTo(value, typeof(long), CultureInfo.InvariantCulture);
break;
case TokenPersistWithEncryption:
bool persistWithEncryption;
if (bool.TryParse(value, out persistWithEncryption))
{
target.PersistWithEncryption = persistWithEncryption;
}
break;
case TokenRemoteNodeSessionIdleTimeoutSec:
target.RemoteNodeSessionIdleTimeoutSec = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
if (configuration != null)
{
configuration._remoteNodeSessionIdleTimeoutSec = target.RemoteNodeSessionIdleTimeoutSec;
}
break;
case TokenMaxActivityProcesses:
target.MaxActivityProcesses = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenMaxConnectedSessions:
target.MaxConnectedSessions = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenMaxDisconnectedSessions:
target.MaxDisconnectedSessions = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenMaxRunningWorkflows:
target.MaxRunningWorkflows = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
configuration._maxInProcRunspaces = target.MaxRunningWorkflows*2;
break;
case TokenMaxSessionsPerRemoteNode:
target.MaxSessionsPerRemoteNode = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenMaxSessionsPerWorkflow:
target.MaxSessionsPerWorkflow = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenOutOfProcessActivity:
string[] outofProcActivities = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
target.OutOfProcessActivity = outofProcActivities.Select(activity => activity.Trim()).ToArray();
break;
case TokenSessionThrottleLimit:
{
target.SessionThrottleLimit = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
}
break;
case TokenValidationCacheLimit:
if (configuration != null)
{
configuration._validationCacheLimit = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
}
break;
case TokenCompiledAssemblyCacheLimit:
if (configuration != null)
{
configuration._compiledAssemblyCacheLimit = (int)LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
}
break;
case TokenOutOfProcessActivityCacheLimit:
if (configuration != null)
{
configuration._outOfProcessActivityCacheLimit = (int) LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
}
break;
case TokenWorkflowShutdownTimeoutMSec:
target.WorkflowShutdownTimeoutMSec = (int)LanguagePrimitives.ConvertTo(value, typeof(int), CultureInfo.InvariantCulture);
break;
case TokenMaxInProcRunspaces:
{
if (configuration != null)
{
configuration._maxInProcRunspaces =
(int) LanguagePrimitives.ConvertTo(value, typeof (int), CultureInfo.InvariantCulture);
}
}
break;
}
}
#endregion Private Methods
#region Internal Methods
/// <summary>
/// PSWorkflowConfigurationProvider
/// </summary>
/// <param name="applicationPrivateData"></param>
/// <param name="configProviderId"></param>
public PSWorkflowConfigurationProvider(string applicationPrivateData, string configProviderId)
{
Populate(applicationPrivateData, configProviderId);
}
private void LoadFromDefaults()
{
_wfOptions.PersistencePath = DefaultPersistencePath;
_wfOptions.MaxPersistenceStoreSizeGB = DefaultMaxPersistenceStoreSizeGB;
_wfOptions.PersistWithEncryption = DefaultPersistWithEncryption;
_wfOptions.MaxRunningWorkflows = DefaultMaxRunningWorkflows;
_wfOptions.AllowedActivity = new List<string>(DefaultAllowedActivity).ToArray();
_wfOptions.OutOfProcessActivity = new List<string>(DefaultOutOfProcessActivity).ToArray();
_wfOptions.EnableValidation = DefaultEnableValidation;
_wfOptions.MaxDisconnectedSessions = DefaultMaxDisconnectedSessions;
_wfOptions.MaxConnectedSessions = DefaultMaxConnectedSessions;
_wfOptions.MaxSessionsPerWorkflow = DefaultMaxSessionsPerWorkflow;
_wfOptions.MaxSessionsPerRemoteNode = DefaultMaxSessionsPerRemoteNode;
_wfOptions.MaxActivityProcesses = DefaultMaxActivityProcesses;
_wfOptions.ActivityProcessIdleTimeoutSec = DefaultActivityProcessIdleTimeoutSec;
_wfOptions.WorkflowApplicationPersistUnloadTimeoutSec = DefaultWorkflowApplicationPersistUnloadTimeoutSec;
_wfOptions.WSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = DefaultWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec;
_wfOptions.ActivitiesCacheCleanupIntervalMSec = DefaultActivitiesCacheCleanupIntervalMSec;
_wfOptions.RemoteNodeSessionIdleTimeoutSec = DefaultRemoteNodeSessionIdleTimeoutSec;
_wfOptions.SessionThrottleLimit = DefaultSessionThrottleLimit;
_validationCacheLimit = DefaultValidationCacheLimit;
_compiledAssemblyCacheLimit = DefaultCompiledAssemblyCacheLimit;
_outOfProcessActivityCacheLimit = DefaultOutOfProcessActivityCacheLimit;
_wfOptions.WorkflowShutdownTimeoutMSec = DefaultWorkflowShutdownTimeoutMSec;
ResetCaching();
}
private void ResetCaching()
{
_powerShellActivitiesAreAllowed = null;
outOfProcessActivityCache.Clear();
}
internal PSSenderInfo _senderInfo = null;
internal void Populate(string applicationPrivateData, string configProviderId, PSSenderInfo senderInfo)
{
_senderInfo = senderInfo;
Populate(applicationPrivateData, configProviderId);
}
/// <summary>
/// Populate the global configuration object with
/// information from the configuration xml
/// </summary>
/// <param name="applicationPrivateData">private data
/// associated with the endpoint</param>
/// <param name="configProviderId"></param>
public void Populate(string applicationPrivateData, string configProviderId)
{
if (_isPopulated)
{
return;
}
lock (_syncObject)
{
if (!_isPopulated)
{
_privateData = applicationPrivateData;
string[] tokens = configProviderId.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
_configProviderId = tokens.Length > 0 ? tokens[tokens.Length - 1] : configProviderId;
_isPopulated = true;
_wfOptions = LoadConfig(_privateData, this);
ResetCaching();
}
else
{
Debug.Assert(false, "Populate should only be called once");
}
}
}
#region PSWorkflowConfigurationProvider Implementation
/// <summary>
/// CreatePSActivityHostController
/// </summary>
/// <returns></returns>
public virtual PSActivityHostController CreatePSActivityHostController()
{
return new PSOutOfProcessActivityController(Runtime);
}
/// <summary>
/// CreatePSWorkflowInstance
/// </summary>
/// <param name="definition"></param>
/// <param name="metadata"></param>
/// <param name="pipelineInput"></param>
/// <param name="job"></param>
/// <returns></returns>
public virtual PSWorkflowInstance CreatePSWorkflowInstance(PSWorkflowDefinition definition, PSWorkflowContext metadata, PSDataCollection<PSObject> pipelineInput, PSWorkflowJob job)
{
return new PSWorkflowApplicationInstance(Runtime, definition, metadata, pipelineInput, job);
}
/// <summary>
/// CreatePSWorkflowInstance
/// </summary>
/// <param name="instanceId"></param>
/// <returns></returns>
public virtual PSWorkflowInstance CreatePSWorkflowInstance(PSWorkflowId instanceId)
{
return new PSWorkflowApplicationInstance(Runtime, instanceId);
}
/// <summary>
/// CreatePSWorkflowInstanceStore
/// </summary>
/// <param name="workflowInstance"></param>
/// <returns></returns>
public virtual PSWorkflowInstanceStore CreatePSWorkflowInstanceStore(PSWorkflowInstance workflowInstance)
{
return new PSWorkflowFileInstanceStore(this, workflowInstance);
}
/// <summary>
/// CreateWorkflowExtensions
/// </summary>
/// <returns></returns>
public virtual IEnumerable<object> CreateWorkflowExtensions()
{
if (PSWorkflowExtensions.CustomHandler != null)
{
return PSWorkflowExtensions.CustomHandler();
}
return null;
}
/// <summary>
/// CreateWorkflowExtensionCreationFunctions
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
[SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the Workflow.")]
public virtual IEnumerable<Func<T>> CreateWorkflowExtensionCreationFunctions<T>()
{
return null;
}
/// <summary>
/// CreateRemoteRunspaceProvider
/// </summary>
/// <returns></returns>
public virtual RunspaceProvider CreateRemoteRunspaceProvider()
{
return new ConnectionManager(RemoteNodeSessionIdleTimeoutSec * 1000,
MaxSessionsPerRemoteNode,
SessionThrottleLimit,
MaxConnectedSessions,
MaxDisconnectedSessions);
}
/// <summary>
/// Local runspace provider
/// </summary>
/// <param name="isUnbounded"></param>
/// <returns></returns>
public virtual RunspaceProvider CreateLocalRunspaceProvider(bool isUnbounded)
{
if(isUnbounded)
return new LocalRunspaceProvider(RemoteNodeSessionIdleTimeoutSec, LanguageMode);
else
return new LocalRunspaceProvider(RemoteNodeSessionIdleTimeoutSec, MaxInProcRunspaces, LanguageMode);
}
#endregion
/// <summary>
/// CurrentUserIdentity returns the current user
/// </summary>
internal WindowsIdentity CurrentUserIdentity
{
get { return _currentIdentity ?? (_currentIdentity = WindowsIdentity.GetCurrent()); }
}
private WindowsIdentity _currentIdentity;
/// <summary>
/// To be called only by test code
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This method is called from the tests")]
internal void ResetPopulate()
{
lock (_syncObject)
{
_isPopulated = false;
LoadFromDefaults();
}
}
#endregion Internal Methods
#region Configuration Properties
/// <summary>
/// ConfigProviderId
/// </summary>
internal string ConfigProviderId
{
get
{
return _configProviderId;
}
}
/// <summary>
/// PersistencePath
/// </summary>
internal string PersistencePath
{
get
{
return _wfOptions.PersistencePath;
}
}
internal bool IsDefaultStorePath;
private string _instanceStorePath;
internal string InstanceStorePath
{
get
{
if (_instanceStorePath != null)
return _instanceStorePath;
lock (_syncObject)
{
if (_instanceStorePath != null)
return _instanceStorePath;
if (CurrentUserIdentity.User != null)
{
string path = Path.Combine(_wfOptions.PersistencePath ?? DefaultPersistencePath, _configProviderId ?? "default", CurrentUserIdentity.User.Value);
WindowsPrincipal principal = new WindowsPrincipal(CurrentUserIdentity);
bool elevated = false;
bool nonInteractive = false;
bool credssp = false;
if (principal.IsInRole(WindowsBuiltInRole.Administrator))
elevated = true;
if (PSSessionConfigurationData.IsServerManager == false) // In order to avoid breaking change (SM+ might get affected)
{
if (!principal.IsInRole(new SecurityIdentifier(WellKnownSidType.InteractiveSid, null)))
nonInteractive = true;
if (_senderInfo != null &&
_senderInfo.UserInfo != null &&
_senderInfo.UserInfo.Identity != null &&
_senderInfo.UserInfo.Identity.AuthenticationType != null &&
_senderInfo.UserInfo.Identity.AuthenticationType.Equals("credssp", StringComparison.OrdinalIgnoreCase))
{
credssp = true;
}
}
if (credssp)
{
path += "_CP"; // the authentication type is credSSP
}
else
{
if (elevated)
path += "_EL"; // token is elevated
if (nonInteractive)
path += "_NI"; // token is not interactive
}
_instanceStorePath = path;
}
IsDefaultStorePath = string.IsNullOrEmpty(_configProviderId) ? true : false;
}
return _instanceStorePath;
}
}
/// <summary>
/// MaxPersistenceStoreSizeGB
/// </summary>
internal long MaxPersistenceStoreSizeGB
{
get
{
return _wfOptions.MaxPersistenceStoreSizeGB;
}
}
/// <summary>
/// PersistWithEncryption
/// </summary>
internal bool PersistWithEncryption
{
get
{
return _wfOptions.PersistWithEncryption;
}
}
/// <summary>
/// MaxRunningWorkflows
/// </summary>
public virtual int MaxRunningWorkflows
{
get
{
return _wfOptions.MaxRunningWorkflows;
}
}
/// <summary>
/// AllowedActivity
/// </summary>
public virtual IEnumerable<string> AllowedActivity
{
get
{
return _wfOptions.AllowedActivity;
}
}
/// <summary>
/// OutOfProcActivity
/// </summary>
public virtual IEnumerable<string> OutOfProcessActivity
{
get
{
return _wfOptions.OutOfProcessActivity;
}
}
/// <summary>
/// EnableValidation
/// </summary>
public virtual bool EnableValidation
{
get
{
return _wfOptions.EnableValidation;
}
}
/// <summary>
/// MaxDisconnectedSessions
/// </summary>
public virtual int MaxDisconnectedSessions
{
get
{
return _wfOptions.MaxDisconnectedSessions;
}
}
/// <summary>
/// MaxConnectedSessions
/// </summary>
public virtual int MaxConnectedSessions
{
get
{
return _wfOptions.MaxConnectedSessions;
}
}
/// <summary>
/// MaxSessionsPerWorkflow
/// </summary>
internal int MaxSessionsPerWorkflow
{
get
{
return _wfOptions.MaxSessionsPerWorkflow;
}
}
/// <summary>
/// MaxSessionsPerRemoteNode
/// </summary>
public virtual int MaxSessionsPerRemoteNode
{
get
{
return _wfOptions.MaxSessionsPerRemoteNode;
}
}
/// <summary>
/// MaxActivityProcesses
/// </summary>
public virtual int MaxActivityProcesses
{
get
{
return _wfOptions.MaxActivityProcesses;
}
}
/// <summary>
/// WorkflowApplicationPersistUnloadTimeoutSec
/// </summary>
public virtual int PSWorkflowApplicationPersistUnloadTimeoutSec
{
get
{
return _wfOptions.WorkflowApplicationPersistUnloadTimeoutSec;
}
}
/// <summary>
/// WSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec
/// </summary>
public virtual int WSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec
{
get
{
return _wfOptions.WSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec;
}
}
/// <summary>
/// ActivitiesCacheCleanupIntervalMSec
/// </summary>
public virtual int ActivitiesCacheCleanupIntervalMSec
{
get
{
return _wfOptions.ActivitiesCacheCleanupIntervalMSec;
}
}
/// <summary>
/// Local Machine Runspace Language Mode
/// </summary>
public virtual PSLanguageMode? LanguageMode
{
get
{
return null;
}
}
/// <summary>
/// ActivityProcessIdleTimeOutSec
/// </summary>
public virtual int ActivityProcessIdleTimeoutSec
{
get
{
return _wfOptions.ActivityProcessIdleTimeoutSec;
}
}
/// <summary>
/// RemoteNodeSessionIdleTimeOutSec
/// </summary>
public virtual int RemoteNodeSessionIdleTimeoutSec
{
get
{
return _wfOptions.RemoteNodeSessionIdleTimeoutSec;
}
}
/// <summary>
/// SessionThrottleLimit
/// </summary>
public virtual int SessionThrottleLimit
{
get
{
return _wfOptions.SessionThrottleLimit;
}
}
internal int ValidationCacheLimit
{
get { return _validationCacheLimit; }
}
internal int CompiledAssemblyCacheLimit
{
get { return _compiledAssemblyCacheLimit; }
}
internal int OutOfProcessActivityCacheLimit
{
get
{
return _outOfProcessActivityCacheLimit;
}
}
/// <summary>
/// WorkflowShutdownTimeoutMSec - the maximum time allowed to suspend the workflows before aborting them.
/// </summary>
internal int WorkflowShutdownTimeoutMSec
{
get
{
return _wfOptions.WorkflowShutdownTimeoutMSec;
}
}
/// <summary>
/// MaxInProcRunspaces
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public virtual int MaxInProcRunspaces
{
get { return _maxInProcRunspaces; }
}
/// <summary>
/// Get Activity Run Mode InProcess or Out of process
/// </summary>
/// <param name="activity"></param>
/// <returns></returns>
public virtual ActivityRunMode GetActivityRunMode(Activity activity)
{
if (activity == null)
throw new ArgumentNullException("activity");
if (outOfProcessActivityCache.Count >= OutOfProcessActivityCacheLimit)
outOfProcessActivityCache.Clear();
bool outOfProc = outOfProcessActivityCache.GetOrAdd(activity.GetType(), IsOutOfProcessActivity);
return outOfProc ? ActivityRunMode.OutOfProcess : ActivityRunMode.InProcess;
}
private bool IsOutOfProcessActivity(Type activityType)
{
return (OutOfProcessActivity ?? new string[0]).Any(outOfProcessActivity => false || IsMatched(outOfProcessActivity, activityType.Name) || IsMatched(outOfProcessActivity, activityType.FullName) || IsMatched(outOfProcessActivity, activityType.Assembly.GetName().Name + "\\" + activityType.Name) || IsMatched(outOfProcessActivity, activityType.Assembly.GetName().Name + "\\" + activityType.FullName) || IsMatched(outOfProcessActivity, activityType.Assembly.GetName().FullName + "\\" + activityType.Name) || IsMatched(outOfProcessActivity, activityType.Assembly.GetName().FullName + "\\" + activityType.FullName));
}
private static bool IsMatched(string allowedActivity, string match)
{
return (WildcardPattern.ContainsWildcardCharacters(allowedActivity)
? new WildcardPattern(allowedActivity, WildcardOptions.IgnoreCase).IsMatch(match)
: string.Equals(allowedActivity, match, StringComparison.OrdinalIgnoreCase));
}
#endregion Configuration Properties
}
}
@@ -1,407 +0,0 @@
/*
* Copyright (c) 2011 Microsoft Corporation. All rights reserved
*/
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Security;
using System.Management.Automation.Tracing;
using System.Threading;
using Microsoft.PowerShell.Activities;
namespace Microsoft.PowerShell.Workflow
{
internal class LocalRunspaceAsyncResult : ConnectionAsyncResult
{
internal LocalRunspaceAsyncResult(object state, AsyncCallback callback, Guid ownerId)
:base(state, callback, ownerId)
{
}
internal Runspace Runspace { get; set; }
}
internal class LocalRunspaceProvider : RunspaceProvider, IDisposable
{
private readonly TimeBasedCache<Runspace> _runspaceCache;
private readonly int _maxRunspaces;
private readonly PSLanguageMode? _languageMode;
private readonly ConcurrentQueue<LocalRunspaceAsyncResult> _requests =
new ConcurrentQueue<LocalRunspaceAsyncResult>();
private readonly ConcurrentQueue<LocalRunspaceAsyncResult> _callbacks =
new ConcurrentQueue<LocalRunspaceAsyncResult>();
private int _isServicing;
private int _isServicingCallbacks;
private const int Servicing = 1;
private const int NotServicing = 0;
private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();
/// <summary>
/// -1 indicates unlimited
/// </summary>
private const int MaxRunspacesPossible = -1;
private const int DefaultMaxRunspaces = MaxRunspacesPossible;
internal TimeBasedCache<Runspace> RunspaceCache
{
get { return _runspaceCache; }
}
internal LocalRunspaceProvider(int timeoutSeconds, PSLanguageMode? languageMode) : this(timeoutSeconds, DefaultMaxRunspaces, languageMode)
{
}
internal LocalRunspaceProvider(int timeoutSeconds, int maxRunspaces, PSLanguageMode? languageMode)
{
_runspaceCache = new TimeBasedCache<Runspace>(timeoutSeconds);
_maxRunspaces = maxRunspaces;
_languageMode = languageMode;
}
/// <summary>
///
/// </summary>
/// <param name="connectionInfo"></param>
/// <param name="retryCount"></param>
/// <param name="retryInterval"></param>
/// <returns></returns>
public override Runspace GetRunspace(WSManConnectionInfo connectionInfo, uint retryCount, uint retryInterval)
{
IAsyncResult asyncResult = BeginGetRunspace(connectionInfo, 0, 0, null, null);
return EndGetRunspace(asyncResult);
}
private Runspace AssignRunspaceIfPossible(PSLanguageMode? sourceLanguageMode = null)
{
Runspace runspace = null;
PSLanguageMode languageMode = (sourceLanguageMode != null) ? sourceLanguageMode.Value :
(_languageMode != null) ? _languageMode.Value : GetSystemLanguageMode();
lock (_runspaceCache.TimerServicingSyncObject)
{
// Retrieve or create a local runspace having the same language mode as the source, if provided.
foreach (Item<Runspace> item in _runspaceCache.Cast<Item<Runspace>>().Where(item => !item.Busy))
{
if (item.Value.SessionStateProxy.LanguageMode == languageMode)
{
item.Idle = false;
item.Busy = true;
runspace = item.Value;
break;
}
}
if ((runspace == null || runspace.RunspaceStateInfo.State != RunspaceState.Opened) &&
(_maxRunspaces == MaxRunspacesPossible || _runspaceCache.Cache.Count < _maxRunspaces))
{
runspace = CreateLocalActivityRunspace(languageMode);
runspace.Open();
_tracer.WriteMessage("New local runspace created");
_runspaceCache.Add(new Item<Runspace>(runspace, runspace.InstanceId));
}
}
return runspace;
}
private static PSLanguageMode GetSystemLanguageMode()
{
return (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce) ?
PSLanguageMode.ConstrainedLanguage : PSLanguageMode.FullLanguage;
}
private void TraceThreadPoolInfo(string message)
{
#if DEBUG
int maxWorkerThreads, maxCompletionPortThreads, availableWorkerThreads, availableCompletionPortThreads,
minWorkerThreads, minCompletionPortThreads;
ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
ThreadPool.GetAvailableThreads(out availableWorkerThreads, out availableCompletionPortThreads);
_tracer.WriteMessage(string.Format(System.Globalization.CultureInfo.InvariantCulture,
"LocalRunspaceProvider: {0} minwt:{1} mincpt:{2} wt:{3} ct:{4} awt:{5} act:{6}",
message, minWorkerThreads, minCompletionPortThreads, maxWorkerThreads,
maxCompletionPortThreads, availableWorkerThreads,
availableCompletionPortThreads));
#else
_tracer.WriteMessage(string.Format(System.Globalization.CultureInfo.InvariantCulture,
"PSW ConnMgr: {0}",
message));
#endif
}
/// <summary>
/// Checks to see if a thread is already servicing and if not starts one
/// </summary>
private void CheckAndStartRequestServicingThread()
{
if (Interlocked.CompareExchange(ref _isServicing, Servicing, NotServicing) != NotServicing) return;
TraceThreadPoolInfo("QueueUserWorkItem Request Servicing thread");
ThreadPool.QueueUserWorkItem(ServiceRequests);
}
private void ServiceRequests(object state)
{
Debug.Assert(_maxRunspaces != MaxRunspacesPossible,
"When infinite runspaces are specified, then we should never hit the servicing thread");
lock(_runspaceCache.TimerServicingSyncObject)
{
LocalRunspaceAsyncResult asyncResult;
Runspace runspace = AssignRunspaceIfPossible();
bool assigned = false;
while (runspace != null && _requests.TryDequeue(out asyncResult))
{
asyncResult.Runspace = runspace;
assigned = true;
AddToPendingCallbacks(asyncResult);
runspace = _runspaceCache.Cache.Count < _maxRunspaces ? AssignRunspaceIfPossible() : null;
}
if (!assigned && runspace != null)
ReleaseRunspace(runspace);
}
Interlocked.CompareExchange(ref _isServicing, NotServicing, Servicing);
}
private void AddToPendingCallbacks(LocalRunspaceAsyncResult asyncResult)
{
_callbacks.Enqueue(asyncResult);
if (Interlocked.CompareExchange(ref _isServicingCallbacks, Servicing, NotServicing) != NotServicing) return;
TraceThreadPoolInfo("Callback thread");
ThreadPool.QueueUserWorkItem(ServiceCallbacks);
}
private void ServiceCallbacks(object state)
{
LocalRunspaceAsyncResult result;
while (_callbacks.TryDequeue(out result))
{
result.SetAsCompleted(null);
}
Interlocked.CompareExchange(ref _isServicingCallbacks, NotServicing, Servicing);
}
/// <summary>
/// Begin for obtaining a runspace for the specified ConnectionInfo
/// </summary>
/// <param name="connectionInfo">connection info to be used for remote connections</param>
/// <param name="retryCount">number of times to retry</param>
/// <param name="callback">optional user defined callback</param>
/// <param name="state">optional user specified state</param>
/// <param name="retryInterval">time in milliseconds before the next retry has to be attempted</param>
/// <returns>async result</returns>
public override IAsyncResult BeginGetRunspace(WSManConnectionInfo connectionInfo, uint retryCount, uint retryInterval, AsyncCallback callback, object state)
{
if (connectionInfo != null)
{
throw new InvalidOperationException();
}
LocalRunspaceAsyncResult asyncResult = new LocalRunspaceAsyncResult(state, callback, Guid.Empty);
// Get the source language mode from the activity arguments if available and pass to runspace fetching.
PSLanguageMode? sourceLanguageMode = null;
RunCommandsArguments args = state as RunCommandsArguments;
if (args != null)
{
PSWorkflowRuntime wfRuntime = args.WorkflowHost as PSWorkflowRuntime;
if (wfRuntime != null)
{
PSWorkflowJob wfJob = wfRuntime.JobManager.GetJob(args.PSActivityContext.JobInstanceId);
if (wfJob != null)
{
sourceLanguageMode = wfJob.SourceLanguageMode;
}
}
}
Runspace runspace = AssignRunspaceIfPossible(sourceLanguageMode);
if (runspace != null)
{
asyncResult.Runspace = runspace;
asyncResult.CompletedSynchronously = true;
asyncResult.SetAsCompleted(null);
}
else
{
// queue the request
_requests.Enqueue(asyncResult);
CheckAndStartRequestServicingThread();
}
return asyncResult;
}
/// <summary>
/// End for obtaining a runspace for the specified connection info
/// </summary>
/// <param name="asyncResult">async result to end on</param>
/// <returns>remote runspace to invoke commands on</returns>
public override Runspace EndGetRunspace(IAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
LocalRunspaceAsyncResult result = asyncResult as LocalRunspaceAsyncResult;
if (result == null)
throw new ArgumentException(Resources.InvalidAsyncResultSpecified, "asyncResult");
// this will throw an exception when a runspace is not successfully
// available
result.EndInvoke();
Debug.Assert(result.Runspace != null, "EndInvoke() should throw an exception if runspace is null");
_tracer.WriteMessage("LocalRunspaceProvider: Request serviced and runspace returned");
Runspace runspace = result.Runspace;
Debug.Assert(runspace.RunspaceStateInfo.State == RunspaceState.Opened, "Only opened runspace should be returned");
return runspace;
}
/// <summary>
///
/// </summary>
/// <param name="runspace"></param>
public override void ReleaseRunspace(Runspace runspace)
{
runspace.ResetRunspaceState();
lock(_runspaceCache.TimerServicingSyncObject)
{
bool found = false;
foreach (Item<Runspace> item in
_runspaceCache.Cast<Item<Runspace>>().Where(item => item.InstanceId == runspace.InstanceId))
{
item.Busy = false;
found = true;
}
if (!found)
throw new InvalidOperationException();
}
if (_maxRunspaces != MaxRunspacesPossible)
CheckAndStartRequestServicingThread();
}
private readonly static object SyncObject = new object();
private static TypeTable _sharedTypeTable;
internal static TypeTable SharedTypeTable
{
get
{
if (_sharedTypeTable == null)
{
lock (SyncObject)
{
if (_sharedTypeTable == null)
{
_sharedTypeTable = TypeTable.LoadDefaultTypeFiles();
}
}
}
return _sharedTypeTable;
}
}
private static InitialSessionState GetInitialSessionStateWithSharedTypesAndNoFormat()
{
InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
// clear existing types and format
initialSessionState.Types.Clear();
initialSessionState.Formats.Clear();
// add default types and formats
initialSessionState.Types.Add(new SessionStateTypeEntry(SharedTypeTable.Clone(unshared: true)));
initialSessionState.DisableFormatUpdates = true;
return initialSessionState;
}
/// <summary>
/// Creates a local runspace with the autoloading turned on.
/// </summary>
/// <returns></returns>
internal static Runspace CreateLocalActivityRunspace(PSLanguageMode? languageMode = null, bool useCurrentThreadForExecution = true)
{
InitialSessionState iss = GetInitialSessionStateWithSharedTypesAndNoFormat();
if (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce)
{
iss.LanguageMode = PSLanguageMode.ConstrainedLanguage;
}
if (languageMode != null && languageMode.HasValue)
{
iss.LanguageMode = languageMode.Value;
}
// Add a variable indicating that we're in Workflow endpoint. This enables the
// autoloading feature.
SessionStateVariableEntry ssve = new SessionStateVariableEntry("RunningInPSWorkflowEndpoint",
true, "True if we're in a Workflow Endpoint", ScopedItemOptions.Constant);
iss.Variables.Add(ssve);
Runspace runspace = RunspaceFactory.CreateRunspace(iss);
if (useCurrentThreadForExecution)
runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
return runspace;
}
/// <summary>
/// Dispose resources
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
///
/// </summary>
/// <param name="disposing"></param>
protected void Dispose(bool disposing)
{
if (disposing)
{
_runspaceCache.Dispose();
}
}
/// <summary>
/// Helper method only to use from test
/// </summary>
internal void Reset()
{
foreach(Item<Runspace> item in _runspaceCache)
{
item.Value.Dispose();
}
_runspaceCache.Cache.Clear();
}
}
}
@@ -1,876 +0,0 @@
//
// Copyright (C) Microsoft. All rights reserved.
//
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Management.Automation;
using System.Collections;
using System.Xml;
using Microsoft.PowerShell.Workflow;
using System.Reflection;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.PowerShell.Commands
{
/// <summary>
/// This class is used to specify Workflow related options in the Register-PSSessionConfiguration
/// </summary>
public sealed class PSWorkflowExecutionOption : PSSessionTypeOption
{
private const string PrivateDataFormat = @"<PrivateData>{0}</PrivateData>";
private const string ParamToken = @"<Param Name='{0}' Value='{1}' />";
private string persistencePath = PSWorkflowConfigurationProvider.DefaultPersistencePath;
private long maxPersistenceStoreSizeGB = PSWorkflowConfigurationProvider.DefaultMaxPersistenceStoreSizeGB;
private bool persistWithEncryption = PSWorkflowConfigurationProvider.DefaultPersistWithEncryption;
private int maxRunningWorkflows = PSWorkflowConfigurationProvider.DefaultMaxRunningWorkflows;
private string[] allowedActivity = new List<string>(PSWorkflowConfigurationProvider.DefaultAllowedActivity).ToArray();
private bool enableValidation = PSWorkflowConfigurationProvider.DefaultEnableValidation;
private string[] outOfProcessActivity = new List<string>(PSWorkflowConfigurationProvider.DefaultOutOfProcessActivity).ToArray();
private int maxDisconnectedSessions = PSWorkflowConfigurationProvider.DefaultMaxDisconnectedSessions;
private int maxConnectedSessions = PSWorkflowConfigurationProvider.DefaultMaxConnectedSessions;
private int maxSessionsPerWorkflow = PSWorkflowConfigurationProvider.DefaultMaxSessionsPerWorkflow;
private int maxSessionsPerRemoteNode = PSWorkflowConfigurationProvider.DefaultMaxSessionsPerRemoteNode;
private int maxActivityProcesses = PSWorkflowConfigurationProvider.DefaultMaxActivityProcesses;
private int activityProcessIdleTimeoutSec = PSWorkflowConfigurationProvider.DefaultActivityProcessIdleTimeoutSec;
private int workflowApplicationPersistUnloadTimeoutSec = PSWorkflowConfigurationProvider.DefaultWorkflowApplicationPersistUnloadTimeoutSec;
private int wsmanPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = PSWorkflowConfigurationProvider.DefaultWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec;
private int activitiesCacheCleanupIntervalMSec = PSWorkflowConfigurationProvider.DefaultActivitiesCacheCleanupIntervalMSec;
private int remoteNodeSessionIdleTimeoutSec = PSWorkflowConfigurationProvider.DefaultRemoteNodeSessionIdleTimeoutSec;
private int sessionThrottleLimit = PSWorkflowConfigurationProvider.DefaultSessionThrottleLimit;
private int workflowShutdownTimeoutMSec = PSWorkflowConfigurationProvider.DefaultWorkflowShutdownTimeoutMSec;
/// <summary>
/// Constructor that loads from default values
/// </summary>
internal PSWorkflowExecutionOption()
{
}
private void ValidateRange(int min, int max, int value)
{
if (value >= min && value <= max)
return;
string msg = string.Format(CultureInfo.InvariantCulture, Resources.ProvidedValueIsOutOfRange, value, min, max);
throw new ArgumentException(msg);
}
/// <summary>
/// SessionThrottleLimit
/// </summary>
public int SessionThrottleLimit
{
get
{
return sessionThrottleLimit;
}
set {
ValidateRange(PSWorkflowConfigurationProvider.MinSessionThrottleLimit, PSWorkflowConfigurationProvider.MaxSessionThrottleLimit, value);
sessionThrottleLimit = value;
}
}
/// <summary>
/// PersistencePath
/// </summary>
public string PersistencePath
{
get
{
return persistencePath;
}
set
{
persistencePath = value;
}
}
/// <summary>
/// MaxPersistenceStoreSizeGB
/// </summary>
public long MaxPersistenceStoreSizeGB
{
get
{
return maxPersistenceStoreSizeGB;
}
set
{
maxPersistenceStoreSizeGB = value;
}
}
/// <summary>
/// PersistWithEncryption
/// </summary>
public bool PersistWithEncryption
{
get {
return persistWithEncryption;
}
set
{
persistWithEncryption = value;
}
}
/// <summary>
/// MaxRunningWorkflows
/// </summary>
public int MaxRunningWorkflows {
get
{
return maxRunningWorkflows;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinMaxRunningWorkflows, PSWorkflowConfigurationProvider.MaxMaxRunningWorkflows, value);
maxRunningWorkflows = value;
}
}
/// <summary>
/// AllowedActivity
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public string[] AllowedActivity
{
get
{
return allowedActivity;
}
set
{
allowedActivity = value;
}
}
/// <summary>
/// OutOfProcActivity
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public string[] OutOfProcessActivity
{
get
{
return outOfProcessActivity;
}
set
{
outOfProcessActivity = value;
}
}
/// <summary>
/// EnableValidation
/// </summary>
public bool EnableValidation
{
get
{
return enableValidation;
}
set
{
enableValidation = value;
}
}
/// <summary>
/// MaxDisconnectedSessions
/// </summary>
public int MaxDisconnectedSessions
{
get
{
return maxDisconnectedSessions;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinMaxDisconnectedSessions, PSWorkflowConfigurationProvider.MaxMaxDisconnectedSessions, value);
maxDisconnectedSessions = value;
}
}
/// <summary>
/// MaxConnectedSessions
/// </summary>
public int MaxConnectedSessions
{
get
{
return maxConnectedSessions;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinMaxConnectedSessions, PSWorkflowConfigurationProvider.MaxMaxConnectedSessions, value);
maxConnectedSessions = value;
}
}
/// <summary>
/// MaxSessionsPerWorkflow
/// </summary>
public int MaxSessionsPerWorkflow
{
get
{
return maxSessionsPerWorkflow;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinMaxSessionsPerWorkflow, PSWorkflowConfigurationProvider.MaxMaxSessionsPerWorkflow, value);
maxSessionsPerWorkflow = value;
}
}
/// <summary>
/// MaxSessionsPerRemoteNode
/// </summary>
public int MaxSessionsPerRemoteNode
{
get
{
return maxSessionsPerRemoteNode;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinMaxSessionsPerRemoteNode, PSWorkflowConfigurationProvider.MaxMaxSessionsPerRemoteNode, value);
maxSessionsPerRemoteNode = value;
}
}
/// <summary>
/// MaxActivityProcesses
/// </summary>
public int MaxActivityProcesses
{
get
{
return maxActivityProcesses;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinMaxActivityProcesses, PSWorkflowConfigurationProvider.MaxMaxActivityProcesses, value);
maxActivityProcesses = value;
}
}
/// <summary>
/// WorkflowApplicationPersistUnloadTimeoutSec
/// </summary>
internal int WorkflowApplicationPersistUnloadTimeoutSec
{
get
{
return workflowApplicationPersistUnloadTimeoutSec;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinWorkflowApplicationPersistUnloadTimeoutSec, PSWorkflowConfigurationProvider.MaxWorkflowApplicationPersistUnloadTimeoutSec, value);
workflowApplicationPersistUnloadTimeoutSec = value;
}
}
/// <summary>
/// WSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec
/// </summary>
internal int WSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec
{
get
{
return wsmanPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec, PSWorkflowConfigurationProvider.MaxWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec, value);
wsmanPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = value;
}
}
/// <summary>
/// ActivitiesCacheCleanupIntervalMSec
/// </summary>
internal int ActivitiesCacheCleanupIntervalMSec
{
get
{
return activitiesCacheCleanupIntervalMSec;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinActivitiesCacheCleanupIntervalMSec, PSWorkflowConfigurationProvider.MaxActivitiesCacheCleanupIntervalMSec, value);
activitiesCacheCleanupIntervalMSec = value;
}
}
/// <summary>
/// ActivityProcessIdleTimeOutSec
/// </summary>
public int ActivityProcessIdleTimeoutSec
{
get
{
return activityProcessIdleTimeoutSec;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinActivityProcessIdleTimeoutSec, PSWorkflowConfigurationProvider.MaxActivityProcessIdleTimeoutSec, value);
activityProcessIdleTimeoutSec = value;
}
}
/// <summary>
/// RemoteNodeSessionIdleTimeOut
/// </summary>
public int RemoteNodeSessionIdleTimeoutSec
{
get
{
return remoteNodeSessionIdleTimeoutSec;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinRemoteNodeSessionIdleTimeoutSec, PSWorkflowConfigurationProvider.MaxRemoteNodeSessionIdleTimeoutSec, value);
remoteNodeSessionIdleTimeoutSec = value;
}
}
/// <summary>
/// WorkflowShutdownTimeoutMSec - the maximum time allowed to suspend the workflows before aborting them.
/// </summary>
public int WorkflowShutdownTimeoutMSec
{
get
{
return workflowShutdownTimeoutMSec;
}
set
{
ValidateRange(PSWorkflowConfigurationProvider.MinWorkflowShutdownTimeoutMSec, PSWorkflowConfigurationProvider.MaxWorkflowShutdownTimeoutMSec, value);
workflowShutdownTimeoutMSec = value;
}
}
/// <summary>
/// Copies values from updated. Only non default values are copies.
/// </summary>
/// <param name="updated"></param>
protected override void CopyUpdatedValuesFrom(PSSessionTypeOption updated)
{
if (updated == null)
throw new ArgumentNullException("updated");
PSWorkflowExecutionOption modified = updated as PSWorkflowExecutionOption;
if (modified == null)
throw new ArgumentNullException("updated");
if (modified.activityProcessIdleTimeoutSec != PSWorkflowConfigurationProvider.DefaultActivityProcessIdleTimeoutSec)
this.activityProcessIdleTimeoutSec = modified.activityProcessIdleTimeoutSec;
if (modified.workflowApplicationPersistUnloadTimeoutSec != PSWorkflowConfigurationProvider.DefaultWorkflowApplicationPersistUnloadTimeoutSec)
this.workflowApplicationPersistUnloadTimeoutSec = modified.workflowApplicationPersistUnloadTimeoutSec;
if (modified.wsmanPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec != PSWorkflowConfigurationProvider.DefaultWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec)
this.wsmanPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec = modified.wsmanPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec;
if (modified.activitiesCacheCleanupIntervalMSec != PSWorkflowConfigurationProvider.DefaultActivitiesCacheCleanupIntervalMSec)
this.activitiesCacheCleanupIntervalMSec = modified.activitiesCacheCleanupIntervalMSec;
if (!ListsMatch(modified.allowedActivity, PSWorkflowConfigurationProvider.DefaultAllowedActivity))
this.allowedActivity = modified.allowedActivity;
if (!string.Equals(modified.persistencePath, PSWorkflowConfigurationProvider.DefaultPersistencePath, StringComparison.OrdinalIgnoreCase))
this.persistencePath = modified.persistencePath;
if (modified.maxPersistenceStoreSizeGB != PSWorkflowConfigurationProvider.DefaultMaxPersistenceStoreSizeGB)
this.maxPersistenceStoreSizeGB = modified.maxPersistenceStoreSizeGB;
if (modified.persistWithEncryption != PSWorkflowConfigurationProvider.DefaultPersistWithEncryption)
this.persistWithEncryption = modified.persistWithEncryption;
if (modified.remoteNodeSessionIdleTimeoutSec != PSWorkflowConfigurationProvider.DefaultRemoteNodeSessionIdleTimeoutSec)
this.remoteNodeSessionIdleTimeoutSec = modified.remoteNodeSessionIdleTimeoutSec;
if (modified.maxActivityProcesses != PSWorkflowConfigurationProvider.DefaultMaxActivityProcesses)
this.maxActivityProcesses = modified.maxActivityProcesses;
if (modified.maxConnectedSessions != PSWorkflowConfigurationProvider.DefaultMaxConnectedSessions)
this.maxConnectedSessions = modified.maxConnectedSessions;
if (modified.maxDisconnectedSessions != PSWorkflowConfigurationProvider.DefaultMaxDisconnectedSessions)
this.maxDisconnectedSessions = modified.maxDisconnectedSessions;
if (modified.maxRunningWorkflows != PSWorkflowConfigurationProvider.DefaultMaxRunningWorkflows)
this.maxRunningWorkflows = modified.maxRunningWorkflows;
if (modified.maxSessionsPerRemoteNode != PSWorkflowConfigurationProvider.DefaultMaxSessionsPerRemoteNode)
this.maxSessionsPerRemoteNode = modified.maxSessionsPerRemoteNode;
if (modified.maxSessionsPerWorkflow != PSWorkflowConfigurationProvider.DefaultMaxSessionsPerWorkflow)
this.maxSessionsPerWorkflow = modified.maxSessionsPerWorkflow;
if (!ListsMatch(modified.outOfProcessActivity, PSWorkflowConfigurationProvider.DefaultOutOfProcessActivity))
this.outOfProcessActivity = modified.outOfProcessActivity;
if (modified.enableValidation != PSWorkflowConfigurationProvider.DefaultEnableValidation)
this.enableValidation = modified.enableValidation;
if (modified.sessionThrottleLimit != PSWorkflowConfigurationProvider.DefaultSessionThrottleLimit)
this.sessionThrottleLimit = modified.sessionThrottleLimit;
if (modified.workflowShutdownTimeoutMSec != PSWorkflowConfigurationProvider.DefaultWorkflowShutdownTimeoutMSec)
this.workflowShutdownTimeoutMSec = modified.workflowShutdownTimeoutMSec;
}
private static bool ListsMatch(IEnumerable<string> a, IEnumerable<string> b)
{
foreach (string strA in a)
{
bool found = false;
foreach (string strB in b)
{
if (string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0)
{
found = true;
break;
}
}
if (!found)
return false;
}
foreach (string strB in b)
{
bool found = false;
foreach (string strA in a)
{
if (string.Compare(strB, strA, StringComparison.OrdinalIgnoreCase) == 0)
{
found = true;
break;
}
}
if (!found)
return false;
}
return true;
}
/// <summary>
/// Returns a new instance constructed from privateData string.
/// </summary>
/// <returns></returns>
protected override PSSessionTypeOption ConstructObjectFromPrivateData(string privateData)
{
return PSWorkflowConfigurationProvider.LoadConfig(privateData, null);
}
/// <summary>
/// Implementation of the abstract method
/// </summary>
/// <returns></returns>
protected override string ConstructPrivateData()
{
StringBuilder privateDataParams = new StringBuilder();
bool usesDefaultPath = string.Compare(persistencePath, PSWorkflowConfigurationProvider.DefaultPersistencePath, StringComparison.OrdinalIgnoreCase) != 0;
if (usesDefaultPath)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenPersistencePath, persistencePath));
if (maxPersistenceStoreSizeGB != PSWorkflowConfigurationProvider.DefaultMaxPersistenceStoreSizeGB)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenMaxPersistenceStoreSizeGB, maxPersistenceStoreSizeGB));
if (persistWithEncryption != PSWorkflowConfigurationProvider.DefaultPersistWithEncryption)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenPersistWithEncryption, persistWithEncryption));
if (maxRunningWorkflows != PSWorkflowConfigurationProvider.DefaultMaxRunningWorkflows)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenMaxRunningWorkflows, maxRunningWorkflows));
if (enableValidation != PSWorkflowConfigurationProvider.DefaultEnableValidation)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenEnableValidation, enableValidation));
StringBuilder allowedAttribute = new StringBuilder();
foreach (string a in allowedActivity ?? new string[0])
{
allowedAttribute.Append(a);
allowedAttribute.Append(',');
}
if (allowedAttribute.Length > 0)
{
allowedAttribute.Remove(allowedAttribute.Length - 1, 1);
}
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenAllowedActivity, allowedAttribute.ToString()));
StringBuilder outOfProcAttribute = new StringBuilder();
foreach (string a in outOfProcessActivity ?? new string[0])
{
outOfProcAttribute.Append(a);
outOfProcAttribute.Append(',');
}
if (outOfProcAttribute.Length > 0)
{
outOfProcAttribute.Remove(outOfProcAttribute.Length - 1, 1);
}
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenOutOfProcessActivity, outOfProcAttribute.ToString()));
if (maxDisconnectedSessions != PSWorkflowConfigurationProvider.DefaultMaxDisconnectedSessions)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenMaxDisconnectedSessions, maxDisconnectedSessions));
if (maxConnectedSessions != PSWorkflowConfigurationProvider.DefaultMaxConnectedSessions)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenMaxConnectedSessions, maxConnectedSessions));
if (maxSessionsPerWorkflow != PSWorkflowConfigurationProvider.DefaultMaxSessionsPerWorkflow)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenMaxSessionsPerWorkflow, maxSessionsPerWorkflow));
if (maxSessionsPerRemoteNode != PSWorkflowConfigurationProvider.DefaultMaxSessionsPerRemoteNode)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenMaxSessionsPerRemoteNode, maxSessionsPerRemoteNode));
if (maxActivityProcesses != PSWorkflowConfigurationProvider.DefaultMaxActivityProcesses)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenMaxActivityProcesses, maxActivityProcesses));
if (activityProcessIdleTimeoutSec != PSWorkflowConfigurationProvider.DefaultActivityProcessIdleTimeoutSec)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenActivityProcessIdleTimeoutSec, activityProcessIdleTimeoutSec));
if (workflowApplicationPersistUnloadTimeoutSec != PSWorkflowConfigurationProvider.DefaultWorkflowApplicationPersistUnloadTimeoutSec)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenWorkflowApplicationPersistUnloadTimeoutSec, workflowApplicationPersistUnloadTimeoutSec));
if (wsmanPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec != PSWorkflowConfigurationProvider.DefaultWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenWSManPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec, wsmanPluginReportCompletionOnZeroActiveSessionsWaitIntervalMSec));
if (activitiesCacheCleanupIntervalMSec != PSWorkflowConfigurationProvider.DefaultActivitiesCacheCleanupIntervalMSec)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenActivitiesCacheCleanupIntervalMSec, activitiesCacheCleanupIntervalMSec));
if (remoteNodeSessionIdleTimeoutSec != PSWorkflowConfigurationProvider.DefaultRemoteNodeSessionIdleTimeoutSec)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenRemoteNodeSessionIdleTimeoutSec, remoteNodeSessionIdleTimeoutSec));
if (sessionThrottleLimit != PSWorkflowConfigurationProvider.DefaultSessionThrottleLimit)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenSessionThrottleLimit, sessionThrottleLimit));
if (workflowShutdownTimeoutMSec != PSWorkflowConfigurationProvider.DefaultWorkflowShutdownTimeoutMSec)
privateDataParams.Append(string.Format(CultureInfo.InvariantCulture, ParamToken, PSWorkflowConfigurationProvider.TokenWorkflowShutdownTimeoutMSec, workflowShutdownTimeoutMSec));
return string.Format(CultureInfo.InvariantCulture, PrivateDataFormat, privateDataParams.ToString());
}
internal string ConstructPrivateDataInternal()
{
return ConstructPrivateData();
}
}
/// <summary>
/// Command to create an object for PSWorkflowExecutionOption
/// </summary>
[Cmdlet(VerbsCommon.New, "PSWorkflowExecutionOption",HelpUri = "https://go.microsoft.com/fwlink/?LinkID=210609")]
[OutputType(typeof(PSWorkflowExecutionOption))]
public sealed class NewPSWorkflowExecutionOptionCommand : PSCmdlet
{
private PSWorkflowExecutionOption option = new PSWorkflowExecutionOption();
private bool enableValidationParamSpecified = false;
/// <summary>
/// PersistencePath
/// </summary>
[Parameter]
public string PersistencePath
{
get
{
return option.PersistencePath;
}
set
{
if (value != null)
{
string rootedPath = value;
bool isPathTooLong = false;
if (!Path.IsPathRooted(value))
{
try
{
rootedPath = Path.GetPathRoot(value);
if (String.IsNullOrEmpty(rootedPath))
{
rootedPath = value;
}
}
catch (PathTooLongException)
{
isPathTooLong = true;
}
}
if (isPathTooLong || (rootedPath != null && rootedPath.Length > Constants.MaxAllowedPersistencePathLength))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, Resources.PersistencePathToolLong, value, Constants.MaxAllowedPersistencePathLength));
}
}
option.PersistencePath = value;
}
}
/// <summary>
/// MaxPersistenceStoreSizeGB
/// </summary>
[Parameter]
public long MaxPersistenceStoreSizeGB
{
get
{
return option.MaxPersistenceStoreSizeGB;
}
set
{
option.MaxPersistenceStoreSizeGB = value;
}
}
/// <summary>
/// UseEncryption
/// </summary>
[Parameter]
public SwitchParameter PersistWithEncryption {
get
{
return option.PersistWithEncryption;
}
set
{
option.PersistWithEncryption = value;
}
}
/// <summary>
/// MaxRunningWorkflows
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinMaxRunningWorkflows, PSWorkflowConfigurationProvider.MaxMaxRunningWorkflows)]
public int MaxRunningWorkflows {
get
{
return option.MaxRunningWorkflows;
}
set
{
option.MaxRunningWorkflows = value;
}
}
/// <summary>
/// AllowedActivity
/// </summary>
[Parameter, SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public string[] AllowedActivity
{
get
{
return option.AllowedActivity;
}
set
{
option.AllowedActivity = value;
}
}
/// <summary>
/// OutOfProcActivity
/// </summary>
[Parameter, SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public string[] OutOfProcessActivity
{
get
{
return option.OutOfProcessActivity;
}
set
{
option.OutOfProcessActivity = value;
}
}
/// <summary>
/// EnableValidation
/// </summary>
[Parameter]
public SwitchParameter EnableValidation
{
get
{
return option.EnableValidation;
}
set
{
option.EnableValidation = value;
enableValidationParamSpecified = true;
}
}
/// <summary>
/// MaxDisconnectedSessions
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinMaxDisconnectedSessions, PSWorkflowConfigurationProvider.MaxMaxDisconnectedSessions)]
public int MaxDisconnectedSessions
{
get
{
return option.MaxDisconnectedSessions;
}
set
{
option.MaxDisconnectedSessions = value;
}
}
/// <summary>
/// MaxConnectedSessions
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinMaxConnectedSessions, PSWorkflowConfigurationProvider.MaxMaxConnectedSessions)]
public int MaxConnectedSessions
{
get
{
return option.MaxConnectedSessions;
}
set
{
option.MaxConnectedSessions = value;
}
}
/// <summary>
/// MaxSessionsPerWorkflow
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinMaxSessionsPerWorkflow, PSWorkflowConfigurationProvider.MaxMaxSessionsPerWorkflow)]
public int MaxSessionsPerWorkflow
{
get
{
return option.MaxSessionsPerWorkflow;
}
set
{
option.MaxSessionsPerWorkflow = value;
}
}
/// <summary>
/// MaxSessionsPerRemoteNode
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinMaxSessionsPerRemoteNode, PSWorkflowConfigurationProvider.MaxMaxSessionsPerRemoteNode)]
public int MaxSessionsPerRemoteNode
{
get
{
return option.MaxSessionsPerRemoteNode;
}
set
{
option.MaxSessionsPerRemoteNode = value;
}
}
/// <summary>
/// MaxActivityProcess
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinMaxActivityProcesses, PSWorkflowConfigurationProvider.MaxMaxActivityProcesses)]
public int MaxActivityProcesses
{
get
{
return option.MaxActivityProcesses;
}
set
{
option.MaxActivityProcesses = value;
}
}
/// <summary>
/// ActivityProcessIdleTimeOutSec
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinActivityProcessIdleTimeoutSec, PSWorkflowConfigurationProvider.MaxActivityProcessIdleTimeoutSec)]
public int ActivityProcessIdleTimeoutSec
{
get
{
return option.ActivityProcessIdleTimeoutSec;
}
set
{
option.ActivityProcessIdleTimeoutSec = value;
}
}
/// <summary>
/// RemoteNodeSessionIdleTimeOutSec
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinRemoteNodeSessionIdleTimeoutSec, PSWorkflowConfigurationProvider.MaxRemoteNodeSessionIdleTimeoutSec)]
public int RemoteNodeSessionIdleTimeoutSec
{
get
{
return option.RemoteNodeSessionIdleTimeoutSec;
}
set
{
option.RemoteNodeSessionIdleTimeoutSec = value;
}
}
/// <summary>
/// SessionThrottleLimit
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinSessionThrottleLimit, PSWorkflowConfigurationProvider.MaxSessionThrottleLimit)]
public int SessionThrottleLimit
{
get
{
return option.SessionThrottleLimit;
}
set
{
option.SessionThrottleLimit = value;
}
}
/// <summary>
/// WorkflowShutdownTimeoutMSec - the maximum time allowed to suspend the workflows before aborting them.
/// </summary>
[Parameter, ValidateRange(PSWorkflowConfigurationProvider.MinWorkflowShutdownTimeoutMSec, PSWorkflowConfigurationProvider.MaxWorkflowShutdownTimeoutMSec)]
public int WorkflowShutdownTimeoutMSec
{
get
{
return option.WorkflowShutdownTimeoutMSec;
}
set
{
option.WorkflowShutdownTimeoutMSec = value;
}
}
/// <summary>
/// ProcessRecord
/// </summary>
protected override void ProcessRecord()
{
// By default EnableValidation should be TRUE for NewPSWorkflowExecutionOption, so that activity validation is done in user created endpoints.
//
if(!enableValidationParamSpecified)
{
option.EnableValidation = true;
}
this.WriteObject(option);
}
}
}
@@ -1,189 +0,0 @@
/*
* Copyright (c) 2010 Microsoft Corporation. All rights reserved
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Management.Automation;
using System.Threading;
using System.Diagnostics.CodeAnalysis;
using System.Activities;
using Microsoft.PowerShell.Workflow;
using System.Collections.Concurrent;
namespace Microsoft.PowerShell.Activities
{
/// <summary>
/// Class the describes an activity host arguments
/// </summary>
internal sealed class PSResumableActivityContext
{
/// <summary>
/// PSActivityHostArguments
/// </summary>
/// <param name="streams"></param>
internal PSResumableActivityContext(PowerShellStreams<PSObject, PSObject> streams)
{
Streams = streams;
Error = null;
Failed = false;
SupportDisconnectedStreams = true;
}
/// <summary>
/// Gets and sets Streams
/// </summary>
internal PowerShellStreams<PSObject, PSObject> Streams { get; set; }
/// <summary>
/// Gets Errors
/// </summary>
internal Exception Error { get; set; }
/// <summary>
/// Get failed
/// </summary>
internal bool Failed { get; set; }
internal bool SupportDisconnectedStreams { get; set; }
}
/// <summary>
/// Class the describes an activity host policy
/// </summary>
public sealed class PSActivityEnvironment
{
private readonly Collection<string> _modules = new Collection<string>();
private readonly Dictionary<string, object> _variables = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Collection of modules that an activity is
/// dependent upon
/// </summary>
public Collection<string> Modules
{
get { return _modules; }
}
/// <summary>
/// Collection of variables that an activity is
/// dependent upon
/// </summary>
public Dictionary<string, object> Variables
{
get { return _variables; }
}
}
#region PSActivityHostController
/// <summary>
/// Activity host manager interface. This interface can be
/// used to implement various activity hosts
/// </summary>
public abstract class PSActivityHostController
{
private PSWorkflowRuntime _runtime;
private readonly ConcurrentDictionary<string, bool> _inProcActivityLookup = new ConcurrentDictionary<string, bool>();
/// <summary>
/// Runtime should be provided for accessing the runtime activity mode
/// </summary>
protected PSActivityHostController(PSWorkflowRuntime runtime)
{
_runtime = runtime;
}
/// <summary>
/// Identifies whether the specified activity should run in the activity
/// host or in-proc
/// </summary>
/// <param name="activity">activity that needs to be verified</param>
/// <returns>true, if the activity should run in the activity
/// host
/// false otherwise</returns>
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly")]
public virtual bool RunInActivityController(Activity activity)
{
if (activity == null)
{
throw new ArgumentNullException("activity");
}
String name = activity.GetType().Name;
if (_inProcActivityLookup.ContainsKey(name)) return _inProcActivityLookup[name];
ActivityRunMode runMode = _runtime.Configuration.GetActivityRunMode(activity);
bool runInProc = runMode == ActivityRunMode.InProcess;
return _inProcActivityLookup.GetOrAdd(name, runInProc);
}
}
/// <summary>
/// This class will be used for disconnected execution where the
/// Job Id and bookmark will be used resume the execution of workflow
/// after the completion of activity controller work.
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public abstract class PSResumableActivityHostController : PSActivityHostController
{
/// <summary>
/// Default Constructor
/// </summary>
/// <param name="runtime"></param>
protected PSResumableActivityHostController(PSWorkflowRuntime runtime)
: base(runtime)
{
}
/// <summary>
/// StartResumablePSCommand
/// </summary>
/// <param name="jobInstanceId"></param>
/// <param name="bookmark"></param>
/// <param name="command"></param>
/// <param name="streams"></param>
/// <param name="environment"></param>
/// <param name="activityInstance"></param>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public virtual void StartResumablePSCommand(Guid jobInstanceId,
Bookmark bookmark,
System.Management.Automation.PowerShell command,
PowerShellStreams<PSObject,PSObject> streams,
PSActivityEnvironment environment,
PSActivity activityInstance)
{
throw new NotImplementedException();
}
/// <summary>
/// StopResumablePSCommand
/// </summary>
/// <param name="jobInstanceId"></param>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public virtual void StopAllResumablePSCommands(Guid jobInstanceId)
{
throw new NotImplementedException();
}
/// <summary>
/// This property identifies if the Activity controller is running in disconnected mode
/// or not. If it is running in disconnected mode then all the output and data streams will be
/// proxied as new objects.
/// </summary>
public virtual bool SupportDisconnectedPSStreams
{
get
{
return true;
}
}
}
#endregion
}
@@ -1,119 +0,0 @@
/*
* Copyright (c) 2011 Microsoft Corporation. All rights reserved
*/
using System;
using System.Activities;
using System.Threading;
using System.Management.Automation.Runspaces;
using System.ComponentModel;
namespace Microsoft.PowerShell.Activities
{
/// <summary>
/// Base activity for cleanup activities
/// </summary>
public abstract class PSCleanupActivity : PSRemotingActivity
{
/// <summary>
/// Creates and returns an empty powershell
/// </summary>
/// <param name="context">activity context</param>
/// <returns>A new activity implementation context</returns>
protected override ActivityImplementationContext GetPowerShell(NativeActivityContext context)
{
ActivityImplementationContext implementationContext = new ActivityImplementationContext
{
PowerShellInstance =
System.Management.Automation.PowerShell.
Create()
};
return implementationContext;
}
/// <summary>
/// Method that needs to be overridden to perform the actual
/// cleanup action
/// </summary>
/// <param name="args">RunCommandsArguments</param>
/// <param name="callback">callback to call when cleanup
/// is done</param>
/// <remarks>The signature forces this method to be internal</remarks>
internal virtual void DoCleanup(RunCommandsArguments args, WaitCallback callback)
{
throw new NotImplementedException();
}
}
/// <summary>
/// Activity to cleanup all Runspaces (PSRP connections) to
/// a remote machine
/// </summary>
public class DisablePSWorkflowConnection : PSCleanupActivity
{
// Arguments
/// <summary>
/// Provides access to the Authentication parameter.
/// </summary>
[RequiredArgument]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public InArgument<int> TimeoutSec
{
get;
set;
}
private int timeout = DefaultCleanupWaitTimerIntervalMs;
private const int DefaultCleanupWaitTimerIntervalMs = 5*60*1000;
/// <summary>
/// Set the display name of the activity
/// </summary>
public DisablePSWorkflowConnection()
{
DisplayName = "Disable-PSWorkflowConnection";
}
/// <summary>
/// Creates and returns an empty powershell
/// </summary>
/// <param name="context">activity context</param>
/// <returns>A new activity implementation context</returns>
protected override ActivityImplementationContext GetPowerShell(NativeActivityContext context)
{
if (TimeoutSec.Expression != null)
{
timeout = TimeoutSec.Get(context);
}
return base.GetPowerShell(context);
}
/// <summary>
/// Method that needs to be overridden to perform the actual
/// cleanup action
/// </summary>
/// <param name="args">RunCommandsArguments</param>
/// <param name="callback">callback to call when cleanup
/// is done</param>
/// <remarks>The signature forces this method to be internal</remarks>
internal override void DoCleanup(RunCommandsArguments args, WaitCallback callback)
{
PSWorkflowHost workflowHost = args.WorkflowHost;
WSManConnectionInfo connectionInfo =
args.ImplementationContext.PowerShellInstance.Runspace.ConnectionInfo as WSManConnectionInfo;
args.CleanupTimeout = timeout;
if (connectionInfo == null)
{
if (callback != null)
callback(args);
}
else
{
workflowHost.RemoteRunspaceProvider.RequestCleanup(connectionInfo, callback, args);
}
}
}
}
@@ -1,257 +0,0 @@
using System;
using System.Activities;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Remoting;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.Threading.Tasks;
using System.ComponentModel;
using Microsoft.PowerShell.Workflow;
namespace Microsoft.PowerShell.Activities
{
/// <summary>
/// Base class for PowerShell-based workflow activities
/// </summary>
public abstract class PSRemotingActivity : PSActivity, IImplementsConnectionRetry
{
/// <summary>
/// The computer name to invoke this activity on.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<string[]> PSComputerName
{
get;
set;
}
/// <summary>
/// Defines the credential to use in the remote connection.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<PSCredential> PSCredential
{
get;
set;
}
/// <summary>
/// Defines the remoting behavior to use when invoking this activity.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<RemotingBehavior> PSRemotingBehavior { get; set; }
/// <summary>
/// Defines the number of retries that the activity will make to connect to a remote
/// machine when it encounters an error. The default is to not retry.
/// </summary>
[BehaviorCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<uint?> PSConnectionRetryCount { get; set; }
/// <summary>
/// Defines the delay, in seconds, between connection retry attempts.
/// The default is one second.
/// </summary>
[BehaviorCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<uint?> PSConnectionRetryIntervalSec { get; set; }
/// <summary>
/// The port to use in a remote connection attempt. The default is:
/// HTTP: 5985, HTTPS: 5986.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<uint?> PSPort { get; set; }
/// <summary>
/// Determines whether to use SSL in the connection attempt. The default is false.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<bool?> PSUseSsl { get; set; }
/// <summary>
/// Determines whether to allow redirection by the remote computer. The default is false.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<bool?> PSAllowRedirection { get; set; }
/// <summary>
/// Defines the remote application name to connect to. The default is "wsman".
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<string> PSApplicationName { get; set; }
/// <summary>
/// Defines the remote configuration name to connect to. The default is "Microsoft.PowerShell".
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<string> PSConfigurationName { get; set; }
/// <summary>
/// Defines the fully-qualified remote URI to connect to. When specified, the PSComputerName,
/// PSApplicationName, PSConfigurationName, and PSPort are not used.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<string[]> PSConnectionUri { get; set; }
/// <summary>
/// Defines the authentication type to be used in the remote connection.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<AuthenticationMechanism?> PSAuthentication { get; set; }
/// <summary>
/// Defines the certificate thumbprint to be used in the remote connection.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<string> PSCertificateThumbprint { get; set; }
/// <summary>
/// Defines any session options to be used in the remote connection.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<PSSessionOption> PSSessionOption { get; set; }
/// <summary>
/// Declares whether this command supports its own custom remoting.
/// Commands that support their own custom remoting should return TRUE
/// from this property, and use the PSComputerName parameter as required
/// when the 'PSRemotingBehavior' argument is set to 'Custom'.
/// </summary>
protected virtual bool SupportsCustomRemoting { get { return false; } }
/// <summary>
/// Returns TRUE if the PSComputerName argument has been specified, and
/// contains at least one target.
/// </summary>
/// <param name="context">The workflow NativeActivityContext</param>
/// <returns></returns>
protected bool GetIsComputerNameSpecified(ActivityContext context)
{
return ((PSComputerName.Get(context) != null) &&
(PSComputerName.Get(context).Length > 0));
}
// Prepare the commands
/// <summary>
/// Prepare commands that use PSRP for remoting...
/// </summary>
/// <param name="context">The activity context to use</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
protected override List<ActivityImplementationContext> GetImplementation(NativeActivityContext context)
{
string[] computernames = PSComputerName.Get(context);
string[] connectionUris = PSConnectionUri.Get(context);
PSSessionOption sessionOptions = PSSessionOption.Get(context);
List<ActivityImplementationContext> commands = new List<ActivityImplementationContext>();
// Configure the remote connectivity options
RemotingBehavior remotingBehavior = PSRemotingBehavior.Get(context);
if (PSRemotingBehavior.Expression == null)
{
remotingBehavior = RemotingBehavior.PowerShell;
}
// If they've specified the 'Custom' remoting behavior, ensure the activity
// supports it.
if ((remotingBehavior == RemotingBehavior.Custom) && (!SupportsCustomRemoting))
{
throw new ArgumentException(Resources.CustomRemotingNotSupported);
}
if (PSCredential.Get(context) != null && PSAuthentication.Get(context) == AuthenticationMechanism.NegotiateWithImplicitCredential)
{
throw new ArgumentException(Resources.CredentialParameterCannotBeSpecifiedWithNegotiateWithImplicitAuthentication);
}
// we need connection info to be populated even for the custom remoting case.
// This is because the ComputerName is picked up from the connection info field
if ((remotingBehavior == RemotingBehavior.PowerShell || (IsActivityInlineScript(this) && RunWithCustomRemoting(context))) &&
(GetIsComputerNameSpecified(context) || (connectionUris != null && connectionUris.Length > 0)))
{
List<WSManConnectionInfo> connectionInfo = ActivityUtils.GetConnectionInfo(
computernames,
connectionUris, PSCertificateThumbprint.Get(context), PSConfigurationName.Get(context),
PSUseSsl.Get(context), PSPort.Get(context), PSApplicationName.Get(context),
PSCredential.Get(context), PSAuthentication.Get(context).GetValueOrDefault(AuthenticationMechanism.Default),
PSAllowRedirection.Get(context).GetValueOrDefault(false),
sessionOptions);
foreach (WSManConnectionInfo connection in connectionInfo)
{
CreatePowerShellInstance(context, connection, commands);
}
}
// Configure the local invocation options
else
{
CreatePowerShellInstance(context, null, commands);
}
return commands;
}
/// <summary>
/// Creates Powershell instance and adds the command to it
/// </summary>
/// <param name="context">The activity context to use</param>
/// <param name="connection">The wsman connection to use</param>
/// <param name="commands">The list of commands</param>
private void CreatePowerShellInstance(NativeActivityContext context, WSManConnectionInfo connection,
List<ActivityImplementationContext> commands)
{
// Create the PowerShell instance, and add the command to it.
ActivityImplementationContext implementationContext = GetPowerShell(context);
#if true
Runspace runspace;
if (connection != null)
{
implementationContext.ConnectionInfo = connection;
runspace = RunspaceFactory.CreateRunspace(connection);
implementationContext.PowerShellInstance.Runspace = runspace;
}
else
{
// if PSComputerName is "" or $null than connection is NULL
UpdateImplementationContextForLocalExecution(implementationContext, context);
}
#endif
// Add it to the queue of commands to execute.
commands.Add(implementationContext);
}
}
}
@@ -1,854 +0,0 @@
using System;
using System.Activities;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Remoting;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.ComponentModel;
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;
using Microsoft.PowerShell.Workflow;
namespace Microsoft.PowerShell.Activities
{
/// <summary>
/// Base class for activities that can use WsMan directly to contact ta managed node.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "CIM")]
public abstract class PSGeneratedCIMActivity : PSActivity, IImplementsConnectionRetry
{
/// <summary>
/// The computer name to invoke this activity on.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<string[]> PSComputerName
{
get;
set;
}
/// <summary>
/// Defines the credential to use in the remote connection.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<PSCredential> PSCredential
{
get;
set;
}
/// <summary>
/// Defines the authentication type to be used in the remote connection.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<AuthenticationMechanism?> PSAuthentication { get; set; }
/// <summary>
/// Defines the certificate thumbprint to be used in the remote connection.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<string> PSCertificateThumbprint { get; set; }
/// <summary>
/// Defines the number of retries that the activity will make to connect to a remote
/// machine when it encounters an error. The default is to not retry.
/// </summary>
[BehaviorCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<uint?> PSConnectionRetryCount { get; set; }
/// <summary>
/// Defines the delay, in seconds, between connection retry attempts.
/// The default is one second.
/// </summary>
[BehaviorCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<uint?> PSConnectionRetryIntervalSec { get; set; }
/// <summary>
/// Defines the resource URI used by the CIM cmdlet.
/// </summary>
[BehaviorCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<Uri> ResourceUri { get; set; }
/// <summary>
/// The port to use in a remote connection attempt. The default is:
/// HTTP: 5985, HTTPS: 5986.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<uint?> PSPort { get; set; }
/// <summary>
/// Determines whether to use SSL in the connection attempt. The default is false.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is forced by the interaction of PowerShell and Workflow.")]
public InArgument<bool?> PSUseSsl { get; set; }
/// <summary>
/// Defines any session options to be used in the remote connection.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<PSSessionOption> PSSessionOption { get; set; }
/// <summary>
/// CIM Sessions to use for this activity.
/// </summary>
[ConnectivityCategory]
[DefaultValue(null)]
public InArgument<CimSession[]> CimSession { get; set; }
/// <summary>
/// Contains the powershell text defining the mode for this command.
/// </summary>
protected abstract string ModuleDefinition { get; }
/// <summary>
/// Returns TRUE if the PSComputerName argument has been specified, and
/// contains at least one target.
/// </summary>
/// <param name="context">The workflow NativeActivityContext</param>
/// <returns></returns>
protected bool GetIsComputerNameSpecified(ActivityContext context)
{
return ((PSComputerName.Get(context) != null) &&
(PSComputerName.Get(context).Length > 0));
}
/// <summary>
/// Prepare commands that use CIM for remoting...
/// </summary>
/// <param name="context">The activity context to use</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
protected override List<ActivityImplementationContext> GetImplementation(NativeActivityContext context)
{
bool needRunspace = !typeof(GenericCimCmdletActivity).IsAssignableFrom(this.GetType());
string[] computernames = PSComputerName.Get(context);
CimSession[] sessions = this.CimSession.Get(context);
Uri resourceUri = null;
if (ResourceUri != null)
{
resourceUri = ResourceUri.Get(context);
}
List<ActivityImplementationContext> commands = new List<ActivityImplementationContext>();
// Configure the remote connectivity options...
if (computernames != null && computernames.Length > 0)
{
WSManSessionOptions sessionOptions = new WSManSessionOptions();
// Set a timeout on the connection...
uint? timeout = PSActionRunningTimeoutSec.Get(context);
if (timeout.HasValue)
{
sessionOptions.Timeout = TimeSpan.FromSeconds((double)(timeout.Value));
}
// See if we should use SSL or not...
bool? useSsl = PSUseSsl.Get(context);
bool sessionOptionUseSsl = false;
if (useSsl.HasValue)
{
sessionOptions.UseSsl = useSsl.Value;
sessionOptionUseSsl = useSsl.Value;
}
// Set the port to use
uint? port = PSPort.Get(context);
uint sessionOptionPort = 0;
if (port.HasValue)
{
sessionOptions.DestinationPort = port.Value;
sessionOptionPort = port.Value;
}
// Map over options from PSSessionConfig to WSManSessionOptions
PSSessionOption pso = PSSessionOption.Get(context);
if (pso != null)
{
sessionOptions.NoEncryption = pso.NoEncryption;
sessionOptions.CertCACheck = pso.SkipCACheck;
sessionOptions.CertCNCheck = pso.SkipCNCheck;
sessionOptions.CertRevocationCheck = pso.SkipRevocationCheck;
if (pso.UseUTF16)
sessionOptions.PacketEncoding = PacketEncoding.Utf16;
if (pso.Culture != null)
sessionOptions.Culture = pso.Culture;
if (pso.UICulture != null)
sessionOptions.UICulture = pso.UICulture;
if (pso.ProxyCredential != null)
{
string[] parts = pso.ProxyCredential.UserName.Split('\\');
string domain, userid;
if (parts.Length < 2)
{
domain = string.Empty;
userid = parts[0];
}
else
{
domain = parts[0];
userid = parts[1];
}
sessionOptions.AddProxyCredentials(
new CimCredential(ConvertPSAuthenticationMechanismToCimPasswordAuthenticationMechanism(pso.ProxyAuthentication),
domain, userid, pso.ProxyCredential.Password));
}
switch (pso.ProxyAccessType)
{
case ProxyAccessType.WinHttpConfig:
sessionOptions.ProxyType = ProxyType.WinHttp;
break;
case ProxyAccessType.AutoDetect:
sessionOptions.ProxyType = ProxyType.Auto;
break;
case ProxyAccessType.IEConfig:
sessionOptions.ProxyType = ProxyType.InternetExplorer;
break;
}
}
PSCredential pscreds = PSCredential.Get(context);
string certificateThumbprint = PSCertificateThumbprint.Get(context);
if (pscreds != null && certificateThumbprint != null)
{
throw new ArgumentException(Resources.CredentialParameterCannotBeSpecifiedWithPSCertificateThumbPrint);
}
PasswordAuthenticationMechanism passwordAuthenticationMechanism = PasswordAuthenticationMechanism.Default;
AuthenticationMechanism? authenticationMechanism = PSAuthentication.Get(context);
if (authenticationMechanism.HasValue)
passwordAuthenticationMechanism = ConvertPSAuthenticationMechanismToCimPasswordAuthenticationMechanism(authenticationMechanism.Value);
if (certificateThumbprint != null)
{
sessionOptions.AddDestinationCredentials(new CimCredential(CertificateAuthenticationMechanism.Default, certificateThumbprint));
}
if (pscreds != null)
{
string[] parts = pscreds.UserName.Split('\\');
string domain, userid;
if (parts.Length < 2)
{
domain = string.Empty;
userid = parts[0];
}
else
{
domain = parts[0];
userid = parts[1];
}
sessionOptions.AddDestinationCredentials(new CimCredential(passwordAuthenticationMechanism, domain, userid, pscreds.Password));
}
// Create the PowerShell instance, and add the script to it.
if (sessions != null && sessions.Length > 0)
{
foreach (CimSession session in sessions)
{
ActivityImplementationContext configuredCommand = GetPowerShell(context);
CimActivityImplementationContext activityImplementationContext =
new CimActivityImplementationContext(
configuredCommand,
session.ComputerName,
pscreds,
certificateThumbprint,
authenticationMechanism,
sessionOptionUseSsl,
sessionOptionPort,
pso,
session,
sessionOptions,
ModuleDefinition,
resourceUri);
commands.Add(activityImplementationContext);
//if (needRunspace)
// GetRunspaceForCimCmdlet(context, activityImplementationContext);
}
}
else if (this.PSCommandName.Equals("CimCmdlets\\New-CimSession", StringComparison.OrdinalIgnoreCase))
{
// NewCimSession activity is a special one as it creates the required sessions based on number of computers specified in one go.
ActivityImplementationContext baseContext = GetPowerShell(context);
CimActivityImplementationContext activityImplementationContext =
new CimActivityImplementationContext(baseContext,
null, // ComputerName
pscreds,
certificateThumbprint,
authenticationMechanism,
sessionOptionUseSsl,
sessionOptionPort,
pso,
null, // session
sessionOptions,
ModuleDefinition,
resourceUri);
commands.Add(activityImplementationContext);
}
else
{
foreach (string computer in computernames)
{
ActivityImplementationContext baseContext = GetPowerShell(context);
CimActivityImplementationContext activityImplementationContext =
new CimActivityImplementationContext(baseContext,
computer,
pscreds,
certificateThumbprint,
authenticationMechanism,
sessionOptionUseSsl,
sessionOptionPort,
pso,
null, // session
sessionOptions,
ModuleDefinition,
resourceUri);
commands.Add(activityImplementationContext);
}
}
}
// Configure the local invocation options
else
{
// Create the PowerShell instance, and add the script to it.
ActivityImplementationContext baseContext = GetPowerShell(context);
CimActivityImplementationContext activityImplementationContext =
new CimActivityImplementationContext(baseContext,
null, // ComputerName
null, // Credential
null, // CertificateThumbprint
AuthenticationMechanism.Default,
false, // UseSsl
0, // Port
null, // PSSessionOption
null, // Session
null, // CimSessionOptions
ModuleDefinition,
resourceUri);
commands.Add(activityImplementationContext);
}
return commands;
}
internal static PasswordAuthenticationMechanism ConvertPSAuthenticationMechanismToCimPasswordAuthenticationMechanism(AuthenticationMechanism psAuthenticationMechanism)
{
switch (psAuthenticationMechanism)
{
case AuthenticationMechanism.Basic:
return PasswordAuthenticationMechanism.Basic;
case AuthenticationMechanism.Negotiate:
case AuthenticationMechanism.NegotiateWithImplicitCredential:
return PasswordAuthenticationMechanism.Negotiate;
case AuthenticationMechanism.Credssp:
return PasswordAuthenticationMechanism.CredSsp;
case AuthenticationMechanism.Digest:
return PasswordAuthenticationMechanism.Digest;
case AuthenticationMechanism.Kerberos:
return PasswordAuthenticationMechanism.Kerberos;
case AuthenticationMechanism.Default:
default:
return PasswordAuthenticationMechanism.Default;
}
}
}
/// <summary>
/// Base class for the built-in generic CIM cmdlets.
/// </summary>
public abstract class GenericCimCmdletActivity : PSGeneratedCIMActivity
{
/// <summary>
/// For these cmdlets, there is no defining text.
/// </summary>
protected override string ModuleDefinition { get { return string.Empty; } }
/// <summary>
/// The .NET type that implements the associated cmdlet
/// </summary>
public abstract Type TypeImplementingCmdlet { get; }
}
/// <summary>
/// Provides additional functionality for CIM activity implementations.
/// </summary>
public class CimActivityImplementationContext : ActivityImplementationContext
{
/// <summary>
/// Create an instance of the CIM activity implementation class
/// </summary>
/// <param name="activityImplementationContext"></param>
/// <param name="computerName"></param>
/// <param name="credential"></param>
/// <param name="certificateThumbprint"></param>
/// <param name="authenticationMechanism"></param>
/// <param name="useSsl"></param>
/// <param name="port"></param>
/// <param name="sessionOption"></param>
/// <param name="session"></param>
/// <param name="cimSessionOptions"></param>
/// <param name="moduleDefinition"></param>
/// <param name="resourceUri"></param>
public CimActivityImplementationContext(
ActivityImplementationContext activityImplementationContext,
string computerName,
PSCredential credential,
string certificateThumbprint,
AuthenticationMechanism? authenticationMechanism,
bool useSsl,
uint port,
PSSessionOption sessionOption,
CimSession session,
CimSessionOptions cimSessionOptions,
string moduleDefinition,
Uri resourceUri)
{
if (activityImplementationContext == null)
{
throw new ArgumentNullException("activityImplementationContext");
}
this.PowerShellInstance = activityImplementationContext.PowerShellInstance;
ResourceUri = resourceUri;
ComputerName = computerName;
PSCredential = credential;
PSCertificateThumbprint = certificateThumbprint;
PSAuthentication = authenticationMechanism;
PSUseSsl = useSsl;
PSPort = port;
PSSessionOption = sessionOption;
Session = session;
SessionOptions = cimSessionOptions;
if (moduleDefinition != null)
{
// Creating a script block forces the string into the compiled script cache so we
// don't need to reparse it at execution time. Locking the static _moduleDefinition is not
// required since the operation is idempotent.
_moduleScriptBlock = ScriptBlock.Create(moduleDefinition);
_moduleDefinition = moduleDefinition;
}
}
/// <summary>
/// Gets the scriptblock that implements this activity's command
/// </summary>
public ScriptBlock ModuleScriptBlock
{
get { return _moduleScriptBlock; }
}
private static ScriptBlock _moduleScriptBlock;
/// <summary>
/// Defines the resource URI used by the CIM cmdlet.
/// </summary>
public Uri ResourceUri { get; set; }
/// <summary>
/// The session specified for this activity
/// </summary>
public CimSession Session { get; set; }
/// <summary>
/// The session options used to create the session for this activity...
/// </summary>
public CimSessionOptions SessionOptions { get; set; }
/// <summary>
/// The name of the computer this activity targets
/// </summary>
public string ComputerName { get; set; }
/// <summary>
/// Base64 encoded string defining this module...
/// </summary>
public string ModuleDefinition { get { return _moduleDefinition; } }
string _moduleDefinition;
/// <summary>
/// Return the session to the session manager
/// </summary>
public override void CleanUp()
{
if (Session != null && !string.IsNullOrEmpty(ComputerName))
{
CimConnectionManager.GetGlobalCimConnectionManager().ReleaseSession(ComputerName, Session);
Session = null;
ComputerName = null;
}
}
}
/// <summary>
/// Class to manage reuse of CIM connections.
/// </summary>
internal class CimConnectionManager
{
private readonly System.Timers.Timer _cleanupTimer = new System.Timers.Timer();
private bool firstTime = true;
internal CimConnectionManager()
{
_cleanupTimer.Elapsed += HandleCleanupTimerElapsed;
_cleanupTimer.AutoReset = true;
_cleanupTimer.Interval = 20*1000;
_cleanupTimer.Start();
}
private void HandleCleanupTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (firstTime)
{
// this is to enable a start delay of 20 seconds
firstTime = false;
return;
}
lock (SyncRoot)
{
List<string> computersToRemove = new List<string>();
foreach (var pair in availableSessions)
{
List<SessionEntry> sel = pair.Value;
if (sel.Count == 0)
{
computersToRemove.Add(pair.Key);
}
else
{
for (int i = sel.Count - 1; i >= 0; i--)
{
// If this connection in use, then skip it
if (sel[i].GetReferenceCount > 0)
continue;
if (--sel[i].IterationsRemaining <= 0)
{
sel[i].Session.Close();
sel.RemoveAt(i);
}
}
}
}
}
}
// Number of scan cycles left until this session entry will be removed.
internal const int MaxIterations = 6;
internal const int MaxCimSessionsUpperLimit = 500;
internal const int MaxCimSessionsLowerLimit = 1;
Dictionary<string, List<SessionEntry>> availableSessions = new Dictionary<string, List<SessionEntry>>();
private class SessionEntry
{
public int IterationsRemaining = MaxIterations;
public CimSessionOptions SessionOptions;
public CimSession Session;
public void AddReference()
{
Interlocked.Add(ref _numberOfUses, 1);
}
public void RemoveReference()
{
Interlocked.Decrement(ref _numberOfUses);
}
int _numberOfUses;
public int GetReferenceCount
{
get { return _numberOfUses; }
}
public PSCredential Credential
{
get { return _credential; }
}
private PSCredential _credential;
public bool UseSsl
{
get
{
return _useSsl;
}
}
private bool _useSsl;
public uint Port
{
get
{
return _port;
}
}
private uint _port;
public PSSessionOption PSSessionOption
{
get
{
return _psSessionOption;
}
}
private PSSessionOption _psSessionOption;
public string CertificateThumbprint
{
get
{
return _certificateThumbprint;
}
}
private string _certificateThumbprint;
public AuthenticationMechanism AuthenticationMechanism
{
get
{
return _authenticationMechanism;
}
}
private AuthenticationMechanism _authenticationMechanism;
public SessionEntry(string computerName, PSCredential credential, string certificateThumbprint, AuthenticationMechanism authenticationMechanism, CimSessionOptions sessionOptions, bool useSsl, uint port, PSSessionOption pssessionOption)
{
SessionOptions = sessionOptions;
_credential = credential;
_certificateThumbprint = certificateThumbprint;
_authenticationMechanism = authenticationMechanism;
_useSsl = useSsl;
_port = port;
_psSessionOption = pssessionOption;
Session = CimSession.Create(computerName, sessionOptions);
}
}
object SyncRoot = new object();
/// <summary>
/// Get a CIM session for the target computer
/// </summary>
/// <param name="computerName"></param>
/// <param name="credential"></param>
/// <param name="certificateThumbprint"></param>
/// <param name="authenticationMechanism"></param>
/// <param name="sessionOptions"></param>
/// <param name="useSsl"></param>
/// <param name="port"></param>
/// <param name="pssessionOption"></param>
/// <returns></returns>
internal CimSession GetSession(string computerName, PSCredential credential, string certificateThumbprint, AuthenticationMechanism authenticationMechanism, CimSessionOptions sessionOptions, bool useSsl, uint port, PSSessionOption pssessionOption)
{
System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(computerName), "ComputerName is null in GetSession. GetSession should not be called in this case.");
lock (SyncRoot)
{
SessionEntry newSessionEntry;
if (availableSessions.ContainsKey(computerName))
{
List<SessionEntry> sel = availableSessions[computerName];
if (sel.Count > 0)
{
for (int i = 0; i < sel.Count; i++)
{
SessionEntry se = sel[i];
// No session options specified or the object matches exactly...
if ((se.SessionOptions == null && sessionOptions == null) || CompareSessionOptions(se, sessionOptions, credential, certificateThumbprint, authenticationMechanism, useSsl, port, pssessionOption))
{
// Up the number of references to this session object...
se.AddReference();
return se.Session;
}
}
}
}
// Allocate a new session entry for this computer
newSessionEntry = new SessionEntry(computerName, credential, certificateThumbprint, authenticationMechanism, sessionOptions, useSsl, port, pssessionOption);
newSessionEntry.IterationsRemaining = MaxIterations;
newSessionEntry.AddReference();
if (! availableSessions.ContainsKey(computerName))
{
availableSessions.Add(computerName, new List<SessionEntry>());
}
availableSessions[computerName].Add(newSessionEntry);
// Return the session object
return newSessionEntry.Session;
}
}
/// <summary>
/// Return a session to the session table.
/// </summary>
/// <param name="computerName"></param>
/// <param name="session"></param>
internal void ReleaseSession(string computerName, CimSession session)
{
System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(computerName), "ComputerName is null in ReleaseSession. ReleaseSession should not be called in this case.");
lock (SyncRoot)
{
if (availableSessions.ContainsKey(computerName))
{
foreach (var se in availableSessions[computerName])
{
if (se.Session == session)
{
se.RemoveReference();
}
}
}
}
}
private static bool CompareSessionOptions(SessionEntry sessionEntry, CimSessionOptions options2, PSCredential credential2, string certificateThumbprint, AuthenticationMechanism authenticationMechanism, bool useSsl, uint port, PSSessionOption pssessionOption)
{
if (!sessionEntry.SessionOptions.Timeout.Equals(options2.Timeout))
return false;
if (!string.Equals(sessionEntry.SessionOptions.Culture.ToString(), options2.Culture.ToString(), StringComparison.OrdinalIgnoreCase))
return false;
if (!string.Equals(sessionEntry.SessionOptions.UICulture.ToString(), options2.UICulture.ToString(), StringComparison.OrdinalIgnoreCase))
return false;
if (!string.Equals(sessionEntry.CertificateThumbprint, certificateThumbprint, StringComparison.OrdinalIgnoreCase))
return false;
if (sessionEntry.AuthenticationMechanism != authenticationMechanism)
return false;
if (!Workflow.WorkflowUtils.CompareCredential(sessionEntry.Credential, credential2))
return false;
if (sessionEntry.UseSsl != useSsl)
return false;
if (sessionEntry.Port != port)
return false;
// check PSSessionOption if present
if (pssessionOption == null ^ sessionEntry.PSSessionOption == null)
{
return false;
}
if (pssessionOption != null && sessionEntry.PSSessionOption != null)
{
if (sessionEntry.PSSessionOption.ProxyAccessType != pssessionOption.ProxyAccessType)
return false;
if (sessionEntry.PSSessionOption.ProxyAuthentication != pssessionOption.ProxyAuthentication)
return false;
if (!Workflow.WorkflowUtils.CompareCredential(sessionEntry.PSSessionOption.ProxyCredential, pssessionOption.ProxyCredential))
return false;
if (sessionEntry.PSSessionOption.SkipCACheck != pssessionOption.SkipCACheck)
return false;
if (sessionEntry.PSSessionOption.SkipCNCheck != pssessionOption.SkipCNCheck)
return false;
if (sessionEntry.PSSessionOption.SkipRevocationCheck != pssessionOption.SkipRevocationCheck)
return false;
if (sessionEntry.PSSessionOption.NoEncryption != pssessionOption.NoEncryption)
return false;
if (sessionEntry.PSSessionOption.UseUTF16 != pssessionOption.UseUTF16)
return false;
}
return true;
}
/// <summary>
/// Gets the global instance of the CIM session manager
/// </summary>
/// <returns></returns>
public static CimConnectionManager GetGlobalCimConnectionManager()
{
lock (gcmLock)
{
if (_globalConnectionManagerInstance == null)
{
_globalConnectionManagerInstance = new CimConnectionManager();
}
return _globalConnectionManagerInstance;
}
}
static CimConnectionManager _globalConnectionManagerInstance;
static object gcmLock = new object();
}
}
@@ -1,243 +0,0 @@
/*
* Copyright (c) 2010 Microsoft Corporation. All rights reserved
*/
using System;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Microsoft.PowerShell.Workflow;
namespace Microsoft.PowerShell.Activities
{
#region PSWorkflowHost
/// <summary>
/// Interface that defines the PowerShell workflow host
/// Workflow host defines the set of services that are
/// made available to an activity
/// </summary>
public abstract class PSWorkflowHost
{
/// <summary>
/// The activity host manager to use for processing
/// activities
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PSActivityHostController PSActivityHostController
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
/// The provider to be used for obtaining runspaces
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual RunspaceProvider RemoteRunspaceProvider
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
/// The provider used to obtain local in-proc
/// runspaces
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual RunspaceProvider LocalRunspaceProvider
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// The provider which will supply an unbounded number of
/// runspaces - to be used in PowerShell value
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual RunspaceProvider UnboundedLocalRunspaceProvider
{
get { throw new NotImplementedException(); }
}
}
#endregion PSWorkflowHost
#region RunspaceProvider
/// <summary>
/// Class that provides a runspace with the specified options
/// and constraints
/// </summary>
public abstract class RunspaceProvider
{
/// <summary>
/// Begin for obtaining a runspace for the specified ConnectionInfo
/// </summary>
/// <param name="connectionInfo">connection info to be used for remote connections</param>
/// <param name="retryCount">number of times to retry</param>
/// <param name="callback">optional user defined callback</param>
/// <param name="state">optional user specified state</param>
/// <param name="retryInterval">time in milliseconds before the next retry has to be attempted</param>
/// <exception cref="NotImplementedException"></exception>
/// <returns>async result</returns>
public virtual IAsyncResult BeginGetRunspace(WSManConnectionInfo connectionInfo, uint retryCount, uint retryInterval, AsyncCallback callback, object state)
{
throw new NotImplementedException();
}
/// <summary>
/// End for obtaining a runspace for the specified connection info
/// </summary>
/// <param name="asyncResult">async result to end on</param>
/// <exception cref="NotImplementedException"></exception>
/// <returns>remote runspace to invoke commands on</returns>
public virtual Runspace EndGetRunspace(IAsyncResult asyncResult)
{
throw new NotImplementedException();
}
/// <summary>
/// Get runspace for the specified connection info to be
/// used for running commands
/// </summary>
/// <param name="connectionInfo">connection info to use</param>
/// <param name="retryCount">retry count </param>
/// <param name="retryInterval">retry interval in ms</param>
/// <returns>remote runspace to use</returns>
public virtual Runspace GetRunspace(WSManConnectionInfo connectionInfo, uint retryCount, uint retryInterval)
{
throw new NotImplementedException();
}
/// <summary>
/// Release the runspace once the activity is finished using the same
/// </summary>
/// <param name="runspace">runspace to release</param>
public virtual void ReleaseRunspace(Runspace runspace)
{
throw new NotImplementedException();
}
/// <summary>
/// Callback to indicate that this runspace been initiated with
/// a pipeline and can be disconnected
/// </summary>
/// <param name="runspace">runspace that needs to be marked as
/// ready for disconnect</param>
public virtual void ReadyForDisconnect(Runspace runspace)
{
throw new NotImplementedException();
}
/// <summary>
/// Request a cleanup to the destination specified in the
/// connection info. This means no runspaces will be held
/// to the specified connection info.
/// </summary>
/// <param name="connectionInfo">connection info to which
/// cleanup is desired</param>
///<param name="callback">callback to invoke</param>
/// <param name="state">caller specified state</param>
public virtual void RequestCleanup(WSManConnectionInfo connectionInfo, WaitCallback callback, object state)
{
throw new NotImplementedException();
}
/// <summary>
/// Checks to see if the provider intentionally disconnected a runspace
/// or it went into disconnected state due to network issues
/// </summary>
/// <param name="runspace">runspace that needs to be checked</param>
/// <returns>true - when intentionally disconnected
/// false - disconnected due to network issues</returns>
public virtual bool IsDisconnectedByRunspaceProvider(Runspace runspace)
{
throw new NotImplementedException();
}
}
#endregion RunspaceProvider
#region DefaultWorkflowHost
/// <summary>
/// Default workflow host implementation
/// </summary>
internal class DefaultWorkflowHost : PSWorkflowHost
{
private readonly PSActivityHostController _activityHostController;
private readonly RunspaceProvider _runspaceProvider;
private static readonly DefaultWorkflowHost _instance = new DefaultWorkflowHost();
private readonly RunspaceProvider _localRunspaceProvider;
private DefaultWorkflowHost()
{
const string applicationPrivateData = @"
<PrivateData>
<Param Name='AllowedActivity' Value='PSDefaultActivities' />
</PrivateData>
";
var runtime = PSWorkflowRuntime.Instance;
runtime.Configuration.Populate(applicationPrivateData, "Microsoft.PowerShell.Workflow");
_activityHostController = runtime.PSActivityHostController;
_runspaceProvider = runtime.RemoteRunspaceProvider;
_localRunspaceProvider = runtime.LocalRunspaceProvider;
}
/// <summary>
/// The activity host manager to use for processing
/// activities
/// </summary>
public override PSActivityHostController PSActivityHostController
{
get
{
return _activityHostController;
}
}
/// <summary>
/// The provider to be used for obtaining runspaces
/// </summary>
public override RunspaceProvider RemoteRunspaceProvider
{
get { return _runspaceProvider; }
}
/// <summary>
///
/// </summary>
public override RunspaceProvider LocalRunspaceProvider
{
get
{
return _localRunspaceProvider;
}
}
/// <summary>
/// return the singleton instance
/// </summary>
internal static DefaultWorkflowHost Instance
{
get { return _instance; }
}
internal void ResetLocalRunspaceProvider()
{
MethodInfo methodInfo = _localRunspaceProvider.GetType().GetMethod("Reset", BindingFlags.NonPublic | BindingFlags.Instance);
methodInfo.Invoke(_localRunspaceProvider, new object[]{});
}
}
#endregion DefaultWorkflowHost
}
@@ -1,295 +0,0 @@
/*
* Copyright (c) 2010 Microsoft Corporation. All rights reserved
*/
using Microsoft.PowerShell.Activities;
using System.Management.Automation.PerformanceData;
using System.Management.Automation.Tracing;
using System.Threading;
using System;
using System.Management.Automation;
using System.Globalization;
namespace Microsoft.PowerShell.Workflow
{
/// <summary>
/// PowerShell Workflow host runtime.
/// </summary>
public class PSWorkflowRuntime : PSWorkflowHost, IDisposable
{
private static PSWorkflowRuntime powerShellWorkflowHostInstance;
private static readonly object syncLock = new object();
private RunspaceProvider _runspaceProvider;
private RunspaceProvider _localRunspaceProvider;
private RunspaceProvider _unboundedLocalRunspaceProvider;
private static readonly Tracer _tracer = new Tracer();
private static readonly PSPerfCountersMgr _psPerfCountersMgrInst = PSPerfCountersMgr.Instance;
private readonly PSWorkflowConfigurationProvider _configuration;
private readonly object _syncObject = new object();
private PSWorkflowJobManager jobManager;
private PSActivityHostController activityHostController;
private bool _isDisposed;
/// <summary>
/// Default constructor
/// </summary>
public PSWorkflowRuntime()
{
_configuration = new PSWorkflowConfigurationProvider();
_configuration.Runtime = this;
PSCounterSetRegistrar registrar =
new PSCounterSetRegistrar(
PSWorkflowPerformanceCounterSetInfo.ProviderId,
PSWorkflowPerformanceCounterSetInfo.CounterSetId,
PSWorkflowPerformanceCounterSetInfo.CounterSetType,
PSWorkflowPerformanceCounterSetInfo.CounterInfoArray);
_psPerfCountersMgrInst.AddCounterSetInstance(registrar);
// Enable caching module paths appdomain-wide.
System.Management.Automation.PSModuleInfo.UseAppDomainLevelModuleCache = true;
}
/// <summary>
/// Constructs runtime based on configuration
/// </summary>
/// <param name="configuration"></param>
public PSWorkflowRuntime(PSWorkflowConfigurationProvider configuration)
{
if (configuration == null)
throw new ArgumentNullException("configuration");
// Only allow FullLanguage or ConstraintLanguage or it can be null in that case system wide default will take an affect
PSLanguageMode? langMode = configuration.LanguageMode;
if (langMode != null && langMode.HasValue && (langMode.Value == PSLanguageMode.NoLanguage || langMode.Value == PSLanguageMode.RestrictedLanguage))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.NotSupportedLanguageMode, langMode.Value.ToString()));
}
_configuration = configuration;
_configuration.Runtime = this;
}
/// <summary>
/// Dispose implementation.
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Dispose implementation.
/// </summary>
/// <param name="disposing"></param>
private void Dispose(bool disposing)
{
if (_isDisposed || !disposing)
return;
lock (_syncObject)
{
if (_isDisposed)
return;
// Suspend all running jobs then dispose all runspace providers
if (jobManager != null)
jobManager.Dispose();
jobManager = null;
var remoteRunspaceProvider = _runspaceProvider as ConnectionManager;
if (remoteRunspaceProvider != null)
remoteRunspaceProvider.Dispose();
_runspaceProvider = null;
var localRunspaceProvider = _localRunspaceProvider as LocalRunspaceProvider;
if (localRunspaceProvider != null)
localRunspaceProvider.Dispose();
_localRunspaceProvider = null;
var unboundedLocalRunspaceProvider = _localRunspaceProvider as LocalRunspaceProvider;
if (unboundedLocalRunspaceProvider != null)
unboundedLocalRunspaceProvider.Dispose();
_unboundedLocalRunspaceProvider = null;
activityHostController = null;
_isDisposed = true;
}
}
private void AssertNotDisposed()
{
if (_isDisposed)
{
throw new ObjectDisposedException("PSWorkflowRuntime");
}
}
internal static PSWorkflowRuntime Instance
{
get
{
if (powerShellWorkflowHostInstance == null)
{
lock (syncLock)
{
if (powerShellWorkflowHostInstance == null)
{
powerShellWorkflowHostInstance = new PSWorkflowRuntime();
}
}
}
return powerShellWorkflowHostInstance;
}
}
internal Tracer Tracer
{
get
{
return _tracer;
}
}
#region Test Helpers
internal void SetWorkflowJobManager(PSWorkflowJobManager wfJobManager)
{
lock (syncLock)
{
jobManager = wfJobManager;
}
}
#endregion Test Helpers
/// <summary>
/// The runtime configuration.
/// </summary>
public virtual PSWorkflowConfigurationProvider Configuration
{
get
{
return _configuration;
}
}
/// <summary>
/// JobManager
/// </summary>
public virtual PSWorkflowJobManager JobManager
{
get
{
if (jobManager != null)
return jobManager;
lock (syncLock)
{
if (jobManager != null)
return jobManager;
AssertNotDisposed();
jobManager = new PSWorkflowJobManager(this, _configuration.MaxRunningWorkflows);
}
return jobManager;
}
}
/// <summary>
/// PSActivityHostController (PSWorkflowHost)
/// </summary>
public override PSActivityHostController PSActivityHostController
{
get
{
if (activityHostController != null)
return activityHostController;
lock (syncLock)
{
if (activityHostController != null)
return activityHostController;
AssertNotDisposed();
activityHostController = _configuration.CreatePSActivityHostController();
}
return activityHostController;
}
}
/// <summary>
/// RemoteRunspaceProvider (PSWorkflowHost)
/// </summary>
public override RunspaceProvider RemoteRunspaceProvider
{
get
{
if (_runspaceProvider == null)
{
lock (_syncObject)
{
if (_runspaceProvider == null)
{
AssertNotDisposed();
_runspaceProvider = _configuration.CreateRemoteRunspaceProvider();
}
}
}
return _runspaceProvider;
}
}
/// <summary>
/// LocalRunspaceProvider (PSWorkflowHost)
/// </summary>
public override RunspaceProvider LocalRunspaceProvider
{
get
{
if (_localRunspaceProvider == null)
{
lock (_syncObject)
{
if (_localRunspaceProvider == null)
{
AssertNotDisposed();
_localRunspaceProvider = _configuration.CreateLocalRunspaceProvider(false);
}
}
}
return _localRunspaceProvider;
}
}
/// <summary>
/// The provider which will supply an unbounded number of
/// runspaces - to be used in PowerShell value
/// </summary>
public override RunspaceProvider UnboundedLocalRunspaceProvider
{
get
{
if (_unboundedLocalRunspaceProvider == null)
{
lock(_syncObject)
{
if (_unboundedLocalRunspaceProvider == null)
{
AssertNotDisposed();
_unboundedLocalRunspaceProvider = _configuration.CreateLocalRunspaceProvider(true);
}
}
}
return _unboundedLocalRunspaceProvider;
}
}
}
}
@@ -1,834 +0,0 @@
//
// Copyright (C) Microsoft. All rights reserved.
//
using System;
using System.Activities;
using System.Activities.Validation;
using System.Runtime.DurableInstancing;
using System.Collections.Generic;
using System.Management.Automation;
using System.Collections.ObjectModel;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using Microsoft.PowerShell.Activities;
using System.Diagnostics;
using System.Reflection;
using System.Globalization;
using System.Runtime.Serialization;
using System.Activities.Persistence;
using System.Activities.Hosting;
namespace Microsoft.PowerShell.Workflow
{
/// <summary>
/// WorkflowStoreComponent
/// </summary>
[Flags]
public enum WorkflowStoreComponents
{
/// <summary>
/// Streams
/// </summary>
Streams = 1,
/// <summary>
/// Metadata
/// </summary>
Metadata = 2,
/// <summary>
/// Definition
/// </summary>
Definition = 4,
/// <summary>
/// Timers
/// </summary>
Timer = 8,
/// <summary>
/// JobState
/// </summary>
JobState = 16,
/// <summary>
/// TerminatingError
/// </summary>
TerminatingError = 32,
/// <summary>
/// ActivityState, like remote activity execution state, etc.
/// </summary>
ActivityState = 64,
}
/// <summary>
/// ActivityRunMode
/// </summary>
public enum ActivityRunMode
{
/// <summary>
/// InProcess
/// </summary>
InProcess = 0,
/// <summary>
/// OutOfProcess
/// </summary>
OutOfProcess = 1,
}
/// <summary>
/// WorkflowInstanceStore
/// </summary>
public abstract class PSWorkflowInstanceStore
{
/// <summary>
/// PSWorkflowInstanceStore
/// </summary>
/// <param name="workflowInstance"></param>
protected PSWorkflowInstanceStore(PSWorkflowInstance workflowInstance)
{
if (workflowInstance == null)
throw new ArgumentNullException("workflowInstance");
PSWorkflowInstance = workflowInstance;
}
/// <summary>
/// PSWorkflowInstance
/// </summary>
public PSWorkflowInstance PSWorkflowInstance
{
get;
private set;
}
/// <summary>
/// CreatePersistenceIOParticipant
/// </summary>
/// <returns></returns>
public abstract PersistenceIOParticipant CreatePersistenceIOParticipant();
/// <summary>
/// CreateInstanceStore
/// </summary>
/// <returns></returns>
public abstract InstanceStore CreateInstanceStore();
#region Save Methods
/// <summary>
/// Save
/// </summary>
/// <param name="components"></param>
public void Save(WorkflowStoreComponents components)
{
this.Save(components, null);
}
internal void Save(WorkflowStoreComponents components, Dictionary<string, object> WorkflowContext)
{
Collection<object> componentsToSave = new Collection<object>();
if ((components & WorkflowStoreComponents.JobState) == WorkflowStoreComponents.JobState)
{
componentsToSave.Add(PSWorkflowInstance.State);
}
if (WorkflowContext != null)
{
componentsToSave.Add(WorkflowContext);
}
if (((components & WorkflowStoreComponents.Definition) == WorkflowStoreComponents.Definition) &&
(PSWorkflowInstance.PSWorkflowDefinition != null))
{
componentsToSave.Add(PSWorkflowInstance.PSWorkflowDefinition);
}
if (((components & WorkflowStoreComponents.TerminatingError) == WorkflowStoreComponents.TerminatingError) &&
(PSWorkflowInstance.Error != null))
{
if (!WorkflowJobSourceAdapter.GetInstance().IsShutdownInProgress)
{
if (PSWorkflowInstance.Error.GetType() != typeof(RemoteException))
{
componentsToSave.Add(PSWorkflowInstance.Error);
}
}
}
if (((components & WorkflowStoreComponents.Metadata) == WorkflowStoreComponents.Metadata) &&
(PSWorkflowInstance.PSWorkflowContext != null))
{
componentsToSave.Add(PSWorkflowInstance.PSWorkflowContext);
}
if (((components & WorkflowStoreComponents.Streams) == WorkflowStoreComponents.Streams) &&
(PSWorkflowInstance.Streams != null))
{
componentsToSave.Add(PSWorkflowInstance.Streams);
}
if (((components & WorkflowStoreComponents.ActivityState) == WorkflowStoreComponents.ActivityState) &&
(PSWorkflowInstance.RemoteActivityState != null))
{
componentsToSave.Add(PSWorkflowInstance.RemoteActivityState);
}
if (((components & WorkflowStoreComponents.Timer) == WorkflowStoreComponents.Timer) &&
PSWorkflowInstance.Timer != null)
{
componentsToSave.Add(PSWorkflowInstance.Timer);
}
DoSave(componentsToSave);
}
/// <summary>
/// DoSave
/// </summary>
/// <param name="components"></param>
protected abstract void DoSave(IEnumerable<object> components);
#endregion Save
#region Load Methods
/// <summary>
/// Load
/// </summary>
/// <param name="components"></param>
public void Load(WorkflowStoreComponents components)
{
Collection<Type> componentsToLoad = new Collection<Type>();
if ((components & WorkflowStoreComponents.JobState) == WorkflowStoreComponents.JobState)
{
componentsToLoad.Add(typeof(JobState));
PSWorkflowInstance.JobStateRetrieved = false;
}
if ((components & WorkflowStoreComponents.Definition) == WorkflowStoreComponents.Definition)
{
componentsToLoad.Add(typeof(PSWorkflowDefinition));
PSWorkflowInstance.PSWorkflowDefinition = null;
}
if ((components & WorkflowStoreComponents.TerminatingError) == WorkflowStoreComponents.TerminatingError)
{
componentsToLoad.Add(typeof(Exception));
PSWorkflowInstance.Error = null;
}
if ((components & WorkflowStoreComponents.Metadata) == WorkflowStoreComponents.Metadata)
{
componentsToLoad.Add(typeof(PSWorkflowContext));
PSWorkflowInstance.PSWorkflowContext = null;
}
if ((components & WorkflowStoreComponents.Streams) == WorkflowStoreComponents.Streams)
{
componentsToLoad.Add(typeof(PowerShellStreams<PSObject, PSObject>));
PSWorkflowInstance.Streams = null;
}
if ((components & WorkflowStoreComponents.ActivityState) == WorkflowStoreComponents.ActivityState)
{
componentsToLoad.Add(typeof(PSWorkflowRemoteActivityState));
PSWorkflowInstance.RemoteActivityState = null;
}
if ((components & WorkflowStoreComponents.Timer) == WorkflowStoreComponents.Timer)
{
componentsToLoad.Add(typeof(PSWorkflowTimer));
PSWorkflowInstance.Timer = null;
}
IEnumerable<object> loadedComponents = DoLoad(componentsToLoad);
foreach (object loadedComponent in loadedComponents)
{
Type componentType = loadedComponent.GetType();
if (componentType == typeof(JobState))
{
PSWorkflowInstance.State = (JobState)loadedComponent;
PSWorkflowInstance.JobStateRetrieved = true;
}
else if (componentType == typeof(PSWorkflowDefinition))
{
PSWorkflowInstance.PSWorkflowDefinition = (PSWorkflowDefinition)loadedComponent;
}
else if (loadedComponent is Exception)
{
PSWorkflowInstance.Error = (Exception)loadedComponent;
}
else if (componentType == typeof(PSWorkflowContext))
{
PSWorkflowInstance.PSWorkflowContext = (PSWorkflowContext)loadedComponent;
}
else if (componentType == typeof(PowerShellStreams<PSObject, PSObject>))
{
PSWorkflowInstance.Streams = (PowerShellStreams<PSObject, PSObject>)loadedComponent;
}
else if (componentType == typeof(PSWorkflowTimer))
{
PSWorkflowInstance.Timer = (PSWorkflowTimer)loadedComponent;
}
else if (componentType == typeof(PSWorkflowRemoteActivityState))
{
PSWorkflowInstance.RemoteActivityState = (PSWorkflowRemoteActivityState)loadedComponent;
}
}
}
internal Dictionary<string, object> LoadWorkflowContext()
{
Dictionary<string, object> workflowContext = null;
Collection<Type> componentsToLoad = new Collection<Type>();
componentsToLoad.Add(typeof(Dictionary<string, object>));
IEnumerable<object> loadedComponents = DoLoad(componentsToLoad);
foreach (object loadedComponent in loadedComponents)
{
Type componentType = loadedComponent.GetType();
if (componentType == typeof(Dictionary<string, object>))
{
workflowContext = (Dictionary<string, object>)loadedComponent;
}
}
return workflowContext;
}
/// <summary>
/// DoLoad
/// </summary>
/// <param name="componentTypes"></param>
protected abstract IEnumerable<object> DoLoad(IEnumerable<Type> componentTypes);
#endregion Load Methods
#region Delete Methods
/// <summary>
/// Delete
/// </summary>
public void Delete()
{
DoDelete();
}
/// <summary>
/// DoDelete
/// </summary>
protected abstract void DoDelete();
#endregion Delete Methods
}
/// <summary>
/// WorkflowInstance
/// </summary>
public abstract class PSWorkflowInstance : IDisposable
{
#region Private Members
/// <summary>
/// _syncLock
/// </summary>
private object _syncLock = new object();
#endregion Private Members
#region Protected Members
/// <summary>
/// _disposed
/// </summary>
protected bool Disposed
{
set;
get;
}
/// <summary>
/// Synchronization object available to derived classes.
/// </summary>
protected object SyncLock
{
get
{
return _syncLock;
}
}
/// <summary>
/// DoStopInstance
/// </summary>
protected virtual void DoStopInstance()
{
throw new NotImplementedException();
}
/// <summary>
/// DoAbortInstance
/// </summary>
/// <param name="reason">Reason for aborting workflow.</param>
protected virtual void DoAbortInstance(string reason)
{
throw new NotImplementedException();
}
/// <summary>
/// DoTerminateInstance
/// </summary>
/// <param name="reason">Reason message for termination</param>
protected virtual void DoTerminateInstance(string reason)
{
throw new NotImplementedException();
}
/// <summary>
/// DoTerminateInstance
/// </summary>
/// <param name="reason">Reason message for termination</param>
/// <param name="suppressError">Suppress error for termination</param>
protected virtual void DoTerminateInstance(string reason, bool suppressError)
{
throw new NotImplementedException();
}
/// <summary>
/// DoResumeInstance
/// </summary>
protected virtual void DoResumeInstance(string label)
{
throw new NotImplementedException();
}
/// <summary>
/// DoSuspendInstance
/// </summary>
/// <param name="notStarted"></param>
protected virtual void DoSuspendInstance(bool notStarted)
{
throw new NotImplementedException();
}
/// <summary>
/// DoExecuteInstance
/// </summary>
protected virtual void DoExecuteInstance()
{
throw new NotImplementedException();
}
/// <summary>
/// DoResumeBookmark
/// </summary>
/// <param name="bookmark"></param>
/// <param name="state"></param>
protected virtual void DoResumeBookmark(Bookmark bookmark, object state)
{
throw new NotImplementedException();
}
/// <summary>
/// Loads the xaml to create an executable activity.
/// </summary>
protected virtual void DoCreateInstance()
{
throw new NotImplementedException();
}
/// <summary>
/// Remove
/// </summary>
protected virtual void DoRemoveInstance()
{
throw new NotImplementedException();
}
/// <summary>
/// DoPersistInstance
/// </summary>
protected virtual void DoPersistInstance()
{
throw new NotImplementedException();
}
/// <summary>
/// DoGetPersistableIdleAction
/// </summary>
/// <param name="bookmarks"></param>
/// <param name="externalSuspendRequest"></param>
/// <returns></returns>
protected virtual PSPersistableIdleAction DoGetPersistableIdleAction(ReadOnlyCollection<BookmarkInfo> bookmarks, bool externalSuspendRequest)
{
throw new NotImplementedException();
}
/// <summary>
/// Dispose
/// </summary>
protected virtual void Dispose(bool disposing)
{
if (!disposing || Disposed)
return;
lock (SyncLock)
{
if (Disposed)
return;
Disposed = true;
this.OnCompleted = null;
this.OnFaulted = null;
this.OnStopped = null;
this.OnAborted = null;
this.OnSuspended = null;
this.OnIdle = null;
this.OnPersistableIdleAction = null;
this.OnUnloaded = null;
}
}
#endregion Protected Members
#region Internal Members
internal PSWorkflowRuntime Runtime { get; set; }
internal void CreateInstance() { this.DoCreateInstance(); }
internal void ExecuteInstance() { this.DoExecuteInstance(); }
internal void SuspendInstance(bool notStarted) { this.DoSuspendInstance(notStarted); }
internal void RemoveInstance() { this.DoRemoveInstance(); }
internal void ResumeInstance(string label) { this.DoResumeInstance(label); }
internal void ResumeBookmark(Bookmark bookmark, object state) { this.DoResumeBookmark(bookmark, state); }
internal void StopInstance() { this.DoStopInstance(); }
internal void AbortInstance(string reason) { this.DoAbortInstance(reason); }
internal void TerminateInstance(string reason, bool suppressError) { this.DoTerminateInstance(reason, suppressError); }
internal void PersistInstance() { this.DoPersistInstance(); }
internal PSPersistableIdleAction GetPersistableIdleAction(ReadOnlyCollection<BookmarkInfo> bookmarks, bool externalSuspendRequest) { return this.DoGetPersistableIdleAction(bookmarks, externalSuspendRequest); }
/// <summary>
/// Gets the Guid of workflow instance.
/// </summary>
internal virtual Guid Id
{
get { return this.InstanceId.Guid; }
}
/// <summary>
/// JobStateRetrieved
/// </summary>
internal bool JobStateRetrieved { get; set; }
internal bool ForceDisableStartOrEndPersistence { get; set; }
/// <summary>
/// CheckForTerminalAction
/// </summary>
internal virtual void CheckForTerminalAction()
{
throw new NotImplementedException();
}
/// <summary>
/// Load instance for resuming the workflow
/// </summary>
internal virtual void DoLoadInstanceForReactivation()
{
throw new NotImplementedException();
}
/// <summary>
/// PerformTaskAtTerminalState
/// </summary>
internal virtual void PerformTaskAtTerminalState()
{
throw new NotImplementedException();
}
/// <summary>
/// On completed handler.
/// </summary>
internal Action<object> OnCompletedDelegate
{
set { this.OnCompleted = value; }
}
/// <summary>
/// On faulted handler.
/// </summary>
internal Action<Exception, object> OnFaultedDelegate
{
set { this.OnFaulted = value; }
}
/// <summary>
/// On stopped handler.
/// </summary>
internal Action<object> OnStoppedDelegate
{
set { this.OnStopped = value; }
}
/// <summary>
/// On aborted handler.
/// </summary>
internal Action<Exception, object> OnAbortedDelegate
{
set { this.OnAborted = value; }
}
/// <summary>
/// On suspended handler.
/// </summary>
internal Action<object> OnSuspendedDelegate
{
set { this.OnSuspended = value; }
}
/// <summary>
/// On idle handler.
/// </summary>
internal Action<ReadOnlyCollection<System.Activities.Hosting.BookmarkInfo>, object> OnIdleDelegate
{
set { this.OnIdle = value; }
}
/// <summary>
/// On persistable idle action handler.
/// </summary>
internal Func<ReadOnlyCollection<System.Activities.Hosting.BookmarkInfo>, bool, object, PSPersistableIdleAction> OnPersistableIdleActionDelegate
{
set { this.OnPersistableIdleAction = value; }
}
/// <summary>
/// On unloaded handler.
/// </summary>
internal Action<object> OnUnloadedDelegate
{
set { this.OnUnloaded = value; }
}
/// <summary>
/// Validate label
/// </summary>
/// <param name="label"></param>
internal virtual void ValidateIfLabelExists(string label)
{
throw new NotImplementedException();
}
internal virtual bool SaveStreamsIfNecessary()
{
return false;
}
#endregion Internal Members
#region protected delegate members
/// <summary>
/// On completed handler.
/// </summary>
protected Action<object> OnCompleted { get; private set; }
/// <summary>
/// On faulted handler.
/// </summary>
protected Action<Exception, object> OnFaulted { get; private set; }
/// <summary>
/// On stopped handler.
/// </summary>
protected Action<object> OnStopped { get; private set; }
/// <summary>
/// On aborted handler.
/// </summary>
protected Action<Exception, object> OnAborted { get; private set; }
/// <summary>
/// On suspended handler.
/// </summary>
protected Action<object> OnSuspended { get; private set; }
/// <summary>
/// On idle handler.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "????")]
protected Action<ReadOnlyCollection<System.Activities.Hosting.BookmarkInfo>, object> OnIdle { get; private set; }
/// <summary>
/// On persistable idle action handler.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "????")]
protected Func<ReadOnlyCollection<System.Activities.Hosting.BookmarkInfo>, bool, object, PSPersistableIdleAction> OnPersistableIdleAction { get; private set; }
/// <summary>
/// On unloaded handler.
/// </summary>
protected Action<object> OnUnloaded { get; private set; }
#endregion protected delegate members
#region Public Members
/// <summary>
/// PSWorkflowJob
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PSWorkflowJob PSWorkflowJob
{
get { throw new NotImplementedException();}
protected internal set { throw new NotImplementedException(); }
}
/// <summary>
/// Gets the Guid of workflow instance.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PSWorkflowId InstanceId
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// Gets the workflow job creation context.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual Dictionary<string, object> CreationContext
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// State
/// </summary>
public virtual JobState State
{
get;
set;
}
/// <summary>
/// InstanceStore
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PSWorkflowInstanceStore InstanceStore
{
get{ throw new NotImplementedException(); }
}
/// <summary>
/// Gets the definition of workflow.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PSWorkflowDefinition PSWorkflowDefinition
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
/// Gets the streams of workflow.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PowerShellStreams<PSObject, PSObject> Streams
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
/// Gets/Sets the RemoteActivityState of workflow.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PSWorkflowRemoteActivityState RemoteActivityState
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
/// Gets the streams of workflow.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Error")]
public virtual Exception Error
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
/// Gets the timers of workflow.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PSWorkflowTimer Timer
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
/// Gets the metadatas of workflow.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public virtual PSWorkflowContext PSWorkflowContext
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
/// <summary>
/// Gets the workflow debugger.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
internal virtual PSWorkflowDebugger PSWorkflowDebugger
{
get { throw new NotImplementedException(); }
}
/// <summary>
/// Dispose
/// </summary>
public void Dispose()
{
if (Disposed)
return;
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Dispose the streams to save memory
/// </summary>
public virtual void DisposeStreams()
{
}
#endregion Public Members
}
}
@@ -1,217 +0,0 @@
/*
* Copyright (c) 2011 Microsoft Corporation. All rights reserved
*/
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.Timers;
namespace Microsoft.PowerShell.Workflow
{
/// <summary>
/// Bounded cache which will clear items when not used for a while
/// </summary>
/// <typeparam name="T">type of item to use</typeparam>
internal class TimeBasedCache<T> : IEnumerable, IDisposable
{
private readonly int _timeoutInSeconds;
private readonly object _timerServicingSyncObject = new object();
private readonly Timer _validationTimer;
private int _timerFired;
private const int TimerFired = 1;
private const int TimerReset = 0;
private readonly ConcurrentDictionary<Guid, Item<T>> _cache = new ConcurrentDictionary<Guid, Item<T>>();
/// <summary>
///
/// </summary>
internal ConcurrentDictionary<Guid, Item<T>> Cache
{
get { return _cache; }
}
/// <summary>
/// The consumer of this class should hold a lock
/// on this object when servicing requests and adding
/// to this cache
/// </summary>
internal object TimerServicingSyncObject
{
get { return _timerServicingSyncObject; }
}
internal TimeBasedCache(int timeoutInSeconds)
{
_timeoutInSeconds = timeoutInSeconds;
_validationTimer = new Timer
{
AutoReset = true,
Interval = _timeoutInSeconds*1000,
Enabled = false
};
_validationTimer.Elapsed += ValidationTimerElapsed;
_validationTimer.Start();
}
private void ValidationTimerElapsed(object sender, ElapsedEventArgs e)
{
// ensure that the servicing thread is done before proceeding
if (_timerFired == TimerFired) return;
lock(TimerServicingSyncObject)
{
if (_timerFired == TimerFired) return;
_timerFired = TimerFired;
Collection<Item<T>> toRemove = new Collection<Item<T>>();
foreach(Item<T> item in _cache.Values)
{
if (item.Idle)
toRemove.Add(item);
else if (!item.Busy)
item.Idle = true;
}
foreach(Item<T> item in toRemove)
{
Item<T> removedItem;
_cache.TryRemove(item.InstanceId, out removedItem);
IDisposable disposable = removedItem.Value as IDisposable;
if (disposable == null) continue;
//dispose and force early GC
disposable.Dispose();
disposable = null;
removedItem = null;
}
_timerFired = TimerReset;
}
}
/// <summary>
///
/// </summary>
internal void Add(Item<T> item)
{
item.Busy = true;
item.Idle = false;
_cache.TryAdd(item.InstanceId, item);
}
/// <summary>
///
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
///
/// </summary>
/// <param name="disposing"></param>
protected void Dispose(bool disposing)
{
if (disposing)
{
_validationTimer.Dispose();
}
}
internal class CacheEnumerator : IEnumerator
{
private readonly ConcurrentDictionary<Guid, Item<T>> _cache;
private readonly IEnumerator _dictionaryEnumerator;
private Item<T> _currentItem;
internal CacheEnumerator(ConcurrentDictionary<Guid, Item<T>> cache)
{
_cache = cache;
_dictionaryEnumerator = _cache.Keys.GetEnumerator();
}
/// <summary>
/// Advances the enumerator to the next element of the collection.
/// </summary>
/// <returns>
/// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
/// </returns>
/// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception><filterpriority>2</filterpriority>
public bool MoveNext()
{
if (_dictionaryEnumerator.MoveNext())
{
Guid key = (Guid)_dictionaryEnumerator.Current;
_currentItem = default(Item<T>);
_cache.TryGetValue(key, out _currentItem);
if (_currentItem != null)
return true;
}
return false;
}
/// <summary>
/// Sets the enumerator to its initial position, which is before the first element in the collection.
/// </summary>
/// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception><filterpriority>2</filterpriority>
public void Reset()
{
_dictionaryEnumerator.Reset();
}
/// <summary>
/// Gets the current element in the collection.
/// </summary>
/// <returns>
/// The current element in the collection.
/// </returns>
/// <exception cref="T:System.InvalidOperationException">The enumerator is positioned before the first element of the collection or after the last element.</exception><filterpriority>2</filterpriority>
public object Current
{
get { return _currentItem; }
}
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
public IEnumerator GetEnumerator()
{
return new CacheEnumerator(_cache);
}
}
/// <summary>
/// one item that will be used in the cache
/// </summary>
/// <typeparam name="T">type of item to use</typeparam>
internal class Item<T>
{
private readonly Guid _instanceId;
private readonly T _value;
internal bool Busy { get; set; }
internal bool Idle { get; set; }
internal T Value
{
get { return _value; }
}
internal Guid InstanceId
{
get { return _instanceId; }
}
internal Item(T value, Guid instanceId)
{
_value = value;
_instanceId = instanceId;
}
}
}
@@ -1,91 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;
using System.Activities;
/// <summary>
/// Define all the metadatas.
/// </summary>
public sealed class PSWorkflowDefinition
{
private Activity workflow;
private string workflowXaml;
private string runtimeAssemblyPath;
private Dictionary<string, string> requiredAssemblies;
/// <summary>
/// Workflow instance constructor.
/// </summary>
/// <param name="workflow">The workflow definition, represented in object-graph.</param>
/// <param name="workflowXaml">The workflow xaml definition.</param>
/// <param name="runtimeAssemblyPath">The path to the runtime assembly.</param>
/// <param name="requiredAssemblies">Required assemblies paths</param>
public PSWorkflowDefinition(
Activity workflow,
string workflowXaml,
string runtimeAssemblyPath,
Dictionary<string, string> requiredAssemblies): this(workflow, workflowXaml, runtimeAssemblyPath)
{
this.requiredAssemblies = requiredAssemblies;
}
/// <summary>
/// Workflow instance constructor.
/// </summary>
/// <param name="workflow">The workflow definition, represented in object-graph.</param>
/// <param name="workflowXaml">The workflow xaml definition.</param>
/// <param name="runtimeAssemblyPath">The path to the runtime assembly.</param>
public PSWorkflowDefinition(
Activity workflow,
string workflowXaml,
string runtimeAssemblyPath)
{
this.workflow = workflow;
this.workflowXaml = workflowXaml;
this.runtimeAssemblyPath = runtimeAssemblyPath;
}
/// <summary>
/// Gets sets the workflow.
/// </summary>
public Activity Workflow
{
get { return this.workflow; }
set { this.workflow = value; }
}
/// <summary>
/// Gets sets the workflow xaml.
/// </summary>
public string WorkflowXaml
{
get { return this.workflowXaml; }
set { this.workflowXaml = value; }
}
/// <summary>
/// Gets sets the runtime assembly path.
/// </summary>
public string RuntimeAssemblyPath
{
get { return this.runtimeAssemblyPath; }
set { this.runtimeAssemblyPath = value; }
}
/// <summary>
/// Gets sets the required assemblies.
/// </summary>
public Dictionary<string, string> RequiredAssemblies
{
get { return this.requiredAssemblies; }
}
}
}
@@ -1,105 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System.Collections.Generic;
/// <summary>
/// Define all the metadatas.
/// </summary>
public class PSWorkflowContext
{
/// <summary>
/// The parameters, which need to be passed to the workflow engine.
/// </summary>
private Dictionary<string, object> _workflowParameters;
/// <summary>
/// The ubiquitous parameters, which are also passed to the engine.
/// </summary>
private Dictionary<string, object> _psWorkflowCommonParameters;
/// <summary>
/// The metadata, which contains all the information related to job and client like, job-id, connection-id and application-id etc.
/// </summary>
private Dictionary<string, object> jobMetadata;
/// <summary>
/// The metadata, which is specific to the caller and doesn't contain any information related to workflow execution.
/// </summary>
private Dictionary<string, object> privateMetadata;
/// <summary>
/// Default Constructor.
/// </summary>
public PSWorkflowContext()
{
this._workflowParameters = null;
this._psWorkflowCommonParameters = null;
this.jobMetadata = null;
this.privateMetadata = null;
}
/// <summary>
/// Workflow metadatas constructor.
/// </summary>
/// <param name="workflowParameters">The parameters, which need to be passed to the workflow engine.</param>
/// <param name="workflowCommonParameters">The ubiquitous parameters, which are also passed to the engine.</param>
/// <param name="jobMetadata">The metadata, which contains all the information related to job and client like, job-id, connection-id and application-id etc.</param>
/// <param name="privateMetadata">The metadata, which is specific to the caller and doesn't contain any information related to workflow execution.</param>
public PSWorkflowContext(
Dictionary<string, object> workflowParameters,
Dictionary<string, object> workflowCommonParameters,
Dictionary<string, object> jobMetadata,
Dictionary<string, object> privateMetadata)
{
this._workflowParameters = workflowParameters;
this._psWorkflowCommonParameters = workflowCommonParameters;
this.jobMetadata = jobMetadata;
this.privateMetadata = privateMetadata;
}
/// <summary>
/// Gets the input to workflow.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public Dictionary<string, object> WorkflowParameters
{
get { return this._workflowParameters; }
set { this._workflowParameters = value; }
}
/// <summary>
/// Gets the input to workflow.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public Dictionary<string, object> PSWorkflowCommonParameters
{
get { return this._psWorkflowCommonParameters; }
set { this._psWorkflowCommonParameters = value; }
}
/// <summary>
/// Gets the input to workflow.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public Dictionary<string, object> JobMetadata
{
get { return this.jobMetadata; }
set { this.jobMetadata = value; }
}
/// <summary>
/// Gets the input to workflow.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public Dictionary<string, object> PrivateMetadata
{
get { return this.privateMetadata; }
set { this.privateMetadata = value; }
}
}
}
@@ -1,107 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System;
using System.Diagnostics.PerformanceData;
using System.Management.Automation;
using System.Management.Automation.PerformanceData;
namespace Microsoft.PowerShell.Workflow
{
/// <summary>
/// PSWorkflowPerformanceCounterSetInfo class contains
/// the data essential to create an
/// instance of PSCounterSetRegistrar for monitoring
/// workflow performance
/// </summary>
internal static class PSWorkflowPerformanceCounterSetInfo
{
internal static Guid ProviderId = new Guid("{5db760bc-64b2-4da7-b4ef-7dab105fbb8c}");
/// <summary>
/// If some other assemblies (e.g. Microsoft.PowerShell.Workflow.Activities) need
/// access to the counters, then they would need to specify the CounterSetId,
/// alongwith the counterId. Hence, CounterSetId is public.
/// </summary>
internal static Guid CounterSetId = new Guid("{faa17411-9025-4b86-8b5e-ce2f32b06e13}");
internal static CounterSetInstanceType CounterSetType = CounterSetInstanceType.Multiple;
internal static CounterInfo[] CounterInfoArray =
new CounterInfo[]{
new CounterInfo(PSWorkflowPerformanceCounterIds.FailedWorkflowJobsCount,CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.FailedWorkflowJobsPerSec,CounterType.RateOfCountPerSecond64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ResumedWorkflowJobsCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ResumedWorkflowJobsPerSec, CounterType.RateOfCountPerSecond64),
new CounterInfo(PSWorkflowPerformanceCounterIds.RunningWorkflowJobsCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.RunningWorkflowJobsPerSec, CounterType.RateOfCountPerSecond64),
new CounterInfo(PSWorkflowPerformanceCounterIds.StoppedWorkflowJobsCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.StoppedWorkflowJobsPerSec, CounterType.RateOfCountPerSecond64),
new CounterInfo(PSWorkflowPerformanceCounterIds.SucceededWorkflowJobsCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.SucceededWorkflowJobsPerSec, CounterType.RateOfCountPerSecond64),
new CounterInfo(PSWorkflowPerformanceCounterIds.SuspendedWorkflowJobsCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.SuspendedWorkflowJobsPerSec, CounterType.RateOfCountPerSecond64),
new CounterInfo(PSWorkflowPerformanceCounterIds.TerminatedWorkflowJobsCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.TerminatedWorkflowJobsPerSec, CounterType.RateOfCountPerSecond64),
//new CounterInfo(PSWorkflowPerformanceCounterIds.TerminatedExceptionWorkflowJobsCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.WaitingWorkflowJobsCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ActivityHostMgrBusyProcessesCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ActivityHostMgrFailedRequestsPerSec, CounterType.RateOfCountPerSecond64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ActivityHostMgrFailedRequestsQueueLength, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ActivityHostMgrIncomingRequestsPerSec, CounterType.RateOfCountPerSecond64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ActivityHostMgrPendingRequestsQueueLength, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ActivityHostMgrCreatedProcessesCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ActivityHostMgrDisposedProcessesCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.ActivityHostMgrProcessesPoolSize, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.PSRemotingPendingRequestsQueueLength, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.PSRemotingRequestsBeingServicedCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.PSRemotingForcedToWaitRequestsQueueLength, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.PSRemotingConnectionsCreatedCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.PSRemotingConnectionsDisposedCount, CounterType.RawData64),
new CounterInfo(PSWorkflowPerformanceCounterIds.PSRemotingConnectionsClosedReopenedCount, CounterType.RawData64)
};
}
/// <summary>
/// PSWorkflowPerformanceCounterIds enumerates the
/// list of valid performance counter ids related to Powershell Workflow.
/// NOTE: The prime reason for making this not an enum are as follows:
/// (1) Everytime the enum will have to be typecasted to an int before invoking any
/// of the Performance Counters API.
/// (2) In case of M3P, its possible that some of the perf counters might be updated
/// by ActivityBase assembly, in which such perf counter ids might need to have
/// public access modifier, instead of internal.
/// </summary>
internal static class PSWorkflowPerformanceCounterIds
{
internal const int FailedWorkflowJobsCount = 1;
internal const int FailedWorkflowJobsPerSec = FailedWorkflowJobsCount + 1;
internal const int ResumedWorkflowJobsCount = FailedWorkflowJobsPerSec + 1;
internal const int ResumedWorkflowJobsPerSec = ResumedWorkflowJobsCount + 1;
internal const int RunningWorkflowJobsCount = ResumedWorkflowJobsPerSec + 1;
internal const int RunningWorkflowJobsPerSec = RunningWorkflowJobsCount + 1;
internal const int StoppedWorkflowJobsCount = RunningWorkflowJobsPerSec + 1;
internal const int StoppedWorkflowJobsPerSec = StoppedWorkflowJobsCount + 1;
internal const int SucceededWorkflowJobsCount = StoppedWorkflowJobsPerSec + 1;
internal const int SucceededWorkflowJobsPerSec = SucceededWorkflowJobsCount + 1;
internal const int SuspendedWorkflowJobsCount = SucceededWorkflowJobsPerSec + 1;
internal const int SuspendedWorkflowJobsPerSec = SuspendedWorkflowJobsCount + 1;
internal const int TerminatedWorkflowJobsCount = SuspendedWorkflowJobsPerSec + 1;
internal const int TerminatedWorkflowJobsPerSec = TerminatedWorkflowJobsCount + 1;
internal const int WaitingWorkflowJobsCount = TerminatedWorkflowJobsPerSec + 1;
internal const int ActivityHostMgrBusyProcessesCount = WaitingWorkflowJobsCount + 1;
internal const int ActivityHostMgrFailedRequestsPerSec = ActivityHostMgrBusyProcessesCount + 1;
internal const int ActivityHostMgrFailedRequestsQueueLength = ActivityHostMgrFailedRequestsPerSec + 1;
internal const int ActivityHostMgrIncomingRequestsPerSec = ActivityHostMgrFailedRequestsQueueLength + 1;
internal const int ActivityHostMgrPendingRequestsQueueLength = ActivityHostMgrIncomingRequestsPerSec + 1;
internal const int ActivityHostMgrCreatedProcessesCount = ActivityHostMgrPendingRequestsQueueLength + 1;
internal const int ActivityHostMgrDisposedProcessesCount = ActivityHostMgrCreatedProcessesCount + 1;
internal const int ActivityHostMgrProcessesPoolSize = ActivityHostMgrDisposedProcessesCount + 1;
internal const int PSRemotingPendingRequestsQueueLength = ActivityHostMgrProcessesPoolSize + 1;
internal const int PSRemotingRequestsBeingServicedCount = PSRemotingPendingRequestsQueueLength + 1;
internal const int PSRemotingForcedToWaitRequestsQueueLength = PSRemotingRequestsBeingServicedCount + 1;
internal const int PSRemotingConnectionsCreatedCount = PSRemotingForcedToWaitRequestsQueueLength + 1;
internal const int PSRemotingConnectionsDisposedCount = PSRemotingConnectionsCreatedCount + 1;
internal const int PSRemotingConnectionsClosedReopenedCount = PSRemotingConnectionsDisposedCount + 1;
};
}
@@ -1,265 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Management.Automation.Tracing;
#if _NOTARMBUILD_
using Microsoft.Build.Evaluation;
using Microsoft.Build.Logging;
#endif
using System.Activities.XamlIntegration;
using System.IO;
using System.Xaml;
using System.Xml;
using System.Collections.Generic;
using System.Runtime.InteropServices;
/// <summary>
/// This class is responsible for compiling dependent workflows.
/// </summary>
internal class WorkflowRuntimeCompilation
{
private static readonly PowerShellTraceSource Tracer = PowerShellTraceSourceFactory.GetTraceSource();
/// <summary>
/// The template project which is used for default project values.
/// </summary>
private const string Template_Project = @"<?xml version=""1.0"" encoding=""utf-8""?><Project ToolsVersion=""4.0"" DefaultTargets=""Build"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""><PropertyGroup><Configuration Condition="" '$(Configuration)' == '' "">Release</Configuration><Platform>AnyCPU</Platform><ProductVersion>10.0</ProductVersion><SchemaVersion>2.0</SchemaVersion><OutputType>Library</OutputType><AppDesignerFolder>Properties</AppDesignerFolder><TargetFrameworkVersion>v4.5</TargetFrameworkVersion><TargetFrameworkProfile></TargetFrameworkProfile><FileAlignment>512</FileAlignment></PropertyGroup><PropertyGroup><DebugSymbols>true</DebugSymbols><DebugType>full</DebugType><Optimize>false</Optimize><OutputPath>bin\Debug\</OutputPath><DefineConstants>DEBUG;TRACE</DefineConstants><ErrorReport>prompt</ErrorReport><WarningLevel>4</WarningLevel></PropertyGroup><PropertyGroup><DebugType>pdbonly</DebugType><Optimize>true</Optimize><OutputPath>bin\Release\</OutputPath><DefineConstants>TRACE</DefineConstants><ErrorReport>prompt</ErrorReport><WarningLevel>4</WarningLevel></PropertyGroup><ItemGroup><Reference Include=""Microsoft.CSharp"" /><Reference Include=""System"" /><Reference Include=""System.Activities"" /><Reference Include=""System.Core"" /><Reference Include=""System.Data"" /><Reference Include=""System.ServiceModel"" /><Reference Include=""System.ServiceModel.Activities"" /><Reference Include=""System.Xaml"" /><Reference Include=""System.Xml"" /><Reference Include=""System.Xml.Linq"" /><Reference Include=""System.Management"" /><Reference Include=""System.Management.Automation"" /><Reference Include=""Microsoft.PowerShell.Workflow.ServiceCore"" /></ItemGroup><Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" /><!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name=""BeforeBuild""></Target><Target Name=""AfterBuild""></Target>--></Project>";
/// <summary>
/// The runtime generated project name.
/// </summary>
internal string ProjectName { get; set; }
/// <summary>
/// The runtime generated Project folder path.
/// </summary>
internal string ProjectFolderPath { get; set; }
/// <summary>
/// The runtime generated Project file path (.csprj file).
/// </summary>
internal string ProjectFilePath { get; set; }
/// <summary>
/// The runtime generated build log path.
/// </summary>
internal string BuildLogPath { get; set; }
/// <summary>
/// The runtime generated assembly name.
/// </summary>
internal string AssemblyName { get; set; }
/// <summary>
/// The runtime generated assembly path.
/// </summary>
internal string AssemblyPath { get; set; }
/// <summary>
/// The returned code of project.Build.
/// </summary>
internal bool BuildReturnedCode { get; set; }
private string _projectRoot;
/// <summary>
/// Default constructor.
/// </summary>
internal WorkflowRuntimeCompilation()
{
if (IsRunningOnProcessorArchitectureARM())
{
Tracer.WriteMessage("The workflow Calling workflow is not supported so throwing the exception.");
throw new NotSupportedException(Resources.WFCallingWFNotSupported);
}
this.ProjectName = "Workflow_" + Guid.NewGuid().ToString("N");
this._projectRoot = Path.Combine(Path.GetTempPath(), @"PSWorkflowCompilation\"+this.ProjectName);
this.ProjectFolderPath = Path.Combine(this._projectRoot, "Project");
this.ProjectFilePath = Path.Combine(this.ProjectFolderPath, "RuntimeProject.csproj");
this.BuildLogPath = Path.Combine(this.ProjectFolderPath, "Build.Log");
this.AssemblyName = this.ProjectName;
this.AssemblyPath = Path.Combine(this._projectRoot, this.ProjectName + ".dll");
}
/// <summary>
/// Compiling the workflow xamls into the assembly.
/// </summary>
internal void Compile(List<string> dependentWorkflows, Dictionary<string, string> requiredAssemblies)
{
if (IsRunningOnProcessorArchitectureARM())
{
Tracer.WriteMessage("The workflow Calling workflow is not supported so throwing the exception.");
throw new NotSupportedException(Resources.WFCallingWFNotSupported);
}
// Note that the _NOT_ARMBUILD_ flag is not a global build flag and needs to be set in the corresponding sources.inc file as appropriate.
#if _NOTARMBUILD_
DirectoryInfo folder = new DirectoryInfo(this.ProjectFolderPath);
folder.Create();
List<string> workflowFiles = new List<string>();
try
{
// Dump the files
foreach (string dependentWorkflow in dependentWorkflows)
{
string newFileName = Path.Combine(this.ProjectFolderPath, Path.GetRandomFileName() + ".xaml");
File.WriteAllText(newFileName, dependentWorkflow);
workflowFiles.Add(newFileName);
}
File.WriteAllText(this.ProjectFilePath, Template_Project);
}
catch (Exception e)
{
Tracer.TraceException(e);
throw;
}
using (ProjectCollection projects = new ProjectCollection())
{
Project project = projects.LoadProject(this.ProjectFilePath);
project.SetProperty("AssemblyName", this.AssemblyName);
HashSet<string> Assemblies = new HashSet<string>();
foreach (string file in workflowFiles)
{
project.AddItem("XamlAppDef", file);
XamlXmlReader reader = new XamlXmlReader(XmlReader.Create(file, new XmlReaderSettings { XmlResolver = null }), new XamlSchemaContext());
using (reader)
{
while (reader.Read())
{
if (reader.NodeType == XamlNodeType.NamespaceDeclaration)
{
string _namespace = reader.Namespace.Namespace.ToLowerInvariant();
if (_namespace.IndexOf("assembly=", StringComparison.OrdinalIgnoreCase) > -1)
{
List<string> filters = new List<string>();
filters.Add("assembly=");
string[] results = _namespace.Split(filters.ToArray(), StringSplitOptions.RemoveEmptyEntries);
if (results.Length > 1 && !string.IsNullOrEmpty(results[1]))
{
string requiredAssemblyLocation;
if (requiredAssemblies != null && requiredAssemblies.Count > 0 && requiredAssemblies.TryGetValue(results[1], out requiredAssemblyLocation))
{
Assemblies.Add(requiredAssemblyLocation);
}
else
{
Assemblies.Add(results[1]);
}
}
}
}
}
}
}
foreach (string assembly in Assemblies)
{
project.AddItem("Reference", assembly);
}
project.Save(this.ProjectFilePath);
FileLogger logger = new FileLogger();
logger.Parameters = "logfile=" + this.BuildLogPath;
this.BuildReturnedCode = false;
// According to MSDN, http://msdn.microsoft.com/en-us/library/microsoft.build.evaluation.projectcollection.aspx
// multiple project collections can exist within an app domain. However, these must not build concurrently.
// Therefore, we need a static lock to prevent multiple threads from accessing this call.
lock (_syncObject)
{
this.BuildReturnedCode = project.Build(logger);
}
logger.Shutdown();
// If compilation succeeded, delete the project files.
//
if (this.BuildReturnedCode)
{
string generatedAssemblyPath = Path.Combine(this.ProjectFolderPath, @"obj\Release\" + this.ProjectName + ".dll");
if (File.Exists(generatedAssemblyPath))
{
File.Move(generatedAssemblyPath, this.AssemblyPath);
}
try
{
System.IO.Directory.Delete(this.ProjectFolderPath, true);
}
catch (Exception e)
{
Tracer.TraceException(e);
// Ignoring the exceptions from Delete of temp directory.
}
}
}
#endif
}
static object _syncObject = new object();
/// <summary>
/// Return true/false to indicate whether the processor architecture is ARM
/// </summary>
/// <returns></returns>
internal static bool IsRunningOnProcessorArchitectureARM()
{
// Important:
// this function has a clone in SMA in admin\monad\src\utils\PsUtils.cs
// if you are making any changes specific to this function then update the clone as well.
NativeMethods.SYSTEM_INFO sysInfo = new NativeMethods.SYSTEM_INFO();
NativeMethods.GetSystemInfo(ref sysInfo);
return sysInfo.wProcessorArchitecture == NativeMethods.PROCESSOR_ARCHITECTURE_ARM;
}
private static class NativeMethods
{
// Important:
// this clone has a clone in SMA in admin\monad\src\utils\PsUtils.cs
// if you are making any changes specific to this class then update the clone as well.
internal const ushort PROCESSOR_ARCHITECTURE_INTEL = 0;
internal const ushort PROCESSOR_ARCHITECTURE_ARM = 5;
internal const ushort PROCESSOR_ARCHITECTURE_IA64 = 6;
internal const ushort PROCESSOR_ARCHITECTURE_AMD64 = 9;
internal const ushort PROCESSOR_ARCHITECTURE_UNKNOWN = 0xFFFF;
[StructLayout(LayoutKind.Sequential)]
internal struct SYSTEM_INFO
{
public ushort wProcessorArchitecture;
public ushort wReserved;
public uint dwPageSize;
public IntPtr lpMinimumApplicationAddress;
public IntPtr lpMaximumApplicationAddress;
public UIntPtr dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public ushort wProcessorLevel;
public ushort wProcessorRevision;
};
[DllImport("kernel32.dll")]
internal static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);
}
}
}
@@ -1,126 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.CodeAnalysis;
/// <summary>
/// Possible states of workflow instance.
/// </summary>
internal enum WorkflowInstanceState
{
/// <summary>
/// Not initialized with any workflow yet.
/// </summary>
NotStarted = 0,
/// <summary>
/// Workflow execution is loaded but not yet started.
/// </summary>
Loaded = 1,
/// <summary>
/// Workflow is currently executing.
/// </summary>
Executing = 2,
/// <summary>
/// Workflow execution is completed.
/// </summary>
CompletedAndClosed = 3,
/// <summary>
/// Faulted state, once the workflow execution is completed.
/// </summary>
Faulted = 4,
/// <summary>
/// Canceled state, once the workflow execution is completed.
/// </summary>
Canceled = 5,
/// <summary>
/// Aborted state, once the workflow execution is completed.
/// </summary>
Aborted = 6,
/// <summary>
/// Un-handled exception and termination state, once the workflow execution is completed.
/// </summary>
UnhandledExceptionAndTermination = 7,
/// <summary>
/// Workflow is currently unloaded.
/// </summary>
Unloaded = 8,
/// <summary>
/// Workflow is currently unknown.
/// </summary>
Unknown = 9,
};
/// <summary>
/// Provides an event definition for the status of a workflow.
/// </summary>
internal class WorkflowStatusEventArgs : EventArgs
{
/// <summary>
/// The instance id.
/// </summary>
private Guid id;
/// <summary>
/// The workflow instance state.
/// </summary>
private WorkflowInstanceState state;
/// <summary>
/// The workflow unhandled exception.
/// </summary>
private Exception unhandledException;
/// <summary>
/// Constructor with instance id and state.
/// </summary>
/// <param name="id">The workflow Id.</param>
/// <param name="state">The state of workflow</param>
/// <param name="unhandledException">The unhandled exception, occurs when streams are closed.</param>
internal WorkflowStatusEventArgs(Guid id, WorkflowInstanceState state, Exception unhandledException)
{
this.id = id;
this.state = state;
this.unhandledException = unhandledException;
}
/// <summary>
/// Gets instance id.
/// </summary>
internal Guid Id
{
get { return this.id; }
}
/// <summary>
/// Gets instance state.
/// </summary>
internal WorkflowInstanceState State
{
get { return this.state; }
}
/// <summary>
/// Gets unhandled exception.
/// </summary>
internal Exception UnhandledException
{
get { return this.unhandledException; }
}
}
}
@@ -1,484 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System.Diagnostics;
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;
using System.Activities;
using System.Timers;
using System.Management.Automation.Tracing;
using System.Collections;
using System.Runtime.Serialization;
/// <summary>
/// Workflow timer types.
/// </summary>
internal enum WorkflowTimerType
{
RunningTimer = 1,
ElapsedTimer = 2,
}
internal delegate void WorkflowTimerElapsedHandler(PSTimer sender, ElapsedEventArgs e);
internal sealed class PSTimer : IDisposable
{
private bool disposed;
private Timer timer;
private readonly object syncLock = new object();
internal WorkflowTimerType TimerType { get; private set; }
private bool IsRecurring;
private bool IsOneTimeTimer;
private TimeSpan Interval;
private TimeSpan RemainingTime;
private DateTime? StartedAtForFirstTime;
private DateTime? StartedTime;
private bool IsRunning;
internal bool TimerReachedAlready = false;
private event WorkflowTimerElapsedHandler Handler;
internal PSTimer(WorkflowTimerType type, bool isRecurring, bool isOneTimeTimer, TimeSpan interval, WorkflowTimerElapsedHandler handler)
{
Debug.Assert(!(isRecurring == true && isOneTimeTimer == true), "Timer cannot be recurring and one-time-timer at the same time.");
this.TimerType = type;
this.IsRecurring = isRecurring;
this.IsOneTimeTimer = isOneTimeTimer;
this.Interval = interval;
this.RemainingTime = interval;
this.StartedAtForFirstTime = null;
this.StartedTime = null;
this.IsRunning = false;
this.Handler = handler;
}
internal PSTimer(Dictionary<string, object> data, WorkflowTimerElapsedHandler handler)
{
this.TimerType = (WorkflowTimerType)data["TimerType"];
this.IsRecurring = (bool)data["IsRecurring"];
this.IsOneTimeTimer = (bool)data["IsOneTimeTimer"];
this.Interval = (TimeSpan)data["Interval"];
if (IsRecurring == false && IsOneTimeTimer == false)
{
this.RemainingTime = (TimeSpan)data["RemainingTime"];
}
else if (IsRecurring == false && IsOneTimeTimer == true)
{
DateTime tmpStartedAtForFirstTime = (DateTime)data["StartedAtForFirstTime"];
TimeSpan diff = Interval - DateTime.UtcNow.Subtract(tmpStartedAtForFirstTime);
if (diff <= TimeSpan.FromSeconds(0))
{
this.TimerReachedAlready = true;
this.RemainingTime = TimeSpan.FromSeconds(2);
}
else if (diff < TimeSpan.FromSeconds(2))
this.RemainingTime = TimeSpan.FromSeconds(2);
else
this.RemainingTime = diff;
}
else
{
this.RemainingTime = Interval;
}
this.StartedAtForFirstTime = null;
this.StartedTime = null;
this.IsRunning = false;
this.Handler = handler;
}
internal Dictionary<string, object> GetSerializedData()
{
Dictionary<string, object> data = new Dictionary<string, object>();
data.Add("TimerType", TimerType);
data.Add("IsRecurring", IsRecurring);
data.Add("IsOneTimeTimer", IsOneTimeTimer);
data.Add("Interval", Interval);
if (IsRecurring == false && IsOneTimeTimer == false)
{
if (IsRunning)
{
Debug.Assert(StartedTime.HasValue, "Started time should have value.");
TimeSpan tmpRemainingTime = RemainingTime - DateTime.UtcNow.Subtract((DateTime)StartedTime);
if (tmpRemainingTime < TimeSpan.FromMilliseconds(0))
tmpRemainingTime = TimeSpan.FromMilliseconds(0);
data.Add("RemainingTime", tmpRemainingTime);
}
else
{
data.Add("RemainingTime", RemainingTime);
}
}
else if (IsRecurring == false && IsOneTimeTimer == true)
{
// one time timer
if (StartedAtForFirstTime.HasValue)
data.Add("StartedAtForFirstTime", StartedAtForFirstTime);
else
data.Add("StartedAtForFirstTime", DateTime.UtcNow);
}
return data;
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (disposed)
return;
if (!IsRunning)
return;
lock (syncLock)
{
if (!IsRunning)
return;
if (Handler != null)
Handler(this, e);
if (IsRecurring == false)
IsRunning = false;
}
}
internal void Start()
{
if (disposed)
return;
if (IsRunning)
return;
if (Interval <= TimeSpan.FromMilliseconds(0))
return;
lock (syncLock)
{
if (IsRunning)
return;
if (timer == null)
{
timer = new System.Timers.Timer(this.RemainingTime.TotalMilliseconds);
timer.AutoReset = IsRecurring;
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
StartedAtForFirstTime = DateTime.UtcNow;
}
else
{
timer.Interval = this.RemainingTime.TotalMilliseconds;
}
timer.Start();
IsRunning = true;
StartedTime = DateTime.UtcNow;
}
}
internal void Stop()
{
if (disposed)
return;
if (!IsRunning)
return;
lock (syncLock)
{
if (!IsRunning)
return;
if (timer == null)
return;
timer.Stop();
IsRunning = false;
Debug.Assert(StartedTime.HasValue, "Started time should have value.");
if (this.IsRecurring == false)
{
RemainingTime -= DateTime.UtcNow.Subtract((DateTime)StartedTime);
if (RemainingTime < TimeSpan.FromMilliseconds(0))
RemainingTime = TimeSpan.FromMilliseconds(0);
}
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <param name="disposing"></param>
private void Dispose(bool disposing)
{
if (this.disposed || !disposing)
return;
lock (syncLock)
{
if (this.disposed)
return;
Stop();
if (timer != null)
{
timer.Elapsed -= this.timer_Elapsed;
this.Handler = null;
this.timer.Dispose();
}
this.disposed = true;
}
}
}
/// <summary>
/// Define all the workflow related timers.
/// </summary>
public sealed class PSWorkflowTimer : IDisposable
{
private readonly PowerShellTraceSource Tracer = PowerShellTraceSourceFactory.GetTraceSource();
private static readonly Tracer StructuredTracer = new Tracer();
private readonly PSWorkflowInstance _instance;
private bool disposed;
private readonly object syncLock = new object();
private Dictionary<WorkflowTimerType, PSTimer> _timers;
/// <summary>
/// Default Constructor
/// </summary>
internal PSWorkflowTimer(PSWorkflowInstance instance)
{
_instance = instance;
_timers = new Dictionary<WorkflowTimerType, PSTimer>();
}
/// <summary>
/// Creates a workflow timer for a workflow instance based on a BLOB
/// </summary>
/// <param name="instance"></param>
/// <param name="deserializedTimers"></param>
public PSWorkflowTimer(PSWorkflowInstance instance, object deserializedTimers)
{
_instance = instance;
_timers = new Dictionary<WorkflowTimerType, PSTimer>();
if (deserializedTimers == null) throw new ArgumentNullException("deserializedTimers");
List<object> deserializedTimerList = (List<object>)deserializedTimers;
foreach (object data in deserializedTimerList)
{
Debug.Assert(data != null, "Timer data should not have been null.");
if (data != null)
{
Debug.Assert(data is Dictionary<string, object>, "The timer data should be of type Dictionary<string, object>.");
if (data is Dictionary<string, object>)
{
PSTimer timer = new PSTimer((Dictionary<string, object>)data, Timer_WorkflowTimerElapsed);
_timers.Add(timer.TimerType, timer);
}
}
}
}
/// <summary>
/// Retrieves timers as a BLOB
/// </summary>
/// <returns></returns>
public object GetSerializedData()
{
if (disposed)
return null;
List<object> serializedTimers = new List<object>();
foreach (PSTimer timer in _timers.Values)
{
serializedTimers.Add(timer.GetSerializedData());
}
return serializedTimers;
}
internal void SetupTimer(WorkflowTimerType timerType, TimeSpan interval)
{
if (disposed)
return;
if (_timers.ContainsKey(timerType))
return;
if (timerType == WorkflowTimerType.ElapsedTimer)
{
_timers.Add(timerType, new PSTimer(timerType, false, true, interval, Timer_WorkflowTimerElapsed));
}
else if (timerType == WorkflowTimerType.RunningTimer)
{
_timers.Add(timerType, new PSTimer(timerType, false, false, interval, Timer_WorkflowTimerElapsed));
}
}
internal bool CheckIfTimerHasReachedAlready(WorkflowTimerType timerType)
{
if (disposed)
return false;
if (_timers.ContainsKey(timerType) && _timers[WorkflowTimerType.ElapsedTimer].TimerReachedAlready)
return true;
return false;
}
internal void StartTimer(WorkflowTimerType timerType)
{
if (disposed)
return;
if (_timers.ContainsKey(timerType))
{
_timers[timerType].Start();
}
}
internal void StopTimer(WorkflowTimerType timerType)
{
if (disposed)
return;
if (_timers.ContainsKey(timerType))
{
_timers[timerType].Stop();
}
}
private void Timer_WorkflowTimerElapsed(PSTimer sender, ElapsedEventArgs e)
{
if (disposed)
return;
StructuredTracer.Correlate();
Tracer.WriteMessage("PSWorkflowTimer Elapsed: " + sender.TimerType);
if (disposed)
return;
switch (sender.TimerType)
{
case WorkflowTimerType.RunningTimer:
sender.Stop();
TerminateWorkflow(Resources.RunningTimeReached);
break;
case WorkflowTimerType.ElapsedTimer:
sender.Stop();
TerminateAndRemoveWorkflow(Resources.ElapsedTimeReached);
break;
}
}
private readonly object syncElapsedLock = new object();
private bool _elapsedTimerCalled = false;
// Terminate workflow
private void TerminateWorkflow(string reason)
{
if (disposed) return;
if (_elapsedTimerCalled) return;
lock (syncElapsedLock)
{
if (disposed) return;
if (_elapsedTimerCalled) return;
try
{
Debug.Assert(_instance.PSWorkflowJob != null, "PSWorkflowJob should be set before calling terminate workflow");
_instance.PSWorkflowJob.StopJob(true, reason);
}
catch (Exception e)
{
// logging the exception in background thread
Tracer.TraceException(e);
}
}
}
// Terminate and Remove workflow
private void TerminateAndRemoveWorkflow(string reason)
{
_elapsedTimerCalled = true;
if (disposed) return;
lock (syncElapsedLock)
{
if (disposed) return;
try
{
_instance.PSWorkflowJob.StopJob(true, Resources.ElapsedTimeReached);
}
catch (Exception e)
{
// logging the exception in background thread
Tracer.TraceException(e);
}
}
}
/// <summary>
/// Dispose implementation.
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Protected virtual implementation of Dispose.
/// </summary>
/// <param name="disposing"></param>
private void Dispose(bool disposing)
{
if (this.disposed || !disposing)
return;
lock (syncLock)
{
if (this.disposed)
return;
foreach (PSTimer wt in _timers.Values)
{
wt.Dispose();
}
_timers.Clear();
this.disposed = true;
}
}
}
}
@@ -1,204 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Activities;
using System.Activities.Statements;
using System.Activities.Validation;
using System.Collections.Generic;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Management.Automation.Tracing;
using Microsoft.PowerShell.Activities;
using System.Activities.Tracking;
using System.Text;
/// <summary>
/// Contains members that allow the addition of custom extension to
/// the PowerShell workflow engine.
/// </summary>
public static class PSWorkflowExtensions
{
/// <summary>
/// The custom workflow extensions delegate to use in this engine
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
"CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "This is needed for providing custom powershell extensions dynamically.")]
static public Func<IEnumerable<object>> CustomHandler { get; set; }
}
/// <summary>
/// Implementing the workflow tracking participant, this will established with communication between activities and hosting
/// engine to perform additional task like persistence and logging etc.
/// </summary>
internal class PSWorkflowTrackingParticipant : TrackingParticipant
{
private readonly PowerShellTraceSource Tracer = PowerShellTraceSourceFactory.GetTraceSource();
private readonly Tracer _structuredTracer = new Tracer();
private const String participantName = "WorkflowTrackingParticipant";
private PSWorkflowDebugger _debugger;
private const string debugBreakActivity = "PowerShellValue<Object>";
/// <summary>
/// Default constructor.
/// </summary>
internal PSWorkflowTrackingParticipant()
{
Tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, "{0} Created", participantName));
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="debugger">PSWorkflowDebugger</param>
internal PSWorkflowTrackingParticipant(PSWorkflowDebugger debugger)
{
_debugger = debugger;
Tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, "{0} Created", participantName));
}
/// <summary>
/// Retrieve each type of tracking record and perform the corresponding functionality.
/// </summary>
/// <param name="record">Represents the tracking record.</param>
/// <param name="timeout">Time out for the tracking to be completed.</param>
protected override void Track(TrackingRecord record, TimeSpan timeout)
{
Tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, "{0} Emitted trackRecord: {1} Level: {2}, RecordNumber: {3}", participantName, record.GetType().FullName, record.Level, record.RecordNumber));
WorkflowInstanceRecord workflowInstanceRecord = record as WorkflowInstanceRecord;
if (workflowInstanceRecord != null)
{
if (_structuredTracer.IsEnabled)
{
if (string.Equals(WorkflowInstanceStates.Persisted, workflowInstanceRecord.State, StringComparison.OrdinalIgnoreCase))
{
_structuredTracer.WorkflowPersisted(workflowInstanceRecord.InstanceId);
}
else if (string.Equals(WorkflowInstanceStates.UnhandledException, workflowInstanceRecord.State, StringComparison.OrdinalIgnoreCase))
{
WorkflowInstanceUnhandledExceptionRecord unhandledRecord = workflowInstanceRecord as WorkflowInstanceUnhandledExceptionRecord;
if (unhandledRecord != null)
{
_structuredTracer.WorkflowActivityExecutionFailed(unhandledRecord.InstanceId,
unhandledRecord.FaultSource != null ? unhandledRecord.FaultSource.Name : unhandledRecord.ActivityDefinitionId,
System.Management.Automation.Tracing.Tracer.GetExceptionString(unhandledRecord.UnhandledException));
}
}
}
this.ProcessWorkflowInstanceRecord(workflowInstanceRecord);
}
ActivityStateRecord activityStateRecord = record as ActivityStateRecord;
if (activityStateRecord != null)
{
if (_structuredTracer.IsEnabled)
{
ActivityInstanceState activityState = ActivityInstanceState.Executing;
if (!string.IsNullOrEmpty(activityStateRecord.State)
&& Enum.TryParse<ActivityInstanceState>(activityStateRecord.State, out activityState))
{
if (activityState == ActivityInstanceState.Executing)
{
_structuredTracer.ActivityExecutionQueued(activityStateRecord.InstanceId, activityStateRecord.Activity.Name);
}
}
}
this.ProcessActivityStateRecord(activityStateRecord);
}
CustomTrackingRecord customTrackingRecord = record as CustomTrackingRecord;
if ((customTrackingRecord != null) && (customTrackingRecord.Data.Count > 0))
{
this.ProcessCustomTrackingRecord(customTrackingRecord);
}
}
/// <summary>
/// Process the workflow instance record.
/// </summary>
/// <param name="record">Record representing workflow instance record.</param>
private void ProcessWorkflowInstanceRecord(WorkflowInstanceRecord record)
{
Tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, " Workflow InstanceID: {0} Workflow instance state: {1}", record.InstanceId, record.State));
}
/// <summary>
/// process the activity state record.
/// </summary>
/// <param name="record">Record representing activity state record.</param>
private void ProcessActivityStateRecord(ActivityStateRecord record)
{
IDictionary<String, object> variables = record.Variables;
StringBuilder vars = new StringBuilder();
if (variables.Count > 0)
{
vars.AppendLine("\n\tVariables:");
foreach (KeyValuePair<string, object> variable in variables)
{
vars.AppendLine(String.Format(CultureInfo.InvariantCulture, "\t\tName: {0} Value: {1}", variable.Key, variable.Value));
}
}
Tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, " :Activity DisplayName: {0} :ActivityInstanceState: {1} {2}", record.Activity.Name, record.State, ((variables.Count > 0) ? vars.ToString() : String.Empty)));
}
/// <summary>
/// Process the custom tracking record. This record will contain the persistence detail.
/// </summary>
/// <param name="record">Record representing custom tracking record.</param>
private void ProcessCustomTrackingRecord(CustomTrackingRecord record)
{
Tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, "\n\tUser Data:"));
if (_debugger != null &&
record.Data != null)
{
// Get breakpoint info if available.
object value;
string bp = null;
if (record.Data.TryGetValue("DebugSequencePoint", out value))
{
bp = value as string;
record.Data.Remove("DebugSequencePoint");
}
// Update debugger variables.
_debugger.UpdateVariables(record.Data);
// Pass breakpoint info to debugger, which will optionally stop WF activity execution here.
if (!string.IsNullOrEmpty(bp))
{
try
{
string[] symbols = bp.Trim('\'', '\"').Split(':');
ActivityPosition debuggerBP = new ActivityPosition(
symbols[2], // WF Name
Convert.ToInt32(symbols[0], CultureInfo.InvariantCulture), // Line number
Convert.ToInt32(symbols[1], CultureInfo.InvariantCulture)); // Col number
// Debugger blocking call if breakpoint hit or debugger stepping is active.
_debugger.DebuggerCheck(debuggerBP);
}
catch (FormatException)
{ }
catch (OverflowException)
{ }
}
}
foreach (string data in record.Data.Keys)
{
Tracer.WriteMessage(String.Format(CultureInfo.InvariantCulture, " \t\t {0} : {1}", data, record.Data[data]));
}
}
}
}
@@ -1,323 +0,0 @@
using System;
using System.Security;
using System.Runtime.InteropServices;
using System.Management.Automation;
using System.Diagnostics;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Remoting;
using System.Management.Automation.Tracing;
namespace Microsoft.PowerShell.Workflow
{
static class WorkflowUtils
{
/// <summary>
/// CompareConnectionUri compares two connection URIs
/// by doing a comparison of elements.
/// </summary>
/// <param name="connectionInfo1">Connection info 1</param>
/// <param name="connectionInfo2">Connection info 2</param>
/// <returns>True if they match else false.</returns>
internal static bool CompareConnectionUri(WSManConnectionInfo connectionInfo1, WSManConnectionInfo connectionInfo2)
{
Debug.Assert(connectionInfo1 != null && connectionInfo2 != null, "Connections should be != null");
Debug.Assert(!string.IsNullOrEmpty(connectionInfo1.Scheme) && !string.IsNullOrEmpty(connectionInfo1.ComputerName)
&& !string.IsNullOrEmpty(connectionInfo1.AppName), "Connection URI elements should be != null or empty");
Debug.Assert(!string.IsNullOrEmpty(connectionInfo2.Scheme) && !string.IsNullOrEmpty(connectionInfo2.ComputerName)
&& !string.IsNullOrEmpty(connectionInfo2.AppName), "Connection URI elements should be != null or empty");
if (String.Compare(connectionInfo2.Scheme, connectionInfo1.Scheme, StringComparison.OrdinalIgnoreCase) != 0)
{
return false;
}
if (String.Compare(connectionInfo2.ComputerName, connectionInfo1.ComputerName, StringComparison.OrdinalIgnoreCase) != 0)
{
return false;
}
if (String.Compare(connectionInfo2.AppName, connectionInfo1.AppName, StringComparison.OrdinalIgnoreCase) != 0)
{
return false;
}
if (connectionInfo2.Port != connectionInfo1.Port)
{
return false;
}
return true;
} // CompareConnectionUri ...
/// <summary>
/// CompareShellUri compares two shell URIs
/// by doing a string of elements.
/// </summary>
/// <param name="shellUri1">Shell Uri 1</param>
/// <param name="shellUri2">Shell Uri 2</param>
/// <returns>True if they match else false.</returns>
internal static bool CompareShellUri(String shellUri1, String shellUri2)
{
Debug.Assert(!string.IsNullOrEmpty(shellUri1) && !string.IsNullOrEmpty(shellUri2), "Shell Uris should be != null or empty");
if (String.Compare(shellUri1, shellUri2, StringComparison.OrdinalIgnoreCase) != 0)
{
return false;
}
return true;
} // CompareShellUri ...
/// <summary>
/// CompareAuthentication compares two authentication mechanisms.
/// </summary>
/// <param name="authentication1">Authentication mechanism 1</param>
/// <param name="authentication2">Authentication mechanism 2</param>
/// <returns>True if they match else false.</returns>
internal static bool CompareAuthentication(AuthenticationMechanism authentication1, AuthenticationMechanism authentication2)
{
return authentication1 == authentication2;
} // CompareAuthentication ...
/// <summary>
/// CompareCredentials compares two PSCredential credentials
/// by doing a username and password comparison .
/// </summary>
/// <param name="credential1">Credential 1</param>
/// <param name="credential2">Credential 2</param>
/// <returns>True if they match else false.</returns>
internal static bool CompareCredential(PSCredential credential1, PSCredential credential2)
{
if (credential1 == null && credential2 == null)
{
return true;
}
// check credentials if present
if (credential1 == null ^ credential2 == null)
{
return false;
}
Debug.Assert(credential1 != null && credential2 != null
&& credential1.UserName != null && credential2.UserName != null, "Credentials should be != null");
// check the username
if (string.Compare(credential1.UserName, credential2.UserName, StringComparison.OrdinalIgnoreCase) != 0)
{
return false;
}
// check the password
if (!WorkflowUtils.ComparePassword(credential1.Password, credential2.Password))
{
return false;
}
return true;
}
/// <summary>
/// ComparePassword uses native functions to perform a string match on two SecureString passwords
/// by doing a strict byte level comparison is done on the two strings.
/// The use of ReadByte allows the function to execute without marking the assembly as unsafe.
/// </summary>
/// <param name="secureString1">Password 1</param>
/// <param name="secureString2">Password 2</param>
/// <returns>True if they match else false.</returns>
internal static bool ComparePassword(SecureString secureString1, SecureString secureString2)
{
if (secureString1 == null && secureString2 == null)
{
return true;
}
if (secureString1 == null ^ secureString2 == null)
{
return false;
}
Debug.Assert(secureString1 != null && secureString2 != null, "SecureStrings should be != null");
if (secureString1.Length != secureString2.Length)
{
return false;
}
IntPtr bstr1 = IntPtr.Zero;
IntPtr bstr2 = IntPtr.Zero;
try
{
bstr1 = Marshal.SecureStringToBSTR(secureString1);
bstr2 = Marshal.SecureStringToBSTR(secureString2);
int offset = 0;
Byte leftHigh, leftLow, rightHigh, rightLow;
bool notDone = true;
do
{
leftLow = Marshal.ReadByte(bstr1, offset + 1);
rightLow = Marshal.ReadByte(bstr2, offset + 1);
leftHigh = Marshal.ReadByte(bstr1, offset);
rightHigh = Marshal.ReadByte(bstr2, offset);
offset += 2;
if (leftLow != rightLow || leftHigh != rightHigh)
{
return false;
}
notDone = leftLow != 0 || leftHigh != 0; // terminator - 2 null characters (0x00)?
leftLow = rightLow = leftHigh = rightHigh = 0;
} while (notDone);
return true;
}
catch (Exception e)
{
using (PowerShellTraceSource tracer = PowerShellTraceSourceFactory.GetTraceSource())
{
// SecureStringToBSTR or ReadByte threw exceptions
tracer.WriteMessage("Getting an exception while comparing credentials...");
tracer.TraceException(e);
return false;
}
}
finally
{
if (IntPtr.Zero != bstr1)
{
Marshal.ZeroFreeBSTR(bstr1);
}
if (IntPtr.Zero != bstr2)
{
Marshal.ZeroFreeBSTR(bstr2);
}
}
} // ComparePassword ...
/// <summary>
/// CompareCertificateThumbprint compares two certificate thumbprints
/// by doing a string comparison.
/// </summary>
/// <param name="certificateThumbprint1">Certificate Thumbprint 1</param>
/// <param name="certificateThumbprint2">Certificate Thumbprint 2</param>
/// <returns>True if they match else false.</returns>
internal static bool CompareCertificateThumbprint(String certificateThumbprint1, String certificateThumbprint2)
{
if (certificateThumbprint1 == null && certificateThumbprint2 == null)
{
return true;
}
if (certificateThumbprint1 == null ^ certificateThumbprint2 == null)
{
return false;
}
Debug.Assert(certificateThumbprint1 != null && certificateThumbprint2 != null, "Certificate thumbprints should be != null");
if (string.Compare(certificateThumbprint1, certificateThumbprint2, StringComparison.OrdinalIgnoreCase) != 0)
{
return false;
}
return true;
} // CompareCertificateThumbprint ...
/// <summary>
/// CompareProxySettings compares the proxy settings for two wsman connections
/// by doing a comparison of elements.
/// </summary>
/// <param name="connectionInfo1">Connection info 1</param>
/// <param name="connectionInfo2">Connection info 2</param>
/// <returns>True if they match else false.</returns>
internal static bool CompareProxySettings(WSManConnectionInfo connectionInfo1, WSManConnectionInfo connectionInfo2)
{
Debug.Assert(connectionInfo1 != null && connectionInfo2 != null, "Connections should be != null");
if (connectionInfo1.ProxyAccessType != connectionInfo2.ProxyAccessType)
{
return false;
}
if (connectionInfo1.ProxyAccessType == ProxyAccessType.None)
{
return true; //stop here if no proxy access type
}
if (connectionInfo1.ProxyAuthentication != connectionInfo2.ProxyAuthentication)
{
return false;
}
// check the proxy credentials password
if (!WorkflowUtils.CompareCredential(connectionInfo1.ProxyCredential, connectionInfo2.ProxyCredential))
{
return false;
}
return true;
} // CompareProxySettings ...
/// <summary>
/// CompareOtherWSManSettings compares the rest of the wsman settings for two wsman connections
/// by doing a comparison of elements.
/// </summary>
/// <param name="connectionInfo1">Connection info 1</param>
/// <param name="connectionInfo2">Connection info 2</param>
/// <returns>True if they match else false.</returns>
internal static bool CompareOtherWSManSettings(WSManConnectionInfo connectionInfo1, WSManConnectionInfo connectionInfo2)
{
Debug.Assert(connectionInfo1 != null && connectionInfo2 != null, "Connections should be != null");
if (connectionInfo1.SkipCACheck != connectionInfo2.SkipCACheck)
{
return false;
}
if (connectionInfo1.SkipCNCheck != connectionInfo2.SkipCNCheck)
{
return false;
}
if (connectionInfo1.SkipRevocationCheck != connectionInfo2.SkipRevocationCheck)
{
return false;
}
if (connectionInfo1.UseCompression != connectionInfo2.UseCompression)
{
return false;
}
if (connectionInfo1.UseUTF16 != connectionInfo2.UseUTF16)
{
return false;
}
if (connectionInfo1.MaximumConnectionRedirectionCount != connectionInfo2.MaximumConnectionRedirectionCount)
{
return false;
}
if (connectionInfo1.MaximumReceivedDataSizePerCommand != connectionInfo2.MaximumReceivedDataSizePerCommand)
{
return false;
}
if (connectionInfo1.MaximumReceivedObjectSize != connectionInfo2.MaximumReceivedObjectSize)
{
return false;
}
if (connectionInfo1.NoEncryption != connectionInfo2.NoEncryption)
{
return false;
}
if (connectionInfo1.NoMachineProfile != connectionInfo2.NoMachineProfile)
{
return false;
}
if (connectionInfo1.OutputBufferingMode != connectionInfo2.OutputBufferingMode)
{
return false;
}
return true;
} // CompareOtherWSManSettings ...
} // WorkflowUtils ...
}
@@ -1,401 +0,0 @@
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System.Diagnostics;
namespace Microsoft.PowerShell.Workflow
{
using System;
using System.Activities;
using System.Activities.Statements;
using System.Activities.Validation;
using System.Collections.Generic;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Management.Automation.Tracing;
using Microsoft.PowerShell.Activities;
using System.Management.Automation;
using System.Collections.Concurrent;
using System.Reflection;
/// <summary>
/// Contains members that allow for controlling the PowerShell workflow
/// engine validation mechanism.
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces")]
public static class Validation
{
/// <summary>
/// The custom validator delegate to use in this engine
/// </summary>
static public Func<Activity, bool> CustomHandler { get; set; }
}
internal class PSWorkflowValidationResults
{
internal PSWorkflowValidationResults()
{
this.IsWorkflowSuspendable = false;
this.Results = null;
}
internal bool IsWorkflowSuspendable { get; set; }
internal ValidationResults Results { get; set; }
}
/// <summary>
/// Validate all the activities in the workflow to check if they are allowed or not.
/// </summary>
public class PSWorkflowValidator
{
#region Privates
private static readonly string Facility = "WorkflowValidation : ";
private static readonly PowerShellTraceSource Tracer = PowerShellTraceSourceFactory.GetTraceSource();
private static readonly Tracer _structuredTracer = new Tracer();
private readonly ConcurrentDictionary<Guid, PSWorkflowValidationResults> _validationCache = new ConcurrentDictionary<Guid, PSWorkflowValidationResults>();
private static readonly List<string> MandatorySystemActivities = new List<string> { "SuspendOnError" };
private static readonly List<string> AllowedSystemActivities = new List<string>
{
"DynamicActivity",
"DoWhile",
"ForEach`1",
"If",
"Parallel",
"ParallelForEach`1",
"Sequence",
"Switch`1",
"While",
"Assign",
"Assign`1",
"Delay",
"InvokeMethod",
"TerminateWorkflow",
"WriteLine",
"Rethrow",
"Throw",
"TryCatch",
"Literal`1",
"VisualBasicValue`1",
"VisualBasicReference`1",
"LocationReferenceValue`1",
"VariableValue`1",
"VariableReference`1",
"LocationReferenceReference`1",
"LambdaValue`1",
"Flowchart",
"FlowDecision",
"FlowSwitch`1",
"AddToCollection`1",
"ExistsInCollection`1",
"RemoveFromCollection`1",
"ClearCollection`1",
};
private static HashSet<string> PowerShellActivitiesAssemblies = new HashSet<string>() {
"microsoft.powershell.activities",
"microsoft.powershell.core.activities",
"microsoft.powershell.diagnostics.activities",
"microsoft.powershell.management.activities",
"microsoft.powershell.security.activities",
"microsoft.powershell.utility.activities",
"microsoft.powershell.workflow.servicecore",
"microsoft.wsman.management.activities",
};
private void ValidateWorkflowInternal(Activity workflow, string runtimeAssembly, PSWorkflowValidationResults validationResults)
{
Tracer.WriteMessage(Facility + "Validating a workflow.");
_structuredTracer.WorkflowValidationStarted(Guid.Empty);
ValidationSettings validationSettings = new ValidationSettings
{
AdditionalConstraints =
{
{ typeof(Activity), new List<Constraint> { ValidateActivitiesConstraint(runtimeAssembly, validationResults)} }
}
};
try
{
validationResults.Results = ActivityValidationServices.Validate(workflow, validationSettings);
}
catch (Exception e)
{
Tracer.TraceException(e);
ValidationException exception = new ValidationException(Resources.ErrorWhileValidatingWorkflow, e);
throw exception;
}
_structuredTracer.WorkflowValidationFinished(Guid.Empty);
}
private Constraint ValidateActivitiesConstraint(string runtimeAssembly, PSWorkflowValidationResults validationResults)
{
DelegateInArgument<Activity> activityToValidate = new DelegateInArgument<Activity>();
DelegateInArgument<ValidationContext> validationContext = new DelegateInArgument<ValidationContext>();
return new Constraint<Activity>
{
Body = new ActivityAction<Activity, ValidationContext>
{
Argument1 = activityToValidate,
Argument2 = validationContext,
Handler = new AssertValidation
{
IsWarning = false,
Assertion = new InArgument<bool>(
env => ValidateActivity(activityToValidate.Get(env), runtimeAssembly, validationResults)),
Message = new InArgument<string>(
env => string.Format(CultureInfo.CurrentCulture, Resources.InvalidActivity, activityToValidate.Get(env).GetType().FullName))
}
}
};
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "It is called by another private method 'ValidateActivitiesConstraint'")]
private bool ValidateActivity(Activity activity, string runtimeAssembly, PSWorkflowValidationResults validationResult)
{
if (validationResult != null && validationResult.IsWorkflowSuspendable == false)
{
validationResult.IsWorkflowSuspendable = CheckIfSuspendable(activity);
}
bool allowed = false;
Type activityType = activity.GetType();
// If there is a custom validator activity, then call it. If it returns true
// then just return the activity.
if (Validation.CustomHandler != null && Validation.CustomHandler.Invoke(activity))
{
allowed = true;
}
else if (MandatorySystemActivities.Contains(activityType.Name))
{
allowed = true;
}
else if (string.Equals(activityType.Assembly.FullName, "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", StringComparison.OrdinalIgnoreCase))
{
allowed = AllowedSystemActivities.Contains(activityType.Name);
}
else if (string.Equals(runtimeAssembly, activityType.Assembly.GetName().Name, StringComparison.OrdinalIgnoreCase))
{
// Allow the activities which belong to runtime assembly containing dependent Xamls.
allowed = true;
}
else if (Configuration.PSDefaultActivitiesAreAllowed
&& PowerShellActivitiesAssemblies.Contains(activityType.Assembly.GetName().Name.ToLowerInvariant()))
{
// Allow any of the activities from our product assemblies provided that product activities were
// specified as allowed activities
allowed = true;
}
else
{
// Check if the activityId matches any activity in the allowed list
// as a full name or as pattern.
foreach (string allowedActivity in Configuration.AllowedActivity ?? new string[0])
{
// skipping * because it has already been checked above
if (string.Equals(allowedActivity, PSWorkflowConfigurationProvider.PSDefaultActivities, StringComparison.OrdinalIgnoreCase))
continue;
if (activity is System.Activities.Activity)
{
if (false
|| IsMatched(allowedActivity, activityType.Name)
|| IsMatched(allowedActivity, activityType.FullName)
|| IsMatched(allowedActivity, activityType.Assembly.GetName().Name + "\\" + activityType.Name)
|| IsMatched(allowedActivity, activityType.Assembly.GetName().Name + "\\" + activityType.FullName)
|| IsMatched(allowedActivity, activityType.Assembly.GetName().FullName + "\\" + activityType.Name)
|| IsMatched(allowedActivity, activityType.Assembly.GetName().FullName + "\\" + activityType.FullName))
{
allowed = true;
break;
}
}
}
}
string displayName = activity.DisplayName;
if (string.IsNullOrEmpty(displayName))
displayName = this.GetType().Name;
if (allowed)
{
_structuredTracer.WorkflowActivityValidated(Guid.Empty, displayName, activityType.FullName);
}
else
{
_structuredTracer.WorkflowActivityValidationFailed(Guid.Empty, displayName, activityType.FullName);
}
return allowed;
}
private bool CheckIfSuspendable(Activity activity)
{
if (string.Equals(activity.GetType().ToString(), "Microsoft.PowerShell.Activities.PSPersist", StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (string.Equals(activity.GetType().ToString(), "Microsoft.PowerShell.Activities.Suspend", StringComparison.OrdinalIgnoreCase))
{
return true;
}
PSActivity psactivity = activity as PSActivity;
if (psactivity != null && psactivity.PSPersist != null && psactivity.PSPersist.Expression != null)
{
return true;
}
Sequence seqActivity = activity as Sequence;
if (seqActivity != null && seqActivity.Variables != null && seqActivity.Variables.Count > 0)
{
foreach (Variable var in seqActivity.Variables)
{
if (string.Equals(var.Name, WorkflowPreferenceVariables.PSPersistPreference, StringComparison.OrdinalIgnoreCase))
return true;
}
}
Parallel parActivity = activity as Parallel;
if (parActivity != null && parActivity.Variables != null && parActivity.Variables.Count > 0)
{
foreach (Variable var in parActivity.Variables)
{
if (string.Equals(var.Name, WorkflowPreferenceVariables.PSPersistPreference, StringComparison.OrdinalIgnoreCase))
return true;
}
}
return false;
}
private static bool IsMatched(string allowedActivity, string match)
{
return (WildcardPattern.ContainsWildcardCharacters(allowedActivity)
? new WildcardPattern(allowedActivity, WildcardOptions.IgnoreCase).IsMatch(match)
: string.Equals(allowedActivity, match, StringComparison.OrdinalIgnoreCase));
}
#endregion Privates
#region Public methods
/// <summary>
/// PSWorkflowValidator
/// </summary>
/// <param name="configuration"></param>
public PSWorkflowValidator(PSWorkflowConfigurationProvider configuration)
{
if (configuration == null)
throw new ArgumentNullException("configuration");
if (TestMode)
{
System.Threading.Interlocked.Increment(ref ObjectCounter);
}
this.Configuration = configuration;
}
/// <summary>
/// Validate the workflow, if it is using the allowed activities.
/// </summary>
/// <param name="workflow">The workflow, which needs to be validated.</param>
/// <param name="runtimeAssembly">The additional runtime assembly, which is needed in validation process.</param>
public ValidationResults ValidateWorkflow(Activity workflow, string runtimeAssembly)
{
PSWorkflowValidationResults validationResults = new PSWorkflowValidationResults();
ValidateWorkflowInternal(workflow, runtimeAssembly, validationResults);
return validationResults.Results;
}
#endregion Public methods
#region Internal Accessors
internal PSWorkflowConfigurationProvider Configuration
{
get;
private set;
}
internal PSWorkflowValidationResults ValidateWorkflow(Guid referenceId, Activity workflow, string runtimeAssembly)
{
PSWorkflowValidationResults validationResults = null;
if (_validationCache.ContainsKey(referenceId))
{
_validationCache.TryGetValue(referenceId, out validationResults);
}
else
{
validationResults = new PSWorkflowValidationResults();
this.ValidateWorkflowInternal(workflow, runtimeAssembly, validationResults);
// sanity check to ensure cache isn't growing unbounded
if (_validationCache.Keys.Count == Configuration.ValidationCacheLimit)
{
_validationCache.Clear();
}
_validationCache.TryAdd(referenceId, validationResults);
}
return validationResults;
}
internal void ProcessValidationResults(ValidationResults results)
{
if (results == null)
throw new ArgumentNullException("results");
if (results.Errors != null && results.Errors.Count == 0)
return;
string errorMessage = string.Empty;
foreach (ValidationError error in results.Errors)
{
errorMessage += error.Message;
errorMessage += "\n";
}
ValidationException exception = new ValidationException(errorMessage);
Tracer.TraceException(exception);
_structuredTracer.WorkflowValidationError(Guid.Empty);
throw exception;
}
#endregion Internal Accessors
# region Test Only Variables & Accessors
// For testing purpose ONLY
internal static bool TestMode = false;
// For testing purpose ONLY
internal static long ObjectCounter = 0;
internal bool IsActivityAllowed(Activity activity, string runtimeAssembly)
{
return ValidateActivity(activity, runtimeAssembly, null);
}
# endregion Test Only Variables & Accessors
}
}
@@ -1,429 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="https://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ActivityNotCached" xml:space="preserve">
<value>The workflow cannot be started because the compiled activity for the workflow was not found. Cache the workflow definition by calling DefinitionCache.Instance.Add.</value>
<comment>DefinitionCache.Instance.Add should not be localized. It is the name of the method.</comment>
</data>
<data name="ActivityNotFound" xml:space="preserve">
<value>Could not find an activity for the command name '{0}'.</value>
</data>
<data name="AsyncResultAlreadyCompleted" xml:space="preserve">
<value>The async result is already finished. A finished operation cannot be called twice.</value>
</data>
<data name="AsyncResultAlreadyEnded" xml:space="preserve">
<value>An End operation has already been called for this async result.</value>
</data>
<data name="AsyncResultNotValid" xml:space="preserve">
<value>The IAsyncResult specified is not valid.</value>
<comment>IAsynResult should not be localized. This is a type.</comment>
</data>
<data name="DuplicateInstanceId" xml:space="preserve">
<value>A duplicate instance ID was found. The instance ID already exists.</value>
</data>
<data name="InstanceOwnerIdMismatch" xml:space="preserve">
<value>The OwnerId of the instance is mismatched.</value>
</data>
<data name="InstanceVersionMismatch" xml:space="preserve">
<value>The Version of the instance is mismatched.</value>
</data>
<data name="InvalidActivity" xml:space="preserve">
<value>The activity is not valid: {0}</value>
</data>
<data name="InvalidAsyncResult" xml:space="preserve">
<value>The async result from the file provider is not valid.</value>
</data>
<data name="InvalidWorkflowExtension" xml:space="preserve">
<value>Workflow files must have a file name extension of .xaml or .dll, not {0}. If you are using a workflow with a file name extension of .dll, then you must pass only one assembly.</value>
</data>
<data name="JobCannotBeStarted" xml:space="preserve">
<value>The job cannot be started. The job state must be NotStarted and the job can only be started once.</value>
</data>
<data name="JobNotFound" xml:space="preserve">
<value>The job could not be removed because a job matching the specified criteria could not be found.</value>
</data>
<data name="NameNotSpecifiedForParam" xml:space="preserve">
<value>A parameter element specified in the configuration does not have a Name attribute. </value>
</data>
<data name="NewJobDefinitionNull" xml:space="preserve">
<value>The workflow job could not be created because the JobInvocationInfo does not contain a JobDefinition. Initialize the JobInvocationInfo with a JobDefinition to create a workflow job.</value>
<comment>JobInvocationInfo and JobDefinition should not be localized. These are types.</comment>
</data>
<data name="NewJobWrongType" xml:space="preserve">
<value>The workflow job could not be created because the JobInvocationInfo specifies a type other than WorkflowJobSourceAdapter. Correct the JobSourceAdapter type or verify that the correct type is being used.</value>
<comment>JobInvocationInfo, WorkflowJobSourceAdapter and JobSourceAdapter should not be localized. These are types.</comment>
</data>
<data name="NoMatchingWorkflowWasFound" xml:space="preserve">
<value>No workflows were found in the specified path '{0}'.</value>
</data>
<data name="NoWorkflowInstance" xml:space="preserve">
<value>A workflow instance does not exist for the specified Instance ID.</value>
</data>
<data name="NoWorkflowProvided" xml:space="preserve">
<value>Null or empty workflow is provided.</value>
</data>
<data name="ParamSpecifiedMoreThanOnce" xml:space="preserve">
<value>Parameter {0} has been specified more than once. Remove multiple references to this parameter from the session configuration, and then try again.</value>
<comment>{0} should not be localized. It is the name of a parameter</comment>
</data>
<data name="UninitializedSpecification" xml:space="preserve">
<value>The workflow job could not be created because the JobInvocationInfo was not properly initialized. Initialize the JobInvocationInfo with workflow information.</value>
<comment>JobInvocationInfo should not be localized. This is a type</comment>
</data>
<data name="ValueNotSpecifiedForParam" xml:space="preserve">
<value>A parameter element specified in the configuration does not have a Value attribute. </value>
<comment>Value should not be localized. This is an attribute.</comment>
</data>
<data name="WorkflowAlreadyLoaded" xml:space="preserve">
<value>This workflow is already loaded.</value>
</data>
<data name="WorkflowInstanceStateCorrupted" xml:space="preserve">
<value>The workflow instance state file does not exist.</value>
</data>
<data name="WorkflowInstanceIncompletelyPersisted" xml:space="preserve">
<value>The workflow job cannot be resumed, either because persistence data could not be saved completely, or saved persistence data has been corrupted. You must restart the workflow.</value>
</data>
<data name="WorkflowNotExecuting" xml:space="preserve">
<value>The workflow is not running. The current state of the workflow instance is {0}.</value>
</data>
<data name="WorkflowNotLoaded" xml:space="preserve">
<value>The workflow instance is not yet loaded.</value>
</data>
<data name="InvalidAsyncResultSpecified" xml:space="preserve">
<value>The specified IAsyncResultObject is not valid.</value>
<comment>IAsyncResult should not be localized. This is a type.</comment>
</data>
<data name="InvalidRunspaceSpecified" xml:space="preserve">
<value>The specified runspace is not valid.</value>
</data>
<data name="WorkflowChildCouldNotBeRemoved" xml:space="preserve">
<value>One or more workflows that are part of the specified job could not be removed.</value>
</data>
<data name="CannotRemoveWorkflowJobDirectly" xml:space="preserve">
<value>Cannot remove the PSWorkflowJob without removing its parent. Please remove the ContainerParentJob that contains this PSWorkflowJob.</value>
<comment>PSWorkflowJob and ContainerParentJob should not be localized. These are types.</comment>
</data>
<data name="ShutdownAbort" xml:space="preserve">
<value>Shutdown request is in progress, workflow is suspending.</value>
</data>
<data name="ParallelScriptBlockSyntax" xml:space="preserve">
<value>The syntax of a parallel script block is 'Parallel { &lt;commands&gt; }'</value>
<comment>"Parallel" should not be localized. This is syntax.</comment>
</data>
<data name="SuspendNotValidState" xml:space="preserve">
<value>Suspend could not be completed.</value>
</data>
<data name="UnblockNotSupported" xml:space="preserve">
<value>Unblock is not a supported operation on a PSWorkflowJob.</value>
<comment>PSWorkflowJob should not be localized. This is a type.</comment>
</data>
<data name="ExitReason" xml:space="preserve">
<value>Workflow complete.</value>
</data>
<data name="RemovingWorkflowInstance" xml:space="preserve">
<value>Removing workflow instance from the table.</value>
</data>
<data name="ElapsedTimeReached" xml:space="preserve">
<value>An elapsed time-out occurred, and the workflow was stopped.</value>
</data>
<data name="RunningTimeReached" xml:space="preserve">
<value>Because a running time-out has occurred, the workflow has been stopped.</value>
</data>
<data name="ResumeNotValidState" xml:space="preserve">
<value>The workflow could not be resumed.</value>
</data>
<data name="ImportingWorkflowFrom" xml:space="preserve">
<value>Importing workflow from file '{0}'.</value>
</data>
<data name="OnlyOneDefaultParameterCollectionAllowed" xml:space="preserve">
<value>The argument to -PSParameterCollection can only contain one entry where PSComputerName is set to '*'. Remove the extra entries and try again.</value>
<comment>PSParameterCollection and PSComputerName should not be localized. These are parameter names.</comment>
</data>
<data name="UnableToStartWorkflow" xml:space="preserve">
<value>The workflow '{0}' could not be started: {1}</value>
</data>
<data name="PersistenceSizeReached" xml:space="preserve">
<value>The Persistence store has reached its maximum size. Free up storage space by removing completed jobs.</value>
</data>
<data name="ProvidedValueIsOutOfRange" xml:space="preserve">
<value>Value {0} is out of the allowed range. Allowed range is from {1} to {2}.</value>
</data>
<data name="ObjectWasCreatedAtNotAllowedLocation" xml:space="preserve">
<value>"Internal Error: The object is marked for restricted construction, but another type is constructing it elsewhere.
Target Type:{0}
Allowed Creator Type: {1}
Actual Creator Type: {2}
Method: {3}</value>
</data>
<data name="SuspendedJobRecoveredFromPreviousSession" xml:space="preserve">
<value>This PSWorkflowJob was recovered from another session in a suspended state. This can indicate that the workflow was interrupted by a process failure, or a system restart. Run Resume-Job to try resuming the workflow.</value>
<comment>PSWorkflowJob and Resume-Job should not be localized. These are a type and a cmdlet name.</comment>
</data>
<data name="ErrorWhileValidatingWorkflow" xml:space="preserve">
<value>An exception has occurred while validating the workflow.</value>
</data>
<data name="AsJobAndJobNameNotAllowed" xml:space="preserve">
<value>The argument to -PSParameterCollection can not contain AsJob, JobName, InputObject or PSParameterCollection as entries. Remove the extra entries and try again.</value>
<comment>PSParameterCollection, AsJob, JobName, InputObject should not be localized. These are the names of parameters.</comment>
</data>
<data name="ActivityParameterGroup" xml:space="preserve">
<value>Activity-Specific Parameters</value>
</data>
<data name="CannotSupplyUriAndComputername" xml:space="preserve">
<value>Cannot supply both connection URI and computer name.</value>
</data>
<data name="ConnectivityGroup" xml:space="preserve">
<value>Connectivity</value>
</data>
<data name="DependModuleImportFailed" xml:space="preserve">
<value>The activity cannot continue running because an error occurred while importing dependent module(s) '{0}' specified for activity '{1}'. To fix this problem, verify that the module exists on the computer. If the module is not required, remove references to the module from the activity.</value>
</data>
<data name="PersistencePathToolLong" xml:space="preserve">
<value>The value of the PersistencePath parameter {0} exceeds the maximum allowed length. The persistence path should not be greater than {1} characters.</value>
</data>
<data name="InputAndOutputGroup" xml:space="preserve">
<value>Input and Output</value>
</data>
<data name="ProgressPositionMessage" xml:space="preserve">
<value> {0} line:{1} char:{2}</value>
</data>
<data name="CompilationErrorWhileBuildingWorkflows" xml:space="preserve">
<value>Compilation error while building dependent workflows. For details see {0}.</value>
</data>
<data name="OneComputerNameAllowed" xml:space="preserve">
<value>Only one computer name is allowed.</value>
</data>
<data name="JobSuspensionInProgress" xml:space="preserve">
<value>Suspend operation is in progress.</value>
</data>
<data name="JobStopInProgress" xml:space="preserve">
<value>Stop operation is in progress.</value>
</data>
<data name="CustomRemotingNotSupported" xml:space="preserve">
<value>This activity does not support custom remote management.</value>
</data>
<data name="ForceSuspendTimeout" xml:space="preserve">
<value>The force-suspend time-out period cannot be zero or null. Specify a time-out period that is greater than zero.</value>
</data>
<data name="ParameterCollectionOnlyUsedWithAsJobAndJobName" xml:space="preserve">
<value>The PSParameterCollection parameter can only be used with AsJob, JobName and InputObject. Move the additional parameters to within the PSParameterCollection argument and try again.</value>
<comment>PSParameterCollection, AsJob, JobName, InputObject should not be localized. These are parameter names.</comment>
</data>
<data name="ErrorWhileExecutingActivityAction" xml:space="preserve">
<value>An error occurred while trying to run the activity.</value>
</data>
<data name="RunningTimeExceeded" xml:space="preserve">
<value>The activity has exceeded the specified maximum running time of {0} seconds.</value>
</data>
<data name="InvalidLabel" xml:space="preserve">
<value>The label is not valid: The label '{0}' doesn't exist.</value>
</data>
<data name="ActivityFailedDueToRunspaceDisconnect" xml:space="preserve">
<value>The activity failed because the connection to the remote computer '{0}' was disconnected.</value>
<comment>{0} is a computer name and should not be localized</comment>
</data>
<data name="ValueFromPipelineNotSupported" xml:space="preserve">
<value>Parameters defined for workflow functions do not support ValueFromPipeline. Remove this attribute and import or define the workflow again.</value>
</data>
<data name="InvalidWorkflowDefinitionState" xml:space="preserve">
<value>The workflow definition has been recycled, because the workflow definition cache limit of {0} has been reached. Import the workflow or module again, and then retry the operation.</value>
</data>
<data name="CredentialParameterCannotBeSpecifiedWithNegotiateWithImplicitAuthentication" xml:space="preserve">
<value>A credential cannot be specified when NegotiateWithImplicitCredential is specified as the value of Authentication.</value>
</data>
<data name="CredentialParameterAssignedWithNoComputerName" xml:space="preserve">
<value>The PSCredential parameter is supported only when the PSComputerName or PSConnectionUri parameters are used. The PSCredential parameter has been ignored.</value>
</data>
<data name="CredentialParameterCannotBeSpecifiedWithPSCertificateThumbPrint" xml:space="preserve">
<value>A CertificateThumbprint cannot be specified when Credential is specified.</value>
</data>
<data name="CmdletDoesNotImplementInputObjectProperty" xml:space="preserve">
<value>The '{0}' cmdlet does not implement the InputObject property.</value>
<comment>{0} is a cmdlet name and should not be localized</comment>
</data>
<data name="WorkflowNameInvalid" xml:space="preserve">
<value>The workflow name "{0}" is not a valid workflow. Specify a valid workflow name and then try the command again.</value>
<comment>{0} is the name of the workflow and should not be localized</comment>
</data>
<data name="CompletedString" xml:space="preserve">
<value>Completed</value>
</data>
<data name="FailedString" xml:space="preserve">
<value>Failed</value>
</data>
<data name="RunningString" xml:space="preserve">
<value>Running</value>
</data>
<data name="InvalidImplementationContext" xml:space="preserve">
<value>The specified ActivityImplementationContext is not of type CimActivityImplementationContext.</value>
</data>
<data name="WarningMessageForPersistence" xml:space="preserve">
<value>This workflow job cannot be suspended because there are no checkpoints (also called persistence points) in the workflow. To make the workflow job suspendable, add checkpoints to the workflow.
For more information about how to add checkpoints, see the help topics for Windows PowerShell Workflow.</value>
</data>
<data name="ErrorMessageForPersistence" xml:space="preserve">
<value>The workflow job cannot be suspended because it does not include checkpoints (also called persistence points). To make the workflow suspendable, use the PSPersist parameter of the workflow. To suspend the workflow forcibly, use the Force parameter of the Suspend-Job cmdlet.</value>
</data>
<data name="XamlNotNull" xml:space="preserve">
<value>The provided XAML cannot be null.</value>
</data>
<data name="InvalidBookmark" xml:space="preserve">
<value>The bookmark '{0}' is not valid; it does not exist in the workflow engine.</value>
</data>
<data name="SerializationErrorException" xml:space="preserve">
<value>The input objects cannot be serialized. Serialized data is required to suspend and resume workflows. To resolve the error, verify that the values of all variables and parameters are of types that can be serialized.</value>
</data>
<data name="SerializationWarning" xml:space="preserve">
<value>The input objects cannot be serialized. This might prevent the workflow from being resumed correctly. The serialization error might indicate a problem with the data contract that is defined at the type or attribute level. To resolve the problem, verify that the values of all variables and parameters can be serialized. Serialization error is: {0}.</value>
</data>
<data name="JobQueuedForResume" xml:space="preserve">
<value>The job has been added to the queue to be resumed.</value>
</data>
<data name="NotSupportedLanguageMode" xml:space="preserve">
<value>The '{0}' language mode is not supported. Supported language modes are FullLanguage and ConstrainedLanguage.</value>
</data>
<data name="WFCallingWFNotSupported" xml:space="preserve">
<value>Workflows cannot call workflows on this platform.</value>
</data>
<data name="DebuggerStopReason" xml:space="preserve">
<value>The debugger Quit command has stopped the workflow job.</value>
</data>
<data name="ProcessDebugCommandNotInDebugStopMode" xml:space="preserve">
<value>"Cannot process the debugger command until the debugger is stopped."</value>
</data>
<data name="RetryingAction" xml:space="preserve">
<value>Retrying activity action: attempt {0}.</value>
<comment>{0} is a number and should not be localized.</comment>
</data>
<data name="XamlWorkflowsNotSupported" xml:space="preserve">
<value>Cannot load the workflow. Only signed in-box XAML-based workflows or script-based workflows are supported in the current language mode.</value>
</data>
<data name="RetryingConnection" xml:space="preserve">
<value>Retrying activity connection: attempt {0} of {1}.</value>
<comment>{0} and {1} are numbers and should not be localized.</comment>
</data>
<data name="DebuggerCannotModifyWFVars" xml:space="preserve">
<value>Workflow variables cannot be modified inside the debugger. The command or script did not run because it attempted to modify variable '${0}'.
</value>
</data>
<data name="JobStoppedByDebugger" xml:space="preserve">
<value>The debugger Quit command has stopped the workflow job.</value>
</data>
</root>