Thread safety / Invoke method causes StackOverflowException - c#

This is an app that uses WMI to fetch Local Administrator group members on a remote computer. In an attempt to make threadsafe calls to update my main UI from within Background Worker I am getting a StackOverflowException. I have copied the example from another thread on Stack. Could someone help me to identify the cause?
private void getLocalAdministrators(string serverName)
{
try
{
System.Management.ManagementScope scope = new System.Management.ManagementScope("\\\\" + serverName + "\\root\\cimv2");
scope.Connect();
StringBuilder qs = new StringBuilder();
qs.Append("SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = \"Win32_Group.Domain='" + serverName + "',Name='" + "Administrators'\"");
System.Management.ObjectQuery query = new System.Management.ObjectQuery(qs.ToString());
System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher(scope, query);
foreach (System.Management.ManagementObject group in searcher.Get())
{
string groupDetails = serverName + tab + group["PartComponent"].ToString() + tab;
string domainPart = groupDetails.Split('=')[1];
domainPart = domainPart.Replace("\"","").Replace(",Name","");
string accountPart = groupDetails.Split('=')[2];
accountPart = accountPart.Replace("\"", "");
if (query != null)
{
updateUISafely(serverName + tab + domainPart + tab + accountPart);
}
else
{
updateUISafely("Error with: " + serverName);
}
}
}
catch (Exception ex)
{
updateUISafely("Error with: " + serverName + ". " + ex.Message);
}
}
public delegate void ProcessResultDelegate(string result);
void updateUISafely(string result)
{
if (textBox2.InvokeRequired)
{
var d = new ProcessResultDelegate(updateUISafely);
d.Invoke(result);
}
else
{
textBox2.AppendText(result + nl);
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string[] strArray;
strArray = textBox1.Text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
int objectCount = strArray.Count();
int count = 0;
foreach (string str in strArray)
{
getLocalAdministrators(str);
count++;
backgroundWorker1.ReportProgress((100 * count) / objectCount);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
foreach (string item in resultsList)
{
textBox2.AppendText(item + Environment.NewLine);
}
btnGet.Enabled = true;
}

You are invoking (aka calling) the delegate, causing it to repeatedly call updateUISafely without ever invoking on the UI thread.
You should call Invoke on the form/control instead providing the delegate as parameter.
Use:
this.Invoke(d);

Related

C# Email parsing. Error: The program ... has exited with code 0 (0x0)

I develop simple application for renaming locally stored emails. Emails are loaded in a listbox and there is a button which does renaming. The problem is that I can rename three email and than the application crushes. No specific error reported. Here is my code...
namespace EmailFilenameRename
{
public partial class Form1 : Form
{
CultureInfo deCulture = new CultureInfo("de-DE");
public Form1()
{
InitializeComponent();
}
private static string[] getAddressParts(string address)
{
var splittedAdress = address.Split(' ');
return splittedAdress.Last().Trim().StartsWith("<")
? new[] { string.Join(" ", splittedAdress.Take(splittedAdress.Length - 1)), splittedAdress.Last().Trim(' ', '<', '>') }
: splittedAdress;
}
private void Form1_Load(object sender, EventArgs e)
{
DirectoryInfo d = new DirectoryInfo(#"C:\...\in");
FileInfo[] Files = d.GetFiles("*.eml");
foreach (FileInfo file in Files)
{
listBox1.Items.Add(file.Name);
}
}
private void button1_Click(object sender, EventArgs e)
{
string oldName = #"C:\...\in\" + listBox1.GetItemText(listBox1.SelectedItem);
var mail = Sasa.Net.Mail.Message.Parse(File.ReadAllText(oldName));
string dt = mail.Headers["Date"].ToString();
DateTimeOffset originalTime = DateTimeOffset.Parse(dt, deCulture);
DateTime utcTime = originalTime.UtcDateTime.ToLocalTime();
string sTime = utcTime.ToString("yyyyMMdd HHmm");
string[] sFrom = getAddressParts(mail.From.ToString());
string sSubject = mail.Subject.Replace(":", "");
String newName = #"C:\...\in\renamed\" + sTime + " -- " + sFrom[1] + " -- " + sSubject + ".eml";
File.Copy(oldName, newName);
File.Delete(oldName);
}
}
}
I have also tried with MimeKit... the same problem exists.

C# WinForms: An unhandled exception of type 'System.IO.IOException' occurred

We have a project to do a program to add and remove universities and had five universities inside our .txt file to show them in our ComboBox.
But it doesn`t work and shows this error:
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Note: It's a Windows Form.
So here's the code:
public partial class Form1 : Form
{
university[] univ = new university[10];
struct university
{
public string uni;
public string prov;
public string city;
public string population;
public string programs;
public string tuition;
public string residence;
}
public Form1()
{
InitializeComponent();
}
private void pictureBox4_Click(object sender, EventArgs e)
{
MessageBox.Show("If you want to check the infomation, click on the combo box and then choose the University of your choice.\n- Click the black button to add a university to the list after filling in everything. \n- Click the red button to remove a university after selecting it.");
}
private void Form1_Load(object sender, EventArgs e)
{
StreamReader sr = new StreamReader("Universities.txt"); // object
String line;
try
{
for (int i = 0; i < univ.Length; i++)
{
line = sr.ReadLine();
string[] sPlit = line.Split(',');
univ[i].uni = sPlit[0];
univ[i].prov = sPlit[1];
univ[i].city = sPlit[2];
univ[i].population = sPlit[3];
univ[i].programs = sPlit[4];
univ[i].tuition = sPlit[5];
univ[i].residence = sPlit[6];
comboBox1.Items.Add(univ[i].uni);
}
sr.Close();
}
catch (Exception p) //catches errors
{
Console.WriteLine("Exception: " + p.Message);
}
finally //final statement before closing
{
Console.WriteLine("Executing finally block.");
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 0)
{
listBox1.Items.Clear();
pictureBox1.Image = Properties.Resources._1;
listBox1.Items.Add("Province: " + univ[0].prov);
listBox1.Items.Add("City: " + univ[0].city);
listBox1.Items.Add("Population: " + univ[0].population);
listBox1.Items.Add("Programs: " + univ[0].programs);
listBox1.Items.Add("Tuition: $" + univ[0].tuition);
listBox1.Items.Add("Residence: $" + univ[0].residence);
}
else if (comboBox1.SelectedIndex == 1)
{
listBox1.Items.Clear();
pictureBox1.Image = Properties.Resources._2;
listBox1.Items.Add("Province: " + univ[1].prov);
listBox1.Items.Add("City: " + univ[1].city);
listBox1.Items.Add("Population: " + univ[1].population);
listBox1.Items.Add("Programs: " + univ[1].programs);
listBox1.Items.Add("Tuition: $" + univ[1].tuition);
listBox1.Items.Add("Residence: $" + univ[1].residence);
}
else if (comboBox1.SelectedIndex == 2)
{
listBox1.Items.Clear();
pictureBox1.Image = Properties.Resources._3;
listBox1.Items.Add("Province: " + univ[2].prov);
listBox1.Items.Add("City: " + univ[2].city);
listBox1.Items.Add("Population: " + univ[2].population);
listBox1.Items.Add("Programs: " + univ[2].programs);
listBox1.Items.Add("Tuition: $" + univ[2].tuition);
listBox1.Items.Add("Residence: $" + univ[2].residence);
}
else if (comboBox1.SelectedIndex == 3)
{
listBox1.Items.Clear();
pictureBox1.Image = Properties.Resources._4;
listBox1.Items.Add("Province: " + univ[3].prov);
listBox1.Items.Add("City: " + univ[3].city);
listBox1.Items.Add("Population: " + univ[3].population);
listBox1.Items.Add("Programs: " + univ[3].programs);
listBox1.Items.Add("Tuition: $" + univ[3].tuition);
listBox1.Items.Add("Residence: $" + univ[3].residence);
}
else if (comboBox1.SelectedIndex == 4)
{
listBox1.Items.Clear();
pictureBox1.Image = Properties.Resources._5;
listBox1.Items.Add("Province: " + univ[4].prov);
listBox1.Items.Add("City: " + univ[4].city);
listBox1.Items.Add("Population: " + univ[4].population);
listBox1.Items.Add("Programs: " + univ[4].programs);
listBox1.Items.Add("Tuition: $" + univ[4].tuition);
listBox1.Items.Add("Residence: $" + univ[4].residence);
}
else
{
pictureBox1.Image = Properties.Resources.noimage;
listBox1.Items.Clear();
}
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void label9_Click(object sender, EventArgs e)
{
}
private void label8_Click(object sender, EventArgs e)
{
}
private void label7_Click(object sender, EventArgs e)
{
}
private void label6_Click(object sender, EventArgs e)
{
}
private void label5_Click(object sender, EventArgs e)
{
}
private void label4_Click(object sender, EventArgs e)
{
}
private void label3_Click(object sender, EventArgs e)
{
}
private void textBox8_TextChanged(object sender, EventArgs e)
{
}
private void textBox7_TextChanged(object sender, EventArgs e)
{
}
private void textBox6_TextChanged(object sender, EventArgs e)
{
}
private void textBox5_TextChanged(object sender, EventArgs e)
{
}
private void textBox4_TextChanged(object sender, EventArgs e)
{
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void AddButton_Click(object sender, EventArgs e)
{
int u = 4;
int p = 4;
int c = 4;
int pop = 4;
int pro = 4;
int t = 4;
int r = 4;
univ[u+1].uni = textBox1.Text;
univ[p + 1].prov = textBox2.Text ;
univ[c + 1].city = textBox3.Text ;
univ[pop + 1].population = textBox4.Text ;
univ[pro + 1].programs = textBox5.Text;
univ[t + 1].tuition = textBox6.Text;
univ[r + 1].residence = textBox7.Text ;
StreamWriter sw = new StreamWriter("Universities.txt", true);
String line;
line = Console.ReadLine();
sw.WriteLine(univ[u + 1].uni + ", " + univ[p + 1].prov + ", " + univ[c + 1].city + ", " + univ[pop + 1].population + "," + univ[pro + 1].programs
+ ", " + univ[t + 1].tuition + "," + univ[r + 1].residence + ",");
MessageBox.Show("A University has been added.");
sw.Close();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("There are " + comboBox1.Items.Count + " universities.");
}
}
}
try
{
// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
string line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
{
//your code goes here
string[] sPlit = line.Split(',');
univ[i].uni = sPlit[0];
univ[i].prov = sPlit[1];
univ[i].city = sPlit[2];
univ[i].population = sPlit[3];
univ[i].programs = sPlit[4];
univ[i].tuition = sPlit[5];
univ[i].residence = sPlit[6];
comboBox1.Items.Add(univ[i].uni);
}
}
}
catch (Exception p) //catches errors
{
Console.WriteLine("Exception: " + p.Message);
}
finally //final statement before closing
{
Console.WriteLine("Executing finally block.");
}
Hope Helps

Index was out of range wpf c#

I have a function that gets the running apps every 10 seconds, place them on a listbox and sends them to the other window if you click the send button. Now the problem is whenever I try to open then immediately close an app, it would send an error pointing to my list.
I'm not sure what to do here.
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index.
Here's my code if in case it brings any help:
private List<int> listedProcesses = new List<int>();
private void SendData()
{
String processID = "";
String processName = "";
String processFileName = "";
String processPath = "";
string hostName = System.Net.Dns.GetHostName();
listBox1.BeginUpdate();
try
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
piis = GetAllProcessInfos();
try
{
if (!listedProcesses.Contains(piis[i].Id)) //place this on a list to avoid redundancy
{
listedProcesses.Add(piis[i].Id);
processID = piis[i].Id.ToString();
processName = piis[i].Name.ToString();
processFileName = piis[i].FileName.ToString();
processPath = piis[i].Path.ToString();
output.Text += "\n\nSENT DATA : \n\t" + processID + "\n\t" + processName + "\n\t" + processFileName + "\n\t" + processPath + "\n";
}
}
catch (Exception ex)
{
wait.Abort();
output.Text += "Error..... " + ex.StackTrace;
}
NetworkStream ns = tcpclnt.GetStream();
String data = "";
data = "--++" + " " + processID + " " + processPath + " " + processFileName + " " + hostName;
if (ns.CanWrite)
{
byte[] bf = new ASCIIEncoding().GetBytes(data);
ns.Write(bf, 0, bf.Length);
ns.Flush();
}
}
}
finally
{
listBox1.EndUpdate();
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
ProcessInfoItem pii = piis.FirstOrDefault(x => x.Id == (int)(sender as ListBox).SelectedValue); //setting value for list box
if (pii != null)
{
string hostName = System.Net.Dns.GetHostName();
textBox4.Text = listBox1.SelectedValue.ToString();
textBox5.Text = (pii.FileName);
textBox6.Text = (pii.Path);
textBox7.Text = hostName;
}
}
private List<ProcessInfoItem> piis = new List<ProcessInfoItem>();
private void Form1_Load(object sender, EventArgs e)
{
piis = GetAllProcessInfos();
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Id";
listBox1.DataSource = piis;
textBox1.Text = GetIpAdd().ToString();
}
private List<ProcessInfoItem> GetAllProcessInfos()
{
List<ProcessInfoItem> result = new List<ProcessInfoItem>();
Process currentProcess = Process.GetCurrentProcess();
Process[] processes = Process.GetProcesses();
foreach (Process p in processes)
{
if (!String.IsNullOrEmpty(p.MainWindowTitle))
{
ProcessInfoItem pii = new ProcessInfoItem(p.Id,p.MainModule.ModuleName, p.MainWindowTitle, p.MainModule.FileName);
result.Add(pii);
}
}
return result;
}
public class ProcessInfoItem
{
public int Id { get; set; }
public string Name { get; set; }
public string FileName { get; set; }
public string Path { get; set; }
public ProcessInfoItem(int id, string name, string filename, string path)
{
this.Id = id;
this.Name = name;
this.FileName = filename;
this.Path = path;
}
}
You are indexing over a different collection that your for loop is referencing. It sounds like you may want:
piis = GetAllProcessInfos();
for (int i = 0; i < piis.Count; i++)
{
instead. However you are calling that function form within the for loop so it's not clear what you should be iterating over.
try to change,
for (int i = 0; i < listBox1.Items.Count; i++)
{
piis = GetAllProcessInfos();
to
piis = GetAllProcessInfos();
for (int i = 0; i < piis.Count; i++)
{

c# BackgroundWorker and Treeview in winform

Env: C#, VStudio 2013, 4.5 Framework, Winforms
Goal : Insert, inside a Treeview, the content of a folder (Sub folder + files) so that user can select those needed. Display a progressbar that show the progress of loading the files and folders in the TreeView.
What i've done so far : Everything in my goal but ...
Error: "This BackgroundWorker is currently busy and cannot run multiple tasks concurrently". I get this error sometimes when I go use other apps while my application is running.
My code :
void backgroundWorkerTreeView_DoWork(object sender, DoWorkEventArgs e)
{
var progress = (((float)(int)e.Argument / (float)totalFilesInTN) * 100);
var value = (int)Math.Round((float)progress);
backgroundWorkerTreeView.ReportProgress(value, e.Argument.ToString());
}
void backgroundWorkerTreeView_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
stStripBarMain.Value = e.ProgressPercentage;
toolStripStatusLabelPrct.Text = " Loading " + e.UserState + " of " + totalFilesInTN;
}
void backgroundWorkerTreeView_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//do the code when bgv completes its work
}
private void ListDirectory(TreeView treeView, string path)
{
try
{
treeView.Nodes.Clear();
if (path != "")
{
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo, 0));
}
}
catch (Exception e)
{
txtLog.Text = txtLog.Text + "[" + DateTime.Now + "] " + e.Message + "\r\n";
}
}
private TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo, int indice)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
if ((directory.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory, indice));
}
}
foreach (var file in directoryInfo.GetFiles())
{
if ((IsNullOrEmpty(ext)) ||
(Array.IndexOf(ext, Path.GetExtension(file.Name.ToLowerInvariant())) >= 0))
{
if ((GetTriggerEvent(file.FullName).Contains(txtParamEvent.Text)) || (txtParamEvent.Text == ""))
{
indice++;
backgroundWorkerTreeView.RunWorkerAsync(indice);
TreeNode newTN = new TreeNode();
newTN.Text = file.Name + #" (" + GetTriggerEvent(file.FullName) + #")";
newTN.Name = file.FullName;
directoryNode.Nodes.Add(newTN);
newTN.Tag = "msg";
}
}
Application.DoEvents();
}
return directoryNode;
}
Thanks for the help
Richard

how to repeating thread from looping inside timer in C#

I have data list from XML, and I want all the item in the list sent to bw_ViewJob_DoWork in my case but I only have the first data of the list in the bw_ViewJob_DoWork as a Trigger:
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
gIP = cmbIP.Text;
timer1.Interval = 2000;
}
Trigger sends here:
private void timer1_Tick(object sender, EventArgs e)
{
string val = "";
for (int i = 0; i < listJob.Items.Count; i++)
{
val = listJob.Items[i].ToString().Substring(0, 4);
WriteLog("Job: [" + val + "] Viewed");
if (bw_ViewJob.IsBusy)
{
bw_ViewJob.CancelAsync();
WriteLog("Job: [" + val + "] Cancel");
}
else
{
bw_ViewJob.RunWorkerAsync(val);
}
}
}
And timer executes this thread infinite-loop every 30s
private void bw_ViewJob_DoWork(object sender, DoWorkEventArgs e)
{
WebRequest request;
Stream dataStream;
StreamReader reader;
string oStatus;
string responseFromServer;
gIP = cmbIP.Text;
string oURL = "https://" + gIP + "/hp/device/hp.extensibility.ec.clientservices.api?api=jobs&method=view&jobId=" + e.Argument;
byPassCert();
int i = 0;
oStatus = "pending";
WriteLog("oURL: [" + oURL + "]");
while (oStatus == "pending")
{
try
{
if (i > 0) { System.Threading.Thread.Sleep(1000); }
if (bw_ViewJob.CancellationPending)
{
e.Cancel = true;
break;
}
request = WebRequest.Create(oURL);
request.Method = "GET";
dataStream = request.GetResponse().GetResponseStream();
reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
// Get Job Info
XmlDocument oXML = new XmlDocument();
oXML.LoadXml(responseFromServer);
oStatus = oXML.DocumentElement.SelectSingleNode("Content/Job").Attributes.GetNamedItem("status").Value;
if (oStatus == "cancelled")
{
e.Cancel = true;
break;
}
i++;
}
catch (Exception eX)
{
MessageBox.Show(eX.Message, "View Job Error");
}
}
e.Result = responseFromServer;
}
private void bw_ViewJob_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
WriteLog(e.Error + ", Job Cancelled");
}
else
{
WriteLog("View Job done. JobID: " + gJobID);
WriteLog("" + e.Result + ", Still Pending, trying view another job");
}
}
I have tried List<string> and lock() but the thread just receives the first item on the list. I have tried timer loop inside the thread but I get the opposite result; the thread only has the last item on the list, I suspect.
if (bw_ViewJob.IsBusy)
{
bw_ViewJob.CancelAsync();
WriteLog("Job: [" + val + "] Cancel");
}
So I think I have to pause the loop at timer and resume again after the thread finishes without repeating the loop from the first data. How do I do that?

Categories