/// <summary> /// This is called on the begining of each new file /// /// It should be noted that if rules are being processed in this function and if each rule can modify the propertyBag and affect other rules /// then the rules should be processed synchronously such that the first rule processed contains the longest scope that matches the file's path /// To avoid trying to do this on your own you can just process the rules in the DoesPropertyValueApply / GetPropertyValueToApply /// </summary> /// <param name="propertyBag">The fsrm property bag representing the current file</param> /// <param name="arrayRuleIds">An array of strings containg the string form of the guids that apply to this file, to convert them to guid's do new Guid(string)</param> public void OnBeginFile( IFsrmPropertyBag propertyBag, object[] arrayRuleIds ) { m_propertyBag = propertyBag; }
/// <summary> /// A function which returns a Stream object which encapsulates an IStream interface /// This makes it much easier to get the file contents in managed code / powershell /// </summary> /// <param name="parentObject">This will be the PSObject that encapsulates a IFsrmPropertyBag</param> /// <returns>A stream which wraps the parentObject's IStream</returns> public static StreamWrapperForIStream GetStream(PSObject parentObject) { IFsrmPropertyBag propertyBag = (IFsrmPropertyBag)parentObject.BaseObject; IStream istream = (IStream)propertyBag.GetFileStreamInterface(_FsrmFileStreamingMode.FsrmFileStreamingMode_Read, _FsrmFileStreamingInterfaceType.FsrmFileStreamingInterfaceType_IStream); return(new StreamWrapperForIStream(istream)); }
/*++ * * Routine RegexClassifier::OnBeginFile * * Description: * * This routine implements the IFsrmClassifierModuleImplementation interface OnBeginFile. * It is called by the pipeline for each file so that the classifier can process its rules for this file. * * Arguments: * * propertyBag - The FSRM property bag object for this file. * arrayRuleIds - The list of rules that are applicable for this file. * * Return value: * * void * * Notes: * * * --*/ public void OnBeginFile( IFsrmPropertyBag propertyBag, object[] arrayRuleIds ) { //reset all rules foreach (KeyValuePair <Guid, FsrmClassificationRule> kvp in m_dictAllRules) { FsrmClassificationRule rule = (FsrmClassificationRule)kvp.Value; rule.ResetRule(); } // create guid form of each id Guid[] ruleIdGuids = new Guid[arrayRuleIds.Length]; for (int i = 0; i < arrayRuleIds.Length; ++i) { ruleIdGuids[i] = new Guid((string)arrayRuleIds[i]); } // wrap the istream in a stream, and use a streamreader to get each line // match each line against each rule's regexp // quit when all data has been read or all rules have been matched using (StreamWrapperForIStream stream = new StreamWrapperForIStream((IStream)propertyBag.GetFileStreamInterface(_FsrmFileStreamingMode.FsrmFileStreamingMode_Read, _FsrmFileStreamingInterfaceType.FsrmFileStreamingInterfaceType_IStream))) { StreamReader streamReader = new StreamReader(stream, m_encoder); bool matchedAllRules = false; do { string line = streamReader.ReadLine(); matchedAllRules = true; foreach (Guid ruleId in ruleIdGuids) { matchedAllRules &= m_dictAllRules[ruleId].DoesRegexSatisfy(line); } } while (!streamReader.EndOfStream && !matchedAllRules); streamReader.Dispose(); } }
/// <summary> /// Sample code does nothing here but you can put any per file cleanup code here /// </summary> public void OnEndFile() { m_propertyBag = null; }
/*++ Routine RegexClassifier::OnBeginFile Description: This routine implements the IFsrmClassifierModuleImplementation interface OnBeginFile. It is called by the pipeline for each file so that the classifier can process its rules for this file. Arguments: propertyBag - The FSRM property bag object for this file. arrayRuleIds - The list of rules that are applicable for this file. Return value: void Notes: --*/ public void OnBeginFile( IFsrmPropertyBag propertyBag, object[] arrayRuleIds ) { //reset all rules foreach (KeyValuePair<Guid, FsrmClassificationRule> kvp in m_dictAllRules) { FsrmClassificationRule rule = (FsrmClassificationRule)kvp.Value; rule.ResetRule(); } // create guid form of each id Guid[] ruleIdGuids = new Guid[arrayRuleIds.Length]; for (int i = 0; i < arrayRuleIds.Length; ++i) { ruleIdGuids[i] = new Guid( (string)arrayRuleIds[i] ); } // wrap the istream in a stream, and use a streamreader to get each line // match each line against each rule's regexp // quit when all data has been read or all rules have been matched using (StreamWrapperForIStream stream = new StreamWrapperForIStream( (IStream)propertyBag.GetFileStreamInterface( _FsrmFileStreamingMode.FsrmFileStreamingMode_Read, _FsrmFileStreamingInterfaceType.FsrmFileStreamingInterfaceType_IStream ) )) { StreamReader streamReader = new StreamReader( stream, m_encoder ); bool matchedAllRules = false; do { string line = streamReader.ReadLine(); matchedAllRules = true; foreach (Guid ruleId in ruleIdGuids) { matchedAllRules &= m_dictAllRules[ruleId].DoesRegexSatisfy( line ); } } while (!streamReader.EndOfStream && !matchedAllRules); streamReader.Dispose(); } }
/// <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; } }