What could be causing an IndexOutOfRange exception with this code? - c#

Recently, I've been getting an IndexOutOfRange exception in a particular method. The new code in this function reads a "csv" file (a .txt file renamed with the extension "CSV") and parses it; so it must be code specific to that or else the data itself that is raising this exception.
But it's apparently not on the Insert into the database, because I added a MessageBox.Show() in the catch block where the insert takes place, and I never see it.
public bool PopulatePlatypusItemsListAndInsertIntoPlatypusItemsTable(frmCentral fc)
{
const int Platypus_ID_OFFSET = 0;
const int Platypus_ITEM_ID_OFFSET = 1;
const int ITEM_ID_OFFSET = 2;
const int PACKSIZE_OFFSET = 3;
bool ret = false;
try
{
string dSQL;
bool First = true;
if (File.Exists(csvFilePathName))
{
int fzz = 0;
dSQL = "DELETE FROM PlatypusItems";
try
{
dbconn.DBCommand(dSQL, true);
}
catch
{
frmCentral.listboxMessage.TopIndex = frmCentral.listboxMessage.Items.Add(Convert.ToString(++frmCentral.lstMessageCount) +
". Error processing PlatypusItem data from server");
}
SqlCeConnection conn = dbconn.GetConnection();
if (conn != null && conn.State == ConnectionState.Closed)
{
conn.Open();
}
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO PlatypusItems ( PlatypusID, PlatypusItemID, ItemID, PackSize) VALUES (?, ?, ?, ?)";
if (!ret)
{
ret = true;
}
PlatypusItem DuckbillItm = new PlatypusItem();
string thisLine;
string[] arrLine;
using (StreamReader sr = new StreamReader(csvFilePathName))
{
while (sr.Peek() >= 0)
{
thisLine = sr.ReadLine();
arrLine = thisLine.Split(',');
DuckbillItm.PlatypusID = arrLine[Platypus_ID_OFFSET];
DuckbillItm.PlatypusItemID = arrLine[Platypus_ITEM_ID_OFFSET];
DuckbillItm.ItemID = arrLine[ITEM_ID_OFFSET];
DuckbillItm.PackSize = Convert.ToInt32(arrLine[PACKSIZE_OFFSET]);
PlatypusItemList.List.Add(DuckbillItm);
dSQL = "INSERT INTO PlatypusItems (PlatypusID, PlatypusItemID, ItemID, PackSize) VALUES (" + DuckbillItm.PlatypusID + ",'" +
DuckbillItm.PlatypusItemID + "','" + DuckbillItm.ItemID + "'," + DuckbillItm.PackSize + ")";
if (!First)
{
cmd.Parameters[0].Value = DuckbillItm.PlatypusID;
cmd.Parameters[1].Value = DuckbillItm.PlatypusItemID;
cmd.Parameters[2].Value = DuckbillItm.ItemID;
cmd.Parameters[3].Value = DuckbillItm.PackSize.ToString();
}
if (First)
{
cmd.Parameters.Add("#PlatypusID", DuckbillItm.PlatypusID);
cmd.Parameters.Add("#PlatypusItemID", DuckbillItm.PlatypusItemID);
cmd.Parameters.Add("#ItemID", DuckbillItm.ItemID);
cmd.Parameters.Add("#PackSize", DuckbillItm.PackSize);
cmd.Prepare();
First = false;
}
if (frmCentral.CancelFetchInvDataInProgress)
{
return false;
}
try
{
// testing with these reversed: - either way, get the IndexOutOfRange exception...
//dbconn.DBCommand(cmd, dSQL, true);
dbconn.DBCommand(cmd, cmd.CommandText, true); //<-- If this works as well or better, dSQL is only there for the progress updating code below
// the first line is the legacy code; the second seems more sensible to me; both seem to work
}
catch (Exception x)
{
MessageBox.Show(string.Format("dbcommand exc message = {0}; PlatypusID = {1}; PlatypusItemID = {2}; ItemID = {3}; PackSize = {4}",
x.Message, DuckbillItm.PlatypusID, DuckbillItm.PlatypusItemID, DuckbillItm.ItemID, DuckbillItm.PackSize));//TODO: Remove
frmCentral.listboxMessage.TopIndex =
frmCentral.listboxMessage.Items.Add(Convert.ToString(++frmCentral.lstMessageCount) +
". Error processing Platypus Item data from server");
}
fzz += dSQL.Length; //<-- tried commenting this weird code out, but still get IndexOutOfRangeException
if (fzz > fc.ProgressChangedIndex)
{
fc.ProgressChangedIndex = fzz + fc.ProgressChangedIncrement;
if (((frmCentral.ProgressBar.progressBar1.Maximum/4) + (fzz*3) < frmCentral.ProgressBar.progressBar1.Maximum) &&
((frmCentral.ProgressBar.progressBar1.Maximum/4) + (fzz*3) > frmCentral.ProgressBar.progressBar1.Value))
{
frmCentral.ProgressBar.progressBar1.Value = (frmCentral.ProgressBar.progressBar1.Maximum/4) + (fzz*3);
frmCentral.ProgressBar.progressBar1.Refresh();
}
}
}
}
}
}
catch (Exception ex)
{
duckbilledPlatypiRUs.ExceptionHandler(ex, "PlatypusItemFile.PopulatePlatypusItemsListAndInsertIntoPlatypusItemsTable");
}
return ret;
}
I know this code is kind of a wacko mix of different styles; the good code is mine, and the weird code is legacy (g,d&r)
I can do this, of course, to sweep the dust under the rug:
catch (Exception ex)
{
if (ex.Message.IndexOf("IndexOutOfRange") < 0)
{
duckbilledPlatypiRUs.ExceptionHandler(ex, "PlatypusItemFile.PopulatePlatypusItemsListAndInsertIntoPlatypusItemsTable");
}
}
...but I don't know if that IndexOutOfRangeException is actually something serious that is wreaking mayhem in the innards of this app.
UPDATE
I added this code:
if (arrLine[PLATYPUS_ID_OFFSET].Length > 10) //TODO: Remove?
{
MessageBox.Show(string.Format("PLATYPUS_ID_OFFSET length should be 10; was {0}", arrLine[PLATYPUS_ID_OFFSET].Length));
arrLine[PLATYPUS_ID_OFFSET] = arrLine[PLATYPUS_ID_OFFSET].Substring(0, 10);
}
if (arrLine[PLATYPUS_ITEM_ID_OFFSET].Length > 19)
{
MessageBox.Show(string.Format("PLATYPUS_ITEM_ID_OFFSET length should be 19; was {0}", arrLine[PLATYPUS_ID_OFFSET].Length));
arrLine[PLATYPUS_ITEM_ID_OFFSET] = arrLine[PLATYPUS_ITEM_ID_OFFSET].Substring(0, 19);
}
if (arrLine[ITEM_ID_OFFSET].Length > 19)
{
MessageBox.Show(string.Format("ITEM_ID_OFFSET length should be 19; was {0}", arrLine[PLATYPUS_ID_OFFSET].Length));
arrLine[ITEM_ID_OFFSET] = arrLine[ITEM_ID_OFFSET].Substring(0, 19);
}
...and I never saw those MessageBox.Show()s, so I guess it's not the three string values that are causing the problem; perhaps the int (PackSize). PackSize would never be greater than what Int32 allows; is there a TryParse() equivalent in .NET 1.1?
UPDATE 2
I do see the "IndexOutOfRange" from the exception here, and yet never the MessageBox.Show()s:
try
{
thisLine = sr.ReadLine();
arrLine = thisLine.Split(',');
if (arrLine[PLATYPUS_ID_OFFSET].Length > 10) //TODO: Remove?
{
MessageBox.Show(string.Format("PLATYPUS_ID_OFFSET length should be 10; was {0}", arrLine[PLATYPUS_ID_OFFSET].Length));
arrLine[PLATYPUS_ID_OFFSET] = arrLine[PLATYPUS_ID_OFFSET].Substring(0, 10);
}
. . .
DuckbillItm.PLATYPUSID = arrLine[PLATYPUS_ID_OFFSET];
DuckbillItm.PLATYPUSItemID = arrLine[PLATYPUS_ITEM_ID_OFFSET];
DuckbillItm.ItemID = arrLine[ITEM_ID_OFFSET];
DuckbillItm.PackSize = Convert.ToInt32(arrLine[PACKSIZE_OFFSET]);
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
UPDATE 3
It was bad data, after all; some of the lines had four commas in them instead of the expected three. So, I just removed those lines (after adding code to check each element of the array for size, and trimming them prior to that) and it runs fine.

My initial guess: Probably one of the arrLine[...] lines (e.g. DuckbillItm.PlatypusID = arrLine[Platypus_ID_OFFSET]) would cause this if your input .csv file is bad. Do a debug build and put your breakpoint on the catch handler, and tell us what "ex.StackTrace" says.

Related

How can I find a phrase anywhere in a String Array?

I need to see if any phrase, such as "duckbilled platypus" appears in a string array.
In the case I'm testing, the phrase does exist in the string list, as shown here:
Yet, when I look for that phrase, as shown here:
...it fails to find it. I never get past the "if (found)" gauntlet in the code below.
Here is the code that I'm using to try to traverse through the contents of one doc to see if any phrase (two words or more) are found in both documents:
private void FindAndStorePhrasesFoundInBothDocs()
{
string[] doc1StrArray;
string[] doc2StrArray;
slPhrasesFoundInBothDocs = new List<string>();
slAllDoc1Words = new List<string>();
int iCountOfWordsInDoc1 = 0;
int iSearchStartIndex = 0;
int iSearchEndIndex = 1;
string sDoc1PhraseToSearchForInDoc2;
string sFoundPhrase;
bool found;
int iLastWordIndexReached = iSearchEndIndex;
try
{
doc1StrArray = File.ReadAllLines(sDoc1Path, Encoding.UTF8);
doc2StrArray = File.ReadAllLines(sDoc2Path, Encoding.UTF8);
foreach (string line in doc1StrArray)
{
string[] subLines = line.Split();
foreach (string whirred in subLines)
{
if (String.IsNullOrEmpty(whirred)) continue;
slAllDoc1Words.Add(whirred);
}
}
iCountOfWordsInDoc1 = slAllDoc1Words.Count();
sDoc1PhraseToSearchForInDoc2 = slAllDoc1Words[iSearchStartIndex] + ' ' + slAllDoc1Words[iSearchEndIndex];
while (iLastWordIndexReached < iCountOfWordsInDoc1 - 1)
{
sFoundPhrase = string.Empty;
// Search for the phrase from doc1 in doc2;
found = doc2StrArray.Contains(sDoc1PhraseToSearchForInDoc2);
if (found)
{
sFoundPhrase = sDoc1PhraseToSearchForInDoc2;
iSearchEndIndex++;
sDoc1PhraseToSearchForInDoc2 = sDoc1PhraseToSearchForInDoc2 + ' ' + slAllDoc1Words[iSearchEndIndex];
}
else //if not found, inc vals of BOTH int args and, if sFoundPhrase not null, assign to sDoc1PhraseToSearchForInDoc2 again.
{
iSearchStartIndex = iSearchEndIndex;
iSearchEndIndex = iSearchStartIndex + 1;
if (!string.IsNullOrWhiteSpace(sFoundPhrase)) // add the previous found phrase if there was one
{
slPhrasesFoundInBothDocs.Add(sFoundPhrase);
}
sDoc1PhraseToSearchForInDoc2 = slAllDoc1Words[iSearchStartIndex] + ' ' + slAllDoc1Words[iSearchEndIndex];
} // if/else
iLastWordIndexReached = iSearchEndIndex;
} // while
} // try
catch (Exception ex)
{
MessageBox.Show("FindAndStorePhrasesFoundInBothDocs(); iSearchStartIndex = " + iSearchStartIndex.ToString() + "iSearchEndIndex = " + iSearchEndIndex.ToString() + " iLastWordIndexReached = " + iLastWordIndexReached.ToString() + " " + ex.Message);
}
}
doc2StrArray does contain the phrase sought, so why does doc2StrArray.Contains(sDoc1PhraseToSearchForInDoc2) fail?
This should do what you want:
found = Array.FindAll(doc2StrArray, s => s.Contains(sDoc1PhraseToSearchForInDoc2));
In List<T>, Contains() looking for an T, Here in your code to found be true must have all the text in particular index (NOT part of it).
Try this
var _list = doc2StrArray.ToList();
var found = _list.FirstOrDefault( w => w.Contains( sDoc1PhraseToSearchForInDoc2 ) ) != null;

How to do unit test on a method that has StreamReader and Database access

I have never done unit tests before. I'd like to learn how to do it. I'd like to use Visual Studio unit test and moq.
My project is transferring data from interbase to SQL Server. Firstly, I extract data from interbase into a plain text file. The layout is FieldName + some spaces up to 32 char length + field value. Then, I write a method that reads the text file line by line; once it reaches the next record, it inserts the current record into SQL Server.
So it involves in stream reader and SQL database insertion. For the stream reader, I read some post on the Internet and I pass the Stream reader as the method's parameter; but the SQL Server part, I have no idea how to simplify my method so that it can be tested.
I really need your help.
public partial class TableTransfer
{
#region declare vars
public string FirstFldName = "";
public string ErrorMsg = "";
public List<MemoBlobTrio> MemoBlobs = null;
public string SqlServerTableName = "";
#endregion
public bool DoTransfer(System.IO.StreamReader sr, Func<TransferShare, string, string, bool> TransferTable)
{
#region declare var
bool DoInsert = true;
TransferShare transferShare = null;
string line = string.Empty;
string blobLines = string.Empty;
string fldName = string.Empty;
string value = string.Empty;
bool Is1stLine = true;
bool isMemoFld = false;
MemoBlobTrio memoBlobTrio = null;
int idx = 0;
#endregion
try
{
using(sr)
{
transferShare = new TransferShare();
ConnectSQLServer(transferShare);
transferShare.StartInsert(SqlServerTableName);
bool readNext = true;
do
{
try
{
if (readNext)
line = sr.ReadLine();
if ((line != null) && (line.Trim() != ""))
{
fldName = line.Length > 30 ? line.Substring(0, 31).TrimEnd() : "";
Is1stLine = fldName == FirstFldName;
if (Is1stLine)
{
if (DoInsert)
EndInsert(transferShare, line);
else
transferShare.ClearSQL();
DoInsert = true;
}
idx = 0;
isMemoFld = false;
while (idx < MemoBlobs.Count)
{
if (fldName == (MemoBlobs[idx] as MemoBlobTrio).fbFldName)
{
memoBlobTrio = MemoBlobs[idx] as MemoBlobTrio;
line = InsertMemoBlob(transferShare, sr, memoBlobTrio.ssFldName, fldName, memoBlobTrio.fbNextFldName);
readNext = false;
isMemoFld = true;
}
idx++;
}
if (!isMemoFld)
{
if (line.Length > 31)
value = line.Remove(0, 31);
else
value = "";
if (!TransferTable(transferShare, fldName, value))
DoInsert = false;
readNext = true;
}
}
}
catch (Exception err)
{
HandleError(err, line);
}
} while (line != null);
if (DoInsert)
EndInsert(transferShare, line);
}
}
finally
{
transferShare.SQLConn.Dispose();
}
return true;
}
private static void ConnectSQLServer(TransferShare transferShare)
{
TransferShare.SQLServerConnStr = "Data Source=" + Environment.MachineName + "\\SQLEXPRESS;Initial Catalog=MyDB;Integrated Security=True";
transferShare.SQLConn.ConnectionString = TransferShare.SQLServerConnStr;
transferShare.SQLConn.Open();
}
}
public class TransferShare
{
public void StartInsert(string TableName)
{
tableName = TableName;
}
public void EndInsert(TransferShare transferShare, string line)
{
SqlCommand Cmd = null;
try
{
sqlInsFld = sqlInsFld.Remove(sqlInsFld.Length - 1);
sqlInsValue = sqlInsValue.Remove(sqlInsValue.Length - 1);
sqlInsFld = "Insert into " + tableName + " (" + sqlInsFld + ")";
sqlInsValue = " Values (" + sqlInsValue + ")";
Cmd = new SqlCommand(sqlInsFld + sqlInsValue, SQLConn);
Cmd.ExecuteNonQuery();
}
catch (Exception err)
{
throw (new Exception(err.Message));
}
finally
{
sqlInsFld = "";
sqlInsValue = "";
}
}
}

FileWatcher issue

OK, so this time I created a service with a file watcher to process file once created.
it seems that my service crashes when the files being processed reaches 1000 (I'm receiving loads of messages).
here is my logic: files comes in, file watcher read the text send it to email, insert into DB, move original message to a folders.
on the service start, I'm processing pending messages first before start to watch (I'm talking about over 1000 of text file pending) and my service needs about a second to work on each file.
All goes OK, but when the total incoming files reaches 1000, it simply crash.
sometimes the service stops processing pending and only start looking for new files only.
I have the "InternalBufferSize = 64000" the max recommended.
Please help me with my code (I know it should be multi-threaded for better handling, but I'm not that expert):
protected override void OnStart(string[] args)
{
using(TREEEntities TEX = new TREEEntities())
{
var mp= TEX.TREE_settings.FirstOrDefault(x=>x.SET_key =="MSGDump");
MsgsPath = mp.SET_value;
var dc = TEX.TREE_settings.FirstOrDefault(x => x.SET_key == "DupCash");
DupCash = Convert.ToInt16(dc.SET_value);
}
if (Directory.Exists(MsgsPath))
{
if (!Directory.Exists(MsgsPath+"\\Archive"))
{
Directory.CreateDirectory(MsgsPath+"\\Archive");
}
if (!Directory.Exists(MsgsPath + "\\Duplicates"))
{
Directory.CreateDirectory(MsgsPath + "\\Duplicates");
}
if (!Directory.Exists(MsgsPath + "\\Unsent"))
{
Directory.CreateDirectory(MsgsPath + "\\Unsent");
}
}
else
{
Directory.CreateDirectory(MsgsPath);
Directory.CreateDirectory(MsgsPath + "\\Archive");
Directory.CreateDirectory(MsgsPath + "\\Duplicates");
Directory.CreateDirectory(MsgsPath + "\\Unsent");
}
processPending();//<--- process pending files after last service stop
fileSystemWatcher1.Path = MsgsPath;//<--- path to be watched
fileSystemWatcher1.EnableRaisingEvents = true;
fileSystemWatcher1.InternalBufferSize = 64000;
addToLog(DateTime.Now, "Service Started", 0, "Service", "Info");
addToLog(DateTime.Now, "File Watcher Started", 0, "Service", "Info");
//dupList.Clear();//<--- clear duplicates validation list
}
protected override void OnStop()
{
fileSystemWatcher1.EnableRaisingEvents = false;
addToLog(DateTime.Now, "File Watcher Stopped", 0, "Service", "Alert");
addToLog(DateTime.Now, "Service Stopped", 0, "Service", "Alert");
}
private void fileSystemWatcher1_Created(object sender, FileSystemEventArgs e)
{
try
{
//---------read from file------------
Thread.Sleep(200);//<---give the file some time to get released
string block;
using (StreamReader sr = File.OpenText(MsgsPath + "\\" + e.Name))
{
block = sr.ReadToEnd();
}
PRT = block.Substring(block.Length - 6, 6);//<--- get the printer name
seq = Convert.ToInt16(block.Substring(block.Length - 20, 20).Substring(0, 4));//<--- get the sequence number
switch (PRT)//<----track sequence number from the 3 printers
{
case "64261B"://<---prt1
int seqPlus1=0;
if(seqPrt1 == 9999)//<---ignore sequence change from 9999 to 1
{ seqPlus1 = 1; }
else { seqPlus1 = seqPrt1 + 1; }
if (seq != seqPlus1 && seqPrt1 != 0)//<---"0" to avoid first service start
{
int x = seq - seqPrt1 - 1;
for (int i = 1; i <= x; i++)
{
addToMissing(PRT, seqPlus1);
addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus1, seqPlus1, "Service", "Missing");
seqPlus1++;
}
seqPrt1 = seq;
}
else { seqPrt1 = seq; }
break;
case "24E9AA"://<---prt2
int seqPlus2=0;
if(seqPrt2 == 9999)
{ seqPlus2 = 1; }
if (seq != seqPlus2 && seqPrt2 != 0)
{
int x = seq - seqPrt2 - 1;
for (int i = 1; i <= x; i++)
{
addToMissing(PRT, seqPlus2);
addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus2, seqPlus2, "Service", "Missing");
seqPlus2++;
}
seqPrt2 = seq;
}
else { seqPrt2 = seq; }
break;
case "642602"://<---prt3
int seqPlus3=0;
if(seqPrt3 == 9999)
{ seqPlus3 = 1; }
if (seq != seqPlus3 && seqPrt3 != 0)
{
int x = seq - seqPrt3 - 1;
for (int i = 1; i <= x; i++)
{
addToMissing(PRT, seqPlus3);
addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus3, seqPlus3, "Service", "Missing");
seqPlus3++;
}
seqPrt3 = seq;
}
else { seqPrt3 = seq; }
break;
}
block = block.Remove(block.Length - 52);//<--- trim the sequence number and unwanted info
string[] Alladd;
List<string> sent = new List<string>();
if (!dupList.Contains(block)) //<--- if msg not found in duplicates validation list
{
//--------extract values--------------
if (block.Substring(0, 3) == "\r\nQ") //<--- if the msg. contains a priority code
{
Alladd = block.Substring(0, block.IndexOf(".")).Replace("\r\n", " ").Substring(4).Split(' ').Distinct().Where(x => !string.IsNullOrEmpty(x)).ToArray(); ;
}
else//<--- if no priority code
{
Alladd = block.Substring(0, block.IndexOf(".")).Replace("\r\n", " ").Substring(1).Split(' ').Distinct().Where(x => !string.IsNullOrEmpty(x)).ToArray(); ;
}
string From = block.Substring(block.IndexOf('.') + 1).Substring(0, 7);
string Msg = block.Substring(block.IndexOf('.') + 1);
Msg = Msg.Substring(Msg.IndexOf('\n') + 1);
//--------add msg content to the DB group table--------
using (TREEEntities TE1 = new TREEEntities())
{
TREE_group tg = new TREE_group()
{
GROUP_original = block,
GROUP_sent = Msg,
GROUP_dateTime = DateTime.Now,
GROUP_from = From,
GROUP_seq = seq,
GROUP_prt = PRT,
};
TE1.AddToTREE_group(tg);
TE1.SaveChanges();
GID = tg.GROUP_ID;
}
//--------validate addresses---------------
foreach (string TB in Alladd)
{
string email = "";
string typeB = "";
TREEEntities TE = new TREEEntities();
var q1 = from x in TE.TREE_users where x.USR_TypeB == TB && x.USR_flag == "act" select new { x.USR_email, x.USR_TypeB };
foreach (var itm in q1)
{
email = itm.USR_email;
typeB = itm.USR_TypeB;
}
//-------send mail if the user exist----
if (TB == typeB)
{
if (typeB == "BAHMVGF")
{
addToFtl(block);
}
try
{
sendMail SM = new sendMail();
SM.SendMail(Msg, "Message from: " + From, email);
//---save record in DB----
addToMsg(typeB, email,"sent","act",1,GID,seq);
sent.Add(typeB);
}
catch (Exception x)
{
addToMsg(typeB, email, "Failed", "act", 1, GID, seq);
addToLog(DateTime.Now, "Send message failed: " + x.Message, GID, "Service", "Warning");
}
}
//-------if no user exist----
else
{
if (TB == "BAHMVGF")
{
addToFtl(block);
}
addToMsg(TB, "No email", "Failed", "act", 1, GID, seq);
addToLog(DateTime.Now, "Send message failed, unknown Type-B address: " + TB, GID, "Service", "Warning");
}
}
if (sent.Count < Alladd.Count())//<--- if there is unsent addresses
{
StringBuilder b = new StringBuilder(block);
foreach (string add in sent)
{
b.Replace(add, "");//<--- remove address that has been sent from the original message and write new msg. to unsent folder
}
if (!Directory.Exists(MsgsPath + "\\Unsent"))
{
Directory.CreateDirectory(MsgsPath + "\\Unsent");
}
using (StreamWriter w = File.AppendText(MsgsPath + "\\Unsent\\" + e.Name))
{
w.WriteLine(b);
}
}
sent.Clear();
//---add to dupList to validate the next messages-------------
if (dupList.Count > DupCash)
{
dupList.RemoveAt(0);
}
dupList.Add(block);
//---move msg to archive folder-----------------
if (!Directory.Exists(MsgsPath + "\\Archive"))
{
Directory.CreateDirectory(MsgsPath + "\\Archive");
}
File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Archive\\" + e.Name);
}
else //<--- if message is a duplicate
{
addToLog(DateTime.Now, "Duplicated message, message not sent", seq, "Service", "Info");
//---move msg to duplicates folder-----------------
if (!Directory.Exists(MsgsPath + "\\Duplicates"))
{
Directory.CreateDirectory(MsgsPath + "\\Duplicates");
}
File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Duplicates\\" + e.Name);
}
}
catch (Exception x)
{
addToLog(DateTime.Now, "Error: " + x.Message, seq, "Service", "Alert");
if (!Directory.Exists(MsgsPath + "\\Unsent"))
{
Directory.CreateDirectory(MsgsPath + "\\Unsent");
}
//---move msg to Unsent folder-----------------
File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Unsent\\" + e.Name);
}
}
I wanted to add this as a comment but it exceeded the allowed number of characters so here goes.
First thing I noticed in your code that you are doing all the file handling inside the Created event handler. This is not a good practice, you should always let your FileSystemWatcher event handlers do minimum work as it might result an overflow which is probably what you are facing.
Instead it is better to delegate the work on a separate thread. You can add the events to a queue and let a background thread worry handling them. You can filter the files in the event handler so that your queue does not get filled with garbage.
Using Sleep inside the event handler is also considered a bad practice as you'll be blocking the FileSystemWatcher event.
The maximum buffer size allowed is 64K, it is not a recommended buffer size unless you are dealing with long paths. Increasing buffer size is expensive, because it comes from non-paged memory that cannot be swapped out to disk, so keep the buffer as small as possible. To avoid a buffer overflow, use the NotifyFilter and IncludeSubdirectories properties to filter out unwanted change notifications.
And finally I would suggest reading the FileSystemWatcher MSDN article and looking at several examples online before attempting to write code as the Windows watcher is somewhat delicate and prone to errors

Oracle Connection and TCP Client/Server Connection at same time

I am writing a program that will live on a "Super PC" in my lab at work. Its job is to constantly query our customers databases proactively looking for common errors that we encounter.
It accomplishes this by using an adjustable timer and simply running down the list of queries and databases and interpreting the results.(Queries and Database connections are added using a Configuration UI)
This program has a TCP client/server connection with another app that I have written that lives on my team members personal machines. Messages get sent from the Server(Query) program to the client program alerting my team of errors found in the Databases.
The problem I keep encountering is occasionally a message gets sent through the socket at the exact same time a DB connection is made or a query is run and it causes the server program to crash with no explanation.
The methods that run the queries is always called in its own thread as well as the server connection is made in its own thread.
In addition I have placed all of the DB methods and Client Server methods in Try/Catch blocks that are setup to catch all exceptions and display the stack trace, but for some reason when it crashes its not hitting any of the catch.
The runQueries Methods is called off a C# .Net System.Timers.Timer which is supposed to launch a new thread on every tick.
Below are my Client/Server Methods and Query Methods
private void serverMeth()
{
try
{
/*conbox.Text = conbox.Text + "The server is running at port 8001..." + Environment.NewLine;
conbox.Text = conbox.Text + "The local End point is :" + myList.LocalEndpoint + Environment.NewLine;
conbox.Text = conbox.Text + "Waiting for a connection....." + Environment.NewLine;*/
msglist.Add("The server is running at port 8001...");
msglist.Add("The local end point is: " + myList.LocalEndpoint);
msglist.Add("Waiting for a connection...");
writeToLog("Listening for connection at "+myList.LocalEndpoint);
/* Start Listeneting at the specified port */
while (true)
{
gatherErrors();
myList.Start();
//Socket s = myList.AcceptSocket();
s = myList.AcceptSocket();
//conbox.Text = conbox.Text + "Connection accepted from " + s.RemoteEndPoint + Environment.NewLine;
msglist.Add("Connection accepted from " + s.RemoteEndPoint);
writeToLog("Connection Established #" + myList.LocalEndpoint);
byte[] b = new byte[20000];
int k = s.Receive(b);
//conbox.Text = conbox.Text + "Recieved..." + Environment.NewLine;
msglist.Add("Recieved...");
writeToLog("Message Recieved from Command Center");
//for (int i = 0; i < k; i++)
//{ conbox.Text = conbox.Text + Convert.ToChar(b[i]); }
string message = ""; //allows it to store the entire message in one line
string dt = DateTime.Now.ToString("MM-dd-yyyy hh:mm:ss");
string eid = "TEST ID";
for (int i = 0; i < k; i++)
{ message = message + Convert.ToChar(b[i]); }
if (message.Contains(uniquekey))
{
writeToLog("Message contains correct passcode");
message = message.Replace(uniquekey, "");
String[] splits = message.Split(',');
message = message.Replace("," + splits[1], "");
writeToLog("Connection from " + splits[1]);
msglist.Add(message); //this takes the completed message and adds it.
//DO IGNORE STUF HERE
if (!message.Equals(""))
{
//Message contains error key
Error erro = null;
for (int i = 0; i < errorss.Count; i++)
{
if (errorss[i].getKey().Equals(message)) {
erro = errorss[i];
}
}
Stage st = null;
if (erro != null)
{
for (int i = 0; i < stages.Count; i++)
{
if (stages[i].errContainCheck(erro))
{
st = stages[i];
}
}
}
if (st != null)
{
st.addIgnore(erro);
writeToLog("Error: " + erro.getKey() + "ignored");
}
}
//conbox.Text = conbox.Text + Environment.NewLine;
msglist.Add(" ");
string msg = "";
string log = "Error(s): ";
for (int i = 0; i < errorss.Count; i++)
{
msg += errorss[i].getTime() + "|"+errorss[i].getMsg()+"|" + errorss[i].getSite()+"|"+errorss[i].getKey();
msg += ",";
log += errorss[i].getKey()+",";
}
log+= "sent to Command Center";
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes(msg));
//conbox.Text = conbox.Text + "\nSent Acknowledgement" + Environment.NewLine;
msglist.Add("\nSent Acknowledgement");
writeToLog(log);
}
else
{
message = "Unauthorized access detected. Disregarding message.";
//.Add(message); //this takes the completed message and adds it.
//conbox.Text = conbox.Text + Environment.NewLine;
msglist.Add(" ");
writeToLog("Passcode mismatch");
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("Access Denied. Unique key mismatch."));
//conbox.Text = conbox.Text + "\nSent Acknowledgement" + Environment.NewLine;
msglist.Add("\nSent Denial Acknowledgement");
}
/* clean up */
s.Close();
myList.Stop();
if (quit == true)
{
break;
}
}
}
catch (Exception err)
{
//conbox.Text = conbox.Text + "Error..... " + err.StackTrace + Environment.NewLine;
msglist.Add("Error..... " + err.StackTrace);
writeToLog("ERROR: "+err.StackTrace);
}
}
private void sasDownload()
{
int selItemList;
selItemList = saerrlist.SelectedIndex;
saerrlist.Items.Clear(); //clears the list before redownload
saerrgrid.Rows.Clear();
try
{
TcpClient tcpclnt = new TcpClient();
//clibox.Text = clibox.Text + "Connecting....." + Environment.NewLine;
tcpclnt.Connect(staralertip.Text, 8001);
// use the ipaddress as in the server program
//clibox.Text = clibox.Text + "Connected" + Environment.NewLine;
//clibox.Text = clibox.Text + "Enter the string to be transmitted : " + Environment.NewLine;
String str = "982jsdf293jsadd02jkdas20dka2";
Stream stm = tcpclnt.GetStream();
if (ackClick)
{
str += ackKey;
ackClick = false;
}
String name = "User not found";
for (int i = 0; i < users.Count(); i++)
{
if(users[i].sys_id.Equals(SNLists.loggedinuser)){
name = users[i].name;
break;
}
}
str += "," + name;
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
//clibox.Text = clibox.Text + "Transmitting....." + Environment.NewLine;
stm.Write(ba, 0, ba.Length);
byte[] bb = new byte[20000];
int k = stm.Read(bb, 0, 20000);
string incmsg = "";
for (int i = 0; i < k; i++)
incmsg = incmsg + Convert.ToChar(bb[i]);
string tempmsg = "";
foreach (char c in incmsg)
{
if (c != ',')
{
tempmsg = tempmsg + c;
}
else if (c == ',')
{
saerrlist.Items.Add(tempmsg);
saerrgrid.Rows.Add(tempmsg.Split('|')[0], tempmsg.Split('|')[1], tempmsg.Split('|')[2], tempmsg.Split('|')[3]);
tempmsg = "";
}
}
saerrlist.Items.Add(tempmsg);
//saerrgrid.Rows.Add(tempmsg.Split('|')[0], tempmsg.Split('|')[1], tempmsg.Split('|')[2]);
//MessageBox.Show(incmsg);
tcpclnt.Close();
}
catch (Exception err)
{
//MessageBox.Show("Error..... " + err.StackTrace, "STAR Command Center: Connectivity Error");
staralertTimer.Enabled = false;
MessageBox.Show("Error downloading recent errors from STAR Alert System.\n\nPlease confirm STAR Alert is running " +
"and hit \"Refresh\" in the STAR Alert tab." + "\n" + err, "STAR Command Center: Connectivity Error");
}
saerrlist.SelectedIndex = selItemList;
}
public void runQueries()
{
OracleConnection con = new OracleConnection();
int siteNum = -1;
try
{
writeToLog("Call to runQueries");
List<List<Error>> results = new List<List<Error>>();
for (int i = 0; i < ppreset.getSites().Count(); i++)
{
siteNum = i;
Site s = ppreset.getSites()[i];
if (s.getStatus().Equals("ACTIVE"))
{
//OracleConnection con = new OracleConnection();
String it = "User Id=" + s.getLogin() + ";Password=" + s.getPassword() + ";Data Source=" + s.getDbName();
con.ConnectionString = it;
//con.OpenAsync();
con.Open();
writeToLog("Connection opened for site: " + s.getSite());
List<Error> subResults = new List<Error>();
for (int j = 0; j < s.getQueries().Count(); j++)
{
Query q = s.getQueries()[j];
string sql = q.getCode();
List<string> columns = getColumns(sql);
List<List<String>> mast = new List<List<String>>();
for (int m = 0; m < columns.Count(); m++)
{
mast.Add(new List<String>());
}
OracleCommand cmd = new OracleCommand(sql, con);
cmd.CommandType = CommandType.Text;
OracleDataReader dr = cmd.ExecuteReader();
writeToLog("Execute SQL, Begin Reading results...");
// dr.Read();
//List<String> results = new List<String>();
if (dr.HasRows)
{
//MessageBox.Show("has rows");
while (dr.Read())
{
//string result = "";
for (int p = 0; p < columns.Count(); p++)
{
if (columns.Count() != 0)
{
mast[p].Add(dr[columns[p]].ToString());
}
}
//results.Add(result);
}
}
subResults.AddRange(ruleCheck(mast, q.getRules(), s.getQueries()[j], ppreset.getSites()[i].getSite()));
cmd.Dispose();
writeToLog("Done reading");
}
results.Add(subResults);
// con.Dispose();
con.Close();
writeToLog("Connection Closed for site: " + s.getSite());
}
}
//we now have all of the error strings gathered from running all queries on all sites in the given preset
//lets send them to a method that will change the status' of the modules and makem RAVVEEEEE
//update(results);
if (errors == null && results.Count != 0)
{
//MessageBox.Show("errors = results");
errors = results;
writeToLog("First error found...errors = results");
for (int i = 0; i < results.Count; i++)
{
for (int j = 0; j < results[i].Count; j++)
{
if (foncig.lallerdisc == true)
{
sendLyncMsg(results[i][j].getMsg());
writeToLog("Lync Msg sent");
}
}
}
}
else
{
for (int i = 0; i < results.Count; i++)
{
for (int j = 0; j < results[i].Count; j++)
{
errors[i].Add(results[i][j]);
writeToLog("Error: " + results[i][j].getKey() + " added");
// MessageBox.Show("Error added to errors");
//////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//LYNC STUFF CAN GO HERE///////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/////FOR EACH ERROR ADDED TO MASTER LIST SEND LYNC///////////////////////////
//////////////////////////////////////////////////////////////////////////////
if (foncig.lallerdisc == true)
{
sendLyncMsg(results[i][j].getMsg());
writeToLog("Lync msg sent");
}
}
}
}
}
catch (Exception e)
{//MessageBox.Show("Err: " + e);
badConn[siteNum] += "x";
writeToLog("Connection error strike added to " + ppreset.getSites()[siteNum].getSite());
con.Close();
checkForBadConn();
writeToLog( e.StackTrace);
}
//foncig.errors = errors;
//here we will check all of the errors in results against all of the errors in errors
//if the error is not in errors add it
//errors = results;
}
Query timer initialization
queryTimer = new System.Timers.Timer(120000);
queryTimer.Elapsed += queryTimer_Tick;
queryTimer.Enabled = true;
Tick method for query timer
private void queryTimer_Tick(object sender, EventArgs e)
{
GC.Collect();
try
{
runQueries();
}
catch (OracleException err)
{
// MessageBox.Show("Err: " + err);
}
}
How the server thread is started
server = new Thread(serverMeth);
server.Start();
Does anyone have any idea why this might be happening? Both programs work as described and do what they are supposed to its just when more and more clients begin connecting to the server it becomes more and more likely that a TCP connection and DB connection will occur at the same time.
Update 12:20 9/15/14
So I'm trying to upload a pic of the log from the last crash... but i don't have enough rep points... derp, anyway
This time the last line in the log is from a log purge(deletes log entries older than 24 hours)
However the program will only crash when I have the client program set to auto refresh. IE Client app has a button to request messages from server or user can select auto-refresh which sets request function to timer.
My only other thought is that multiple threads are trying to write to the log file at the same time, however my write to log method uses writeLinesAsync() so that shouldn't be a problem?
This issue turned out to be caused by multiple threads trying to write to the log file at the same time.
I resolved it by following #user469104's advice and creating an internal lock object to lock the writeToLog methods.
Both client and server apps have been running for multiple days now without breaking.
Thanks Everyone!

Exception occurs when trying to pass value to crystal report text box object

I am trying to pass value from C# code to a CrystalReport report.
Edit
private void PrintOrder(List<OrderPrintBO> pListOrderBO)
{
DSOrderReport oDSOrderReport = new DSOrderReport();
DataTable oDataTable = oDSOrderReport.Tables[0];
String sOrderNo = "";
if (pListOrderBO.Count > 0)
{
for (int i = 0; i < pListOrderBO.Count; i++)
{
DataRow oRow = oDataTable.NewRow();
oRow["OrderID"] = pListOrderBO[i].OrderID;
oRow["OrderNumber"] = pListOrderBO[i].OrderNumber;
sOrderNo = pListOrderBO[i].OrderNumber;
oDataTable.Rows.Add(oRow);
}
}
oDSOrderReport.Merge(oDataTable);
oDSOrderReport.AcceptChanges();
if (oDSOrderReport.Tables[0].Rows.Count > 0)
{
// Main Copy
PrintDialog printDialog = new PrintDialog();
rptOrder oMainOrder = new rptOrder();
String sCompanyName = System.Configuration.ConfigurationManager.AppSettings["CompanyName"].ToString();
String sPhone1 = System.Configuration.ConfigurationManager.AppSettings["Phone1"].ToString();
String sPhone2 = System.Configuration.ConfigurationManager.AppSettings["Phone2"].ToString();
String sShowOrderNo = System.Configuration.ConfigurationManager.AppSettings["ShowOrderNo"].ToString();
((CrystalDecisions.CrystalReports.Engine.TextObject)oMainOrder.ReportDefinition.ReportObjects["txtCompanyName"]).Text = sCompanyName;
((CrystalDecisions.CrystalReports.Engine.TextObject)oMainOrder.ReportDefinition.ReportObjects["txtPhone1"]).Text = "Tel:" + sPhone1;
((CrystalDecisions.CrystalReports.Engine.TextObject)oMainOrder.ReportDefinition.ReportObjects["txtPhone2"]).Text = "Tel:" + sPhone2;
////This commented out section gives exception
//string sVarOrderNo = "";
//if (sShowOrderNo.ToLower() == "yes")
//{
// sVarOrderNo = sOrderNo;
//}
//((CrystalDecisions.CrystalReports.Engine.TextObject)oMainOrder.ReportDefinition.ReportObjects["txtOrderNo"]).Text = "O.N. : " + sVarOrderNo;
oMainOrder.SetDataSource(oDSOrderReport);
oMainOrder.PrintOptions.PrinterName = printDialog.PrinterSettings.PrinterName;
try
{
oMainOrder.PrintToPrinter(1, false, 0, 0);
MessageBox.Show("Order Printed Successfully", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
else
{
MessageBox.Show("Error in Printing Order", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
End Edit
For the first three text boxes (CompanyName, Phone1 & Phone2), every thing working just fine, but when I tried to pass the OrderNo to the report, Index was outside the bounds of the array. exception is occured, even though my report have a TextBox object named txtOrderNo
I am not sure why this is happening. Please help. Thanks.
Try to change your sOrderNo related code is as below.
string sVarOrderNo = "";
if (sShowOrderNo.ToLower() == "yes")
{
sVarOrderNo = sOrderNo;
}
((CrystalDecisions.CrystalReports.Engine.TextObject)oMainOrder.ReportDefinition.ReportObjects["txtOrderNo"]).Text = "O.N. : " + sVarOrderNo;
UPDATE
Your problem is below mentioned code snippet.Inside the for loop you try to assign a value to sOrderNo. Which is meaningless.B'cos it overrides every time when loop goes.So what is the purpose of this ? If you need this value then you have to bring this value through as your table's row or as a parameter to the report.
if (pListOrderBO.Count > 0)
{
for (int i = 0; i < pListOrderBO.Count; i++)
{
DataRow oRow = oDataTable.NewRow();
oRow["OrderID"] = pListOrderBO[i].OrderID;
oRow["OrderNumber"] = pListOrderBO[i].OrderNumber;
sOrderNo = pListOrderBO[i].OrderNumber;
oDataTable.Rows.Add(oRow);
}
}
I hope this will help to you.

Categories