/// <summary>
        /// States whether or not this rule should apply the predefined value to the predefined property
        /// The caller will handle aggregation if multiple rules
        ///
        /// *Note
        /// this need not be implemented if not supporting yes no classifiers
        /// </summary>
        /// <param name="property">The name of the property that this rule can modify</param>
        /// <param name="Value">The value to set that will be applied to the property if applyValue is true</param>
        /// <param name="applyValue">True if the caller should set Value to property, False if the caller should not set Value to property</param>
        /// <param name="idRule">The id of the rule to process</param>
        /// <param name="idPropDef">The id of the property definition that this rule can modify</param>
        public void DoesPropertyValueApply(
            string property,
            string Value,
            out bool applyValue,
            Guid idRule,
            Guid idPropDef
            )
        {
            PowerShellRuleHoster rule = m_dictAllRules[idRule];

            // run the powershell pipeline for this value
            rule.StepPipeline(m_propertyBag);

            // if the rule doesn't apply force the value to false
            if (rule.RuleNoApply)
            {
                applyValue = false;
            }
            else
            {
                try
                {
                    applyValue = (bool)rule.PropertyValue;
                }
                catch (Exception ex)
                {
                    //Assuming this error is due to casting

                    String message = String.Format(CultureInfo.InvariantCulture,
                                                   "PowerShell Classifier for rule [{0}] and file [{1}], failed to convert the property recieved from powershell of type [{2}] and value [{3}] into the a boolean value for yes/no classification, with error [{4}]",
                                                   rule.RuleName,
                                                   m_propertyBag.VolumeName + m_propertyBag.RelativePath + "\\" + m_propertyBag.Name,
                                                   rule.PropertyValue.GetType().ToString(),
                                                   rule.PropertyValue.ToString(),
                                                   ex.Message);

                    m_propertyBag.AddMessage(message);

                    throw new COMException(message, ex.InnerException);
                }
            }
        }
        /// <summary>
        /// Runs one step of the pipeline using propertyBag as the pipeline input
        /// Saves last outputed object
        /// Saves whether the pipeline returned 0 or 1 object
        /// throws exception if pipeline outputed more than 1 object
        /// <param name="propertyBag">The property bag to run the powershell script's pipeline on</param>
        public void StepPipeline(
            IFsrmPropertyBag propertyBag
            )
        {
            ResetRuleResults();

            m_waitHandleIndex lockIndex;
            bool readAValue = false;
            bool tooManyValues = false;
            m_ruleNoApply = false;

            // insert the property bag into the pipeline after adding the GetStream Method
            PSObject psPropertyBag = new PSObject(propertyBag);
            psPropertyBag.Methods.Add(new PSCodeMethod("GetStream", m_getStreamMethodInfo));
            m_propertyBagWriter.InsertData(psPropertyBag);

            // wait for either the pipeline to close or
            // for another property to be requested from the enumerator
            // If for input a in the script value 1 is emitted, it must be emitted before value b is requested
            // Handle multiple values being emitted but fail the current property bag if it happens
            do
            {
                lockIndex = (m_waitHandleIndex)WaitHandle.WaitAny(m_powershellPaused);

                //pipeline terminated unexpectedly save message and restart it
                if (m_pipeLine.Output.EndOfPipeline)
                {

                    string message;

                    if (m_pipeLine.PipelineStateInfo.State == PipelineState.Failed)
                    {
                        message = string.Format(CultureInfo.InvariantCulture,
                                                   "Powershell Classifier terminated abruptly due to failuer while processing file [{0}] in rule [{1}] - failure details: [{2}]",
                                                   propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                                                   m_ruleName,
                                                   m_pipeLine.PipelineStateInfo.Reason.Message);
                    }
                    else
                    {
                        message = string.Format(CultureInfo.InvariantCulture,
                                                   "Powershell Classifier exited abruptly without failures while processing file [{0}] in rule [{1}].",
                                                   propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                                                   m_ruleName);
                    }

                    propertyBag.AddMessage(message);
                    CreateAndBeginPipeline();
                    throw new COMException( message, m_pipeLine.PipelineStateInfo.Reason );
                }

                // if we haven't read a value pop one off and save it
                if (m_pipeLine.Output.Count >= 1 && !readAValue)
                {
                    readAValue = true;
                    m_propertyValue = m_pipeLine.Output.Read();
                }

                // if we have read a value and there are values in the pipeline, then
                // set the tooManyValues flag and eat everythign in the pipeline
                while (m_pipeLine.Output.Count > 0 && readAValue)
                {
                    // if the m_propertyValue currently points to the first value ouput for the pipeline
                    // the add a message for it, other wise output messages for duplicate values after popping them off
                    if (!tooManyValues)
                    {
                        string message1 = string.Format( CultureInfo.InvariantCulture,
                               "Powershell Classifier returned too many values while processing file [{0}] in rule [{1}] - returned object of type [{2}], and value [{3}]",
                               propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                               m_ruleName,
                               m_propertyValue.BaseObject.GetType().ToString(),
                               m_propertyValue.BaseObject.ToString() );
                        propertyBag.AddMessage(message1);

                    }

                    // cleanup pipeline
                    m_propertyValue = m_pipeLine.Output.Read();

                    // ouput message for current object
                    string message2 = string.Format( CultureInfo.InvariantCulture,
                               "Powershell Classifier returned too many values while processing file [{0}] in rule [{1}] - returned object of type [{2}], and value [{3}]",
                               propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                               m_ruleName,
                               m_propertyValue.BaseObject.GetType().ToString(),
                               m_propertyValue.BaseObject.ToString() );
                    propertyBag.AddMessage(message2);

                    tooManyValues = true;
                }

            } while (lockIndex != m_waitHandleIndex.Enumerator && m_pipeLine.Output.IsOpen);

            // if script didn't output any values for this property bag record it
            if (!readAValue)
            {
                m_ruleNoApply = true;
            }

            // if output too many values finish failing this property
            if (tooManyValues)
            {
                //already added messages for reason why we are failing
                string message3 = string.Format( CultureInfo.InvariantCulture,
                               "Powershell Classifier returned too many values while processing file [{0}] in rule [{1}]",
                               propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                               m_ruleName );
                throw new COMException( message3, HRESULTS.PS_CLS_E_TOO_MANY_VALUES );
            }

            // if there were errors in the pipeline pop them all off and then fail current property bag
            if (m_pipeLine.Error.Count > 0)
            {

                Exception firstError = null;
                while(m_pipeLine.Error.Count > 0)
                {
                    Exception exception = (Exception)m_pipeLine.Error.Read();
                    if (firstError == null)
                    {
                        firstError = exception;
                    }
                    // add message to pipeline
                    propertyBag.AddMessage(exception.Message);
                }

                throw (Exception)firstError;
            }
        }
        /// <summary>
        /// Runs one step of the pipeline using propertyBag as the pipeline input
        /// Saves last outputed object
        /// Saves whether the pipeline returned 0 or 1 object
        /// throws exception if pipeline outputed more than 1 object
        /// <param name="propertyBag">The property bag to run the powershell script's pipeline on</param>
        public void StepPipeline(
            IFsrmPropertyBag propertyBag
            )
        {
            ResetRuleResults();

            m_waitHandleIndex lockIndex;
            bool readAValue    = false;
            bool tooManyValues = false;

            m_ruleNoApply = false;

            // insert the property bag into the pipeline after adding the GetStream Method
            PSObject psPropertyBag = new PSObject(propertyBag);

            psPropertyBag.Methods.Add(new PSCodeMethod("GetStream", m_getStreamMethodInfo));
            m_propertyBagWriter.InsertData(psPropertyBag);

            // wait for either the pipeline to close or
            // for another property to be requested from the enumerator
            // If for input a in the script value 1 is emitted, it must be emitted before value b is requested
            // Handle multiple values being emitted but fail the current property bag if it happens
            do
            {
                lockIndex = (m_waitHandleIndex)WaitHandle.WaitAny(m_powershellPaused);

                //pipeline terminated unexpectedly save message and restart it
                if (m_pipeLine.Output.EndOfPipeline)
                {
                    string message;

                    if (m_pipeLine.PipelineStateInfo.State == PipelineState.Failed)
                    {
                        message = string.Format(CultureInfo.InvariantCulture,
                                                "Powershell Classifier terminated abruptly due to failuer while processing file [{0}] in rule [{1}] - failure details: [{2}]",
                                                propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                                                m_ruleName,
                                                m_pipeLine.PipelineStateInfo.Reason.Message);
                    }
                    else
                    {
                        message = string.Format(CultureInfo.InvariantCulture,
                                                "Powershell Classifier exited abruptly without failures while processing file [{0}] in rule [{1}].",
                                                propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                                                m_ruleName);
                    }

                    propertyBag.AddMessage(message);
                    CreateAndBeginPipeline();
                    throw new COMException(message, m_pipeLine.PipelineStateInfo.Reason);
                }

                // if we haven't read a value pop one off and save it
                if (m_pipeLine.Output.Count >= 1 && !readAValue)
                {
                    readAValue      = true;
                    m_propertyValue = m_pipeLine.Output.Read();
                }

                // if we have read a value and there are values in the pipeline, then
                // set the tooManyValues flag and eat everythign in the pipeline
                while (m_pipeLine.Output.Count > 0 && readAValue)
                {
                    // if the m_propertyValue currently points to the first value ouput for the pipeline
                    // the add a message for it, other wise output messages for duplicate values after popping them off
                    if (!tooManyValues)
                    {
                        string message1 = string.Format(CultureInfo.InvariantCulture,
                                                        "Powershell Classifier returned too many values while processing file [{0}] in rule [{1}] - returned object of type [{2}], and value [{3}]",
                                                        propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                                                        m_ruleName,
                                                        m_propertyValue.BaseObject.GetType().ToString(),
                                                        m_propertyValue.BaseObject.ToString());
                        propertyBag.AddMessage(message1);
                    }

                    // cleanup pipeline
                    m_propertyValue = m_pipeLine.Output.Read();

                    // ouput message for current object
                    string message2 = string.Format(CultureInfo.InvariantCulture,
                                                    "Powershell Classifier returned too many values while processing file [{0}] in rule [{1}] - returned object of type [{2}], and value [{3}]",
                                                    propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                                                    m_ruleName,
                                                    m_propertyValue.BaseObject.GetType().ToString(),
                                                    m_propertyValue.BaseObject.ToString());
                    propertyBag.AddMessage(message2);

                    tooManyValues = true;
                }
            } while (lockIndex != m_waitHandleIndex.Enumerator && m_pipeLine.Output.IsOpen);

            // if script didn't output any values for this property bag record it
            if (!readAValue)
            {
                m_ruleNoApply = true;
            }

            // if output too many values finish failing this property
            if (tooManyValues)
            {
                //already added messages for reason why we are failing
                string message3 = string.Format(CultureInfo.InvariantCulture,
                                                "Powershell Classifier returned too many values while processing file [{0}] in rule [{1}]",
                                                propertyBag.VolumeName + propertyBag.RelativePath + "\\" + propertyBag.Name,
                                                m_ruleName);
                throw new COMException(message3, HRESULTS.PS_CLS_E_TOO_MANY_VALUES);
            }

            // if there were errors in the pipeline pop them all off and then fail current property bag
            if (m_pipeLine.Error.Count > 0)
            {
                Exception firstError = null;
                while (m_pipeLine.Error.Count > 0)
                {
                    Exception exception = (Exception)m_pipeLine.Error.Read();
                    if (firstError == null)
                    {
                        firstError = exception;
                    }
                    // add message to pipeline
                    propertyBag.AddMessage(exception.Message);
                }

                throw (Exception)firstError;
            }
        }