Cisco JTAPI phone register/unregister status - cisco

I am using the below code to check the phone status(if phone is up or down). When phone is down sends an alarm. However this doesn't show when 8800 series phones are down. Is there any other method to check the Phone register/unregister status?
#Override public void terminalChangedEvent(TermEv[] eventList) {
if ( eventList != null ) {
for (TermEv eventList1 : eventList) {
if (eventList1 instanceof CiscoTermInServiceEv){
if(terminalInService.test()==true){
LogSQL.removeLog(terminal.getName());
}
System.out.println(terminal.getName());
terminalInService.set();
return;
} else if (eventList1 instanceof CiscoTermOutOfServiceEv &&
terminalInService.test()==true) {
offline();
}
}
}
}
Second Question, I was not able to find the methods or documentation about "com.cisco.cti.util.Condition" class. What does Condition.set() and Condition.test() methods do?

Looks like you have the right general idea - JTAPI should work fine for 88xx models, assuming you have the correct device->user association, and user permissions (Standard CTI Enabled, and Standard CTI Allow Control of Phones supporting Connected Xfer and conf needed for 88xx).
Here is my version working on CUCM 11.5:
package com.mycompany.app;
import com.cisco.jtapi.extensions.*;
import java.util.*;
import javax.telephony.*;
import javax.telephony.events.*;
import javax.telephony.callcontrol.*;
import javax.telephony.callcontrol.events.*;
import com.cisco.cti.util.Condition;
public class DataTerm implements ProviderObserver, TerminalObserver {
public static final int OUT_OF_SERVICE = 0;
public static final int IN_SERVICE = 1;
private Address destAddress;
private CiscoTerminal observedTerminal;
private boolean addressInService;
private boolean terminalInService;
protected int state = OUT_OF_SERVICE;
Condition conditionInService = new Condition();
Provider provider;
public DataTerm(String[] args) {
try {
System.out.println("Initializing Jtapi");
String providerName = "ds-ucm115-1.cisco.com";
String login = "dstaudt";
String passwd = "password";
String dest = "2999";
JtapiPeer peer = JtapiPeerFactory.getJtapiPeer(null);
String providerString = providerName + ";login=" + login + ";passwd=" + passwd;
System.out.println("Opening " + providerString + "...\n");
provider = peer.getProvider(providerString);
provider.addObserver(this);
conditionInService.waitTrue();
this.destAddress = provider.getAddress(dest);
this.observedTerminal = (CiscoTerminal) destAddress.getTerminals()[0];
try {
if (destAddress != null) {
System.out.println("Adding Terminal Observer to Terminal" + observedTerminal.getName());
observedTerminal.addObserver(this);
}
} catch (Exception e) {
}
} catch (Exception e) {
System.out.println("Caught exception " + e);
}
}
public void terminalChangedEvent(TermEv[] events) {
for (int i = 0; i < events.length; i++) {
Terminal terminal = events[i].getTerminal();
switch (events[i].getID()) {
case CiscoTermInServiceEv.ID:
System.out.println("Received " + events[i] + "for " + terminal.getName());
terminalInService = true;
break;
case CiscoTermOutOfServiceEv.ID:
System.out.println("Received " + events[i] + "for " + terminal.getName());
terminalInService = false;
if (state != OUT_OF_SERVICE) { // you only want to notify when you had notified earlier that you are IN_SERVICE
state = OUT_OF_SERVICE;
}
break;
}
}
}
public void providerChangedEvent(ProvEv[] eventList) {
if (eventList != null) {
for (int i = 0; i < eventList.length; i++) {
if (eventList[i] instanceof ProvInServiceEv) {
conditionInService.set();
}
}
}
}
}
The "com.cisco.cti.util.Condition" seems to be based on this pattern:
public interface Condition
Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.
Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to "wait") until notified by another thread that some state condition may now be true. Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition. The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread, just like Object.wait.
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html

Related

Multithreading and Monitoring

I am trying to get multithreading more unraveled in my head. I made these three classes.
A global variable class
public partial class globes
{
public bool[] sets = new bool[] { false, false, false };
public bool boolChanged = false;
public string tmpStr = string.Empty;
public int gcount = 0;
public bool intChanged = false;
public Random r = new Random();
public bool gDone = false;
public bool first = true;
}
Drop in point
class Driver
{
static void Main(string[] args)
{
Console.WriteLine("start");
globes g = new globes();
Thread[] threads = new Thread[6];
ParameterizedThreadStart[] pts = new ParameterizedThreadStart[6];
lockMe _lockme = new lockMe();
for (int b = 0; b < 3; b++)
{
pts[b] = new ParameterizedThreadStart(_lockme.paramThreadStarter);
threads[b] = new Thread(pts[b]);
threads[b].Name = string.Format("{0}", b);
threads[b].Start(b);
}
}
}
And then my threading class
class lockMe
{
#region Fields
private string[] words = new string[] {"string0", "string1", "string2", "string3"};
private globes g = new globes();
private object myKey = new object();
private string[] name = new string[] { String.Empty, String.Empty, String.Empty };
#endregion
#region methods
// first called for all threads
private void setName(Int16 i)
{
Monitor.Enter(myKey);
{
try
{
name[i] = string.Format("{0}:{1}", Thread.CurrentThread.Name, g.r.Next(100, 500).ToString());
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
}
// thread 1
private void changeBool(Int16 a)
{
Monitor.Enter(myKey);
{
try
{
int i = getBools();
//Thread.Sleep(3000);
if (g.gcount > 5) { g.gDone = true; return; }
if (i == 3) resets();
else { for (int x = 0; x <= i; i++) { g.sets[x] = true; } }
Console.WriteLine("Thread {0} ran through changeBool()\n", name[a]);
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
}
// thread 2
private void changeInt(Int16 i)
{
Monitor.Enter(myKey);
{
try
{
g.gcount++;
//Thread.Sleep(g.r.Next(1000, 3000));
Console.WriteLine("Thread {0}: Count is now at {1}\n", name[i], g.gcount);
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
}
// thread 3
private void printString(Int16 i)
{
Monitor.Enter(myKey);
{
try
{
Console.WriteLine("...incoming...");
//Thread.Sleep(g.r.Next(1500, 2500));
Console.WriteLine("Thread {0} printing...{1}\n", name[i], words[g.r.Next(0, 3)]);
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
}
// not locked- called from within a locked peice
private int getBools()
{
if ((g.sets[0] == false) && (g.sets[1] == false) && (g.sets[2] == false)) return 0;
else if ((g.sets[0] == true) && (g.sets[1] == false) && (g.sets[2] == false)) return 1;
else if ((g.sets[2] == true) && (g.sets[3] == false)) return 2;
else if ((g.sets[0] == true) && (g.sets[1] == true) && (g.sets[2] == true)) return 3;
else return 99;
}
// should not need locks- called within locked statement
private void resets()
{
if (g.first) { Console.WriteLine("FIRST!!"); g.first = false; }
else Console.WriteLine("Cycle has reset...");
}
private bool getStatus()
{
bool x = false;
Monitor.Enter(myKey);
{
try
{
x = g.gDone;
}
finally
{
Monitor.PulseAll(myKey);
Monitor.Exit(myKey);
}
}
return x;
}
#endregion
#region Constructors
public void paramThreadStarter(object starter)
{
Int16 i = Convert.ToInt16(starter);
setName(i);
do
{
switch (i)
{
default: throw new Exception();
case 0:
changeBool(i);
break;
case 1:
changeInt(i);
break;
case 2:
printString(i);
break;
}
} while (!getStatus());
Console.WriteLine("fin");
Console.ReadLine();
}
#endregion
}
So I have a few questions. The first- is it better to have my global class set like this? Or should I be using a static class with properties and altering them that way? Next question is, when this runs, at random one of the threads will run, pulse/exit the lock, and then step right back in (sometimes like 5-10 times before the next thread picks up the lock). Why does this happen?
Each thread is given a certain amount of CPU time, I doubt that one particular thread is getting more actual CPU time over the others if you are locking all the calls in the same fashion and the thread priorities are the same among the threads.
Regarding how you use your global class, it doesn't really matter. The way you are using it wouldn't change it one way or the other. Your use of globals was to test thread safety, so when multiple threads are trying to change shared properties all that matters is that you enforce thread safety.
Pulse might be a better option knowing that only one thread can actually enter, pulseAll is appropriate when you lock something because you have a task to do, once that task is complete and won't lock the very next time. In your scenario you lock every time so doing a pulseAll is just going to waste cpu because you know that it will be locked for the next request.
Common example of when to use static classes and why you must make them thread safe:
public static class StoreManager
{
private static Dictionary<string,DataStore> _cache = new Dictionary<string,DataStore>(StringComparer.OrdinalIgnoreCase);
private static object _syncRoot = new object();
public static DataStore Get(string storeName)
{
//this method will look for the cached DataStore, if it doesn't
//find it in cache it will load from DB.
//The thread safety issue scenario to imagine is, what if 2 or more requests for
//the same storename come in? You must make sure that only 1 thread goes to the
//the DB and all the rest wait...
//check to see if a DataStore for storeName is in the dictionary
if ( _cache.ContainsKey( storeName) == false )
{
//only threads requesting unknown DataStores enter here...
//now serialize access so only 1 thread at a time can do this...
lock(_syncRoot)
{
if (_cache.ContainsKey(storeName) == false )
{
//only 1 thread will ever create a DataStore for storeName
DataStore ds = DataStoreManager.Get(storeName); //some code here goes to DB and gets a DataStore
_cache.Add(storeName,ds);
}
}
}
return _cache[storeName];
}
}
What's really important to see is that the Get method only single threads the call when there is no DataStore for the storeName.
Double-Check-Lock:
You can see the first lock() happens after an if, so imagine 3 threads simultaneously run the if ( _cache.ContainsKey(storeName) .., now all 3 threads enter the if. Now we lock so that only 1 thread can enter, now we do the same exact if statement, only the very first thread that gets here will actually pass this if statement and get the DataStore. Once the first thread .Add's the DataStore and exits the lock the other 2 threads will fail the second check (double check).
From that point on any request for that storeName will get the cached instance.
So we single threaded our application only in the spots that required it.

Plugin code to update another entity when case is created mscrm 2011

Im new with plugin. my problem is, When the case is created, i need to update the case id into ledger. What connect this two is the leadid. in my case i rename lead as outbound call.
this is my code. I dont know whether it is correct or not. Hope you guys can help me with this because it gives me error. I manage to register it. no problem to build and register but when the case is created, it gives me error.
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Client;
using System.Net;
using System.Web.Services;
/*
* Purpose: 1) To update case number into lejar
*
* Triggered upon CREATE message by record in Case form.
*/
namespace UpdateLejar
{
public class UpdateLejar : IPlugin
{
/*public void printLogFile(String exMessage, String eventMessage, String pluginFile)
{
DateTime date = DateTime.Today;
String fileName = date.ToString("yyyyMdd");
String timestamp = DateTime.Now.ToString();
string path = #"C:\CRM Integration\PLUGIN\UpdateLejar\Log\" + fileName;
//open if file exist, check file..
if (File.Exists(path))
{
//if exist, append
using (StreamWriter sw = File.AppendText(path))
{
sw.Write(timestamp + " ");
sw.WriteLine(pluginFile + eventMessage + " event: " + exMessage);
sw.WriteLine();
}
}
else
{
//if no exist, create new file
using (StreamWriter sw = File.CreateText(path))
{
sw.Write(timestamp + " ");
sw.WriteLine(pluginFile + eventMessage + " event: " + exMessage);
sw.WriteLine();
}
}
}*/
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
//for update and create event
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parmameters.
Entity targetEntity = (Entity)context.InputParameters["Target"];
// Verify that the entity represents a connection.
if (targetEntity.LogicalName != "incident")
{
return;
}
else
{
try
{
//triggered upon create message
if (context.MessageName == "Create")
{
Guid recordid = new Guid(context.OutputParameters["incidentid"].ToString());
EntityReference app_inc_id = new EntityReference();
app_inc_id = targetEntity.GetAttributeValue<EntityReference>("new_outboundcalllid");
Entity member = service.Retrieve("new_lejer", ((EntityReference)targetEntity["new_outboundcallid"]).Id, new ColumnSet(true));
//DateTime createdon = targetEntity.GetAttributeValue<DateTime>("createdon");
if (app_inc_id != null)
{
if (targetEntity.Attributes.Contains("new_outboundcallid") == member.Attributes.Contains("new_outboundcalllistid_lejer"))
{
member["new_ringkasanlejarid"] = targetEntity.Attributes["incidentid"].ToString();
service.Update(member);
}
}
}
tracingService.Trace("Lejar updated.");
}
catch (FaultException<OrganizationServiceFault> ex)
{
//printLogFile(ex.Message, context.MessageName, "UpdateLejar plug-in. ");
throw new InvalidPluginExecutionException("An error occurred in UpdateLejar plug-in.", ex);
}
catch (Exception ex)
{
//printLogFile(ex.Message, context.MessageName, "UpdateLejar plug-in. ");
tracingService.Trace("UpdateLejar: {0}", ex.ToString());
throw;
}
}
}
}
}
}
Please check,
is that entity containing the attributes or not.
check it and try:
if (targetEntity.Contains("new_outboundcallid"))
((EntityReference)targetEntity["new_outboundcallid"]).Id
member["new_ringkasanlejarid"] = targetEntity.Attributes["incidentid"].ToString();
What is new_ringkasanlejarid's type? You're setting a string to it. If new_ringkasanlejarid is an entity reference, this might be causing problems.
You might want to share the error details or trace log, all we can do is assume what the problem is at the moment.

E_SCN_READINCOMPATIBLE Notification error thrown while scanning bar code on MC9090G

I'm using EMDK 2.5 (VS2008 and VC# and .NetCF3.5) Barcode2 class from the library to write a sample application to scan bar codes. I followed the samples available in EMDK namely CS_Barcode2Sample1 project.Every time I hardware trigger the scan the notification "E_SCN_READINCOMPATIBLE" is thrown and not able to retrieve the scanned data. The documentation doesn't say much about the cause of E_SCN_READINCOMPATIBLE notification and no luck from Google search. I tried several options including making use of Symbol.Barcode and the outcome is same.
I also tried EMDK 2.3 but the result is same.
I've pasted the whole code here....
public partial class Form1 : Form
{
private Barcode2 myBarcode2 = null;
public Form1()
{
InitializeComponent();
InitBarcode();
}
public bool InitBarcode()
{
// If the Barcode2 object is already initialized then fail the initialization.
if (myBarcode2 != null)
{
return false;
}
else // Else initialize the reader.
{
try
{
Symbol.Barcode2.Device[] AvailableDevices = Symbol.Barcode2.Devices.SupportedDevices;
if (AvailableDevices.Length == 0)
{
return false;
}
if (AvailableDevices.Length == 1)
{
//get the first available scanner in the list
Symbol.Barcode2.Device MyDevice = AvailableDevices[0];
// Create the reader, based on selected device.
myBarcode2 = new Barcode2(MyDevice);
// Attach a scan notification handler.
//this.myScanNotifyHandler = new Barcode2.OnScanHandler(myBarcode2_ScanNotify);
myBarcode2.OnScan += myBarcode2_ScanNotify;
// Attach a status notification handler.
//this.myStatusNotifyHandler = new Barcode2.OnStatusHandler(myBarcode2_StatusNotify);
myBarcode2.OnStatus += myBarcode2_StatusNotify;
myBarcode2.Config.TriggerMode = TRIGGERMODES.HARD;
// Submit a scan.
myBarcode2.Scan(5000);
}
}
catch (OperationFailureException ex)
{
MessageBox.Show("Exception Raised 1");
return false;
}
catch (InvalidRequestException ex)
{
MessageBox.Show("Exception Raised 2");
return false;
}
catch (InvalidIndexerException ex)
{
MessageBox.Show("Exception Raised 3");
return false;
}
}
return false;
}
private void myBarcode2_ScanNotify(ScanDataCollection scanDataCollection)
{
// Checks if the BeginInvoke method is required because the OnScan delegate is called by a different thread
if (this.InvokeRequired)
{
// Executes the OnScan delegate asynchronously on the main thread
this.BeginInvoke(new Barcode2.OnScanHandler(myBarcode2_ScanNotify), new object[] { scanDataCollection });
}
else
{
// Get ScanData
ScanData scanData = scanDataCollection.GetFirst;
int i;
switch (scanData.Result)
{
case Symbol.Barcode2.Results.SUCCESS:
String str = scanData.Text;
myBarcode2.Config.TriggerMode = TRIGGERMODES.HARD;
myBarcode2.Scan(5000);
break;
case Symbol.Barcode2.Results.E_SCN_READTIMEOUT:
break;
case Symbol.Barcode2.Results.CANCELED:
break;
case Symbol.Barcode2.Results.E_SCN_DEVICEFAILURE:
i = 93;
break;
default:
if (scanData.Result == Symbol.Barcode2.Results.E_SCN_READINCOMPATIBLE)
{
// If the failure is E_SCN_READINCOMPATIBLE, exit the application.
MessageBox.Show("Fatal Error");
this.Close();
return;
}
break;
}
}
}
private void myBarcode2_StatusNotify(StatusData statusData)
{
// Checks if the Invoke method is required because the OnStatus delegate is called by a different thread
if (this.InvokeRequired)
{
// Executes the OnStatus delegate on the main thread
this.Invoke(new Barcode2.OnStatusHandler(myBarcode2_StatusNotify), new object[] { statusData });
}
else
{
int i;
switch (statusData.State)
{
case States.IDLE:
break;
case States.READY:
break;
default:
break;
}
}
}
}
}
I've went thru this recently also, as I observed, it probably due to the scanner device is occupied by other application, where the scan request has been queued already, you can go to memory management, and kill the suspect app, and try your app again.
Refer to the Symbol FAQ

LWUIT4IO (v1.5) ConnectionRequest's readResponse() Issue - Nokia SDK 2.0

I have been porting an existing J2ME mobile app, that allows users to view archived news videos, to the latest Nokia SDK 2.0 platform for Series 40 full-touch devices.
I am using both the LWUIT and LWUIT4IO technologies for the UI and Network functionalities of the application respectively.
The app has been tested to work on the S40 5th Edition SDK platform emulator. Extending LWUIT4IO's ConnectionRequest class and utilizing LWUIT's XMLParser, the app can successfully send a HTTP request and get the expected response data from a web service that basically returns an XML-formatted type of feed (containing necessary metadata for the video) (Here's the URL of the web service: http://nokiamusic.myxph.com/nokianewsfeed.aspx?format=3gp)
But for some reason, this is not the case when trying to run the app on the latest Nokia SDK 2.0 platform. It throws a java.lang.NullPointerException upon trying to parse (XMLParser.parse()) the InputStream response of the web service. When I trace the Network Traffic Monitor of the emulator of the corresponding Request sent and Response received - 0 bytes were returned as content despite a successful response status 200. Apparently the XMLParser object has nothing to parse in the first place.
I am hoping that you can somehow shed light on this issue or share any related resolutions, or help me further refine the problem.
Posted below is the code of the SegmentService class (a sub-class of LWUIT's ConnectionRequest) that connects to the webservice and processes the XML response:
public class SegmentService extends ConnectionRequest implements ParserCallback {
private Vector segments;
private Video segment;
public SegmentService(String backend) {
String slash = backend.endsWith("/") ? "" : "/";
setPost(false);
setUrl(backend + slash + "nokianewsfeed.aspx");
addArgument("format", "3gp");
}
public void setDateFilter(String date) {
System.out.println(date);
addArgument("date", date);
}
private Video getCurrent() {
if (segment == null) {
segment = new Video();
}
return segment;
}
protected void readResponse(InputStream input) throws IOException {
InputStreamReader i = new InputStreamReader(input, "UTF-8");
XMLParser xmlparser = new XMLParser();
System.out.println("Parsing the xml...");
Element element = xmlparser.parse(i);
System.out.println("Root " + element.getTagName());
int max = element.getNumChildren();
System.out.println("Number of children: " + max);
segments = new Vector();
for (int c = 0; c < max; c++) {
Element e = element.getChildAt(c);
System.out.println("segment " + c);
int len = e.getNumChildren();
System.out.println("Number of children: " + len);
for (int d=0; d<len; d++) {
Element s = e.getChildAt(d);
String property = s.getTagName();
System.out.println("key: " + property);
String value = (s.getNumChildren()>0) ? s.getChildAt(0).getText() : null;
System.out.println("value: " + value);
if (property.equals("title")) {
getCurrent().setTitle(value);
} else if (property.equals("description")) {
getCurrent().setDescription(value);
} else if (property.equals("videourl")) {
getCurrent().setVideoUrl(value);
} else if (property.equals("thumburl")) {
getCurrent().setThumbUrl(value);
} else if (property.equals("adurl")) {
getCurrent().setAdUrl(value);
} else if (property.equals("publishdate")) {
getCurrent().setPublishDate(value);
} else if (property.equals("category")) {
getCurrent().setCategory(value);
} else if (property.equals("weburl")) {
getCurrent().setWebUrl(value);
} else if (property.equals("thumburl2")) {
getCurrent().setThumb210(value);
} else if (property.equals("thumburl4")) {
getCurrent().setThumb40(value);
}
}
if (segment != null) {
segments.addElement(segment);
segment = null;
}
}
fireResponseListener(new NetworkEvent(this, segments));
}
public boolean parsingError(int errorId, String tag, String attribute, String value, String description) {
System.out.println(errorId);
System.out.println(tag);
System.out.println(value);
System.out.println(description);
return true;
}
}

C# powershell output reader iterator getting modified when pipeline closed and disposed

I'm calling a powershell script from C#. The script is pretty small and is "gps;$host.SetShouldExit(9)", which list process, and then send back an exit code to be captured by the PSHost object.
The problem I have is when the pipeline has been stopped and disposed, the output reader PSHost collection still seems to be written to, and is filling up. So when I try and copy it to my own output object, it craps out with a OutOfMemoryException when I try to iterate over it. Sometimes it will except with a Collection was modified message. Here is the code.
private void ProcessAndExecuteBlock(ScriptBlock Block)
{
Collection<PSObject> PSCollection = new Collection<PSObject>();
Collection<Object> PSErrorCollection = new Collection<Object>();
Boolean Error = false;
int ExitCode=0;
//Send for exection.
ExecuteScript(Block.Script);
// Process the waithandles.
while (PExecutor.PLine.PipelineStateInfo.State == PipelineState.Running)
{
// Wait for either error or data waithandle.
switch (WaitHandle.WaitAny(PExecutor.Hand))
{
// Data
case 0:
Collection<PSObject> data = PExecutor.PLine.Output.NonBlockingRead();
if (data.Count > 0)
{
for (int cnt = 0; cnt <= (data.Count-1); cnt++)
{
PSCollection.Add(data[cnt]);
}
}
// Check to see if the pipeline has been closed.
if (PExecutor.PLine.Output.EndOfPipeline)
{
// Bring back the exit code.
ExitCode = RHost.ExitCode;
}
break;
case 1:
Collection<object> Errordata = PExecutor.PLine.Error.NonBlockingRead();
if (Errordata.Count > 0)
{
Error = true;
for (int count = 0; count <= (Errordata.Count - 1); count++)
{
PSErrorCollection.Add(Errordata[count]);
}
}
break;
}
}
PExecutor.Stop();
// Create the Execution Return block
ExecutionResults ER = new ExecutionResults(Block.RuleGuid,Block.SubRuleGuid, Block.MessageIdentfier);
ER.ExitCode = ExitCode;
// Add in the data results.
lock (ReadSync)
{
if (PSCollection.Count > 0)
{
ER.DataAdd(PSCollection);
}
}
// Add in the error data if any.
if (Error)
{
if (PSErrorCollection.Count > 0)
{
ER.ErrorAdd(PSErrorCollection);
}
else
{
ER.InError = true;
}
}
// We have finished, so enque the block back.
EnQueueOutput(ER);
}
and this is the PipelineExecutor class which setups the pipeline for execution.
public class PipelineExecutor
{
private Pipeline pipeline;
private WaitHandle[] Handles;
public Pipeline PLine
{
get { return pipeline; }
}
public WaitHandle[] Hand
{
get { return Handles; }
}
public PipelineExecutor(Runspace runSpace, string command)
{
pipeline = runSpace.CreatePipeline(command);
Handles = new WaitHandle[2];
Handles[0] = pipeline.Output.WaitHandle;
Handles[1] = pipeline.Error.WaitHandle;
}
public void Start()
{
if (pipeline.PipelineStateInfo.State == PipelineState.NotStarted)
{
pipeline.Input.Close();
pipeline.InvokeAsync();
}
}
public void Stop()
{
pipeline.StopAsync();
}
}
An this is the DataAdd method, where the exception arises.
public void DataAdd(Collection<PSObject> Data)
{
foreach (PSObject Ps in Data)
{
Data.Add(Ps);
}
}
I put a for loop around the Data.Add, and the Collection filled up with 600k+ so feels like the gps command is still running, but why. Any ideas.
Thanks in advance.
Found the problem. Named the resultant collection and the iterator the same, so as it was iterating, it was adding to the collection, and back into the iterator, and so forth. Doh!.

Resources