// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved using System; using System.Collections; using System.Threading; using System.Management.Automation; namespace Microsoft.Samples.Fsrm.PowerShellHostClassifier { /// /// A class that allows us to ensure powershell gets one object at a time /// and to find out when powershell finshes processing one object and requests the next /// public class BlockablePropertyBagEnumerator : IEnumerator, IDisposable { bool m_inputEnded; PSObject m_nextValue; PSObject m_currentValue; ManualResetEvent m_DataRequestedWait; ManualResetEvent m_DataAddedWait; #region IEnumerator Members /// /// Get the current Value /// object IEnumerator.Current { get { return m_currentValue; } } /// /// Move the to the next object, will block untill we have more data to use /// /// True if MoveNext did not traverse past end of elements, false if it did bool IEnumerator.MoveNext() { // trigger we are waiting for data m_DataRequestedWait.Set(); // wait for data to be added m_DataAddedWait.WaitOne(); m_DataAddedWait.Reset(); m_DataRequestedWait.Reset(); // now that we have recieved data lets set it to current // this data can be no more data if input has ended m_currentValue = m_nextValue; return !m_inputEnded; } /// /// Not Implemented /// public void Reset() { throw new NotImplementedException("The method or operation is not implemented."); } #endregion /// /// Constructor /// public BlockablePropertyBagEnumerator() { m_DataRequestedWait = new ManualResetEvent( false ); m_DataAddedWait = new ManualResetEvent( false ); } /// /// Destructor /// ~BlockablePropertyBagEnumerator() { Dispose(false); } /// /// Dispose Method /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose Method /// /// If should free managed objects protected virtual void Dispose(bool disposing) { if (disposing) { m_DataRequestedWait.Close(); m_DataAddedWait.Close(); } } /// /// Allow Subsequent / current blocked MoveNext calls to state no more items /// public void EndInput() { m_inputEnded = true; m_nextValue = null; m_DataAddedWait.Set(); } /// /// Insert data into the next value of the enumerator /// /// public void InsertData(PSObject Data) { // At this time powershell MUST be contending on DataAddedWait m_DataRequestedWait.Reset(); m_nextValue = Data; m_DataAddedWait.Set(); } /// /// Reset the blocakble enum into a state when it had no data /// public void ResetBlockableEnum() { m_DataRequestedWait.Reset(); m_DataAddedWait.Reset(); m_inputEnded = false; m_nextValue = null; m_currentValue = null; } /// /// An ManualResetEvent Handle that states if data has been requested /// public ManualResetEvent RequestedDataWaitHandle { get { return m_DataRequestedWait; } } } }