-1

sorry for bugging you guys with such a small problem, but I cannot find a solution. I have created one class for getting attachments from exchange server and Form for adding server configuration and textbox which I attend to use for the log output. I have added backgroundWorker to create separate thread and when class gets right attachment and collect info for the output, it redirects to backgroundWorker DoWork method. The problem is that UI of the textbox is simply doesn't want to append text

Class for downloading attachment looks like:

namespace DownloadAttachmentExchange
{
    class ExchangeDwnClass
    {
    private string path_ = "";
    private string filterSender_ = "";
    private string subject_ = "";
    private string id_ = "";
    private string username_ = "";
    private string password_ = "";
    private string exchange_ = "";
    private string filterExcel_ = "";
    private string filterCSV_ = "";
    private string attachmentName_ = "";
    private int emailFetch_ = 0;
    private DateTime current_;

    ExchangeService serv = new ExchangeService(ExchangeVersion.Exchange2010_SP1);


    public string Path
    {
        get { return path_; }
        set { path_ = value; }
    }
    public string FilterSender
    {
        get { return filterSender_; }
        set { filterSender_ = value; }
    }
    public string Subject
    {
        get { return subject_; }
        set { subject_ = value; }
    }
    public string ID
    {
        get { return id_; }
        set { id_ = value; }
    }
    public string Username
    {
        get { return username_; }
        set { username_ = value; }
    }
    public string Password
    {
        get { return password_; }
        set { password_ = value; }
    }
    public string Exchange
    {
        get { return exchange_; }
        set { exchange_ = value; }
    }
    public string FilterExcel
    {
        get { return filterExcel_; }
        set { filterExcel_ = value; }    
    }
    public string FilterCsv
    {
        get { return filterCSV_; }
        set { filterCSV_ = value; }
    }
    public string AttachementName
    {
        get { return attachmentName_; }
        set { attachmentName_ = value; }
    }
    public int EmailFetch
    {
        get { return emailFetch_; }
        set { emailFetch_ = value; }
    }
    public DateTime CurrentDate
    {
        get { return current_; }
        set { current_ = value; }
    }

    public void GetAttachments()
    {
        try
        {  
            serv.Credentials = new WebCredentials(Username, Password);
            serv.AutodiscoverUrl(Exchange);

            ItemView view = new ItemView(10);
            FindItemsResults<Item> result = serv.FindItems(WellKnownFolderName.Inbox, new ItemView(EmailFetch));

            if (result != null && result.Items != null && result.Items.Count > 0)
            {
                foreach (Item item in result.Items)
                {
                    EmailMessage msg = EmailMessage.Bind(serv, item.Id, new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments, ItemSchema.HasAttachments, EmailMessageSchema.From, EmailMessageSchema.Sender));
                    if (msg.Sender.ToString().Contains(FilterSender) && msg.From.ToString().Contains(FilterSender))
                    {
                        foreach (Attachment att in msg.Attachments)
                        {
                            if (att is FileAttachment)
                            {
                                FileAttachment file = att as FileAttachment;
                                if (file.Name.Contains(FilterExcel) || file.Name.Contains(FilterCsv))
                                {
                                    Form1 form = new Form1();
                                    file.Load(Path +"\\"+ file.Name);
                                    AttachementName = file.Name.ToString();
                                    Subject = item.Subject.ToString();
                                    ID = item.Id.ToString();
                                    CurrentDate = DateTime.Now;                                 
                                    form.date = CurrentDate.ToString();
                                    form.subject = Subject;
                                    form.attachment = AttachementName;         
                                    form.backgroundWorker1.RunWorkerAsync();
                                    Thread.Sleep(60000);
                                }
                            }
                        }
                    }
                    //item.Delete(DeleteMode.HardDelete);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        Console.ReadLine();
    }
    public void StopDownloadingAttachment()
    { 

    }
}
}

Form looks like this:

namespace DownloadAttachmentExchange
{
public partial class Form1 : Form
{
    private string path = "";
    public string date = "";
    public string attachment = "";
    public string subject = "";
    public Form1()
    {
        InitializeComponent();
    }
    ExchangeDwnClass exchange = new ExchangeDwnClass();
    private void button3_Click(object sender, EventArgs e)
    {
        if(folderBrowserDialog1.ShowDialog(this)== DialogResult.OK)
        {
            path = folderBrowserDialog1.SelectedPath;   
            exchange.Path = path;
            pathTxt.Text = path;
        }
    }

    private void onBtn_Click(object sender, EventArgs e)
    {
        exchange.Username = userTxt.Text;
        exchange.Password = passwdTxt.Text;
        exchange.FilterSender = fromFilterTxt.Text;
        exchange.EmailFetch = Convert.ToInt32(fetchUpDown.Value);
        exchange.Exchange = exchangeTxt.Text;
        exchange.GetAttachments();
    }

    private void filterExcelCheck_CheckedChanged(object sender, EventArgs e)
    {
        if (filterExcelCheck.CheckState == CheckState.Checked)
        {
            exchange.FilterExcel = ".xlsx";
        }
        else
        {
            exchange.FilterExcel = "";
        }
    }

    private void filterCSVCheck_CheckedChanged(object sender, EventArgs e)
    {
        if (filterCSVCheck.CheckState == CheckState.Checked)
        {
            exchange.FilterCsv = ".csv";
        }
        else
        {
            exchange.FilterCsv = "";
        }
    }

    private void exchangeTxt_MouseHover(object sender, EventArgs e)
    {
        tipLbl.Visible = true;
        tipLbl.Text = "It is usually same as email address...";
    }

    private void exchangeTxt_MouseLeave(object sender, EventArgs e)
    {
        tipLbl.Visible = false;
    }
    //("\n" + CurrentDate.ToString() + " , Message id: " + ID + " , Message subject: " + Subject + " , Attachment name: " + AttachementName + "\r");
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        //e.Result = "\n" + date + " , Message subject: " + subject + " , Attachment name: " + attachment + "\r";
        logOutputTxt.Text = "\n" + date + " , Message subject: " + subject + " , Attachment name: " + attachment + "\r";
        //backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
    }

    //private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    //{
    //    if (e.Cancelled)
    //    {
    //        logOutputTxt.Text = "Thread is somehow cancelled, please contact developer for this issue...!";
    //    }
    //    else if (e.Error != null)
    //    {
    //        logOutputTxt.Text = e.Error.Message;
    //    }
    //    else
    //    {
    //        logOutputTxt.Text += e.Result;
    //    }
    //}
}
}

as you can see I'm calling background worker from class ExchangeDwnClass which I believe is OK, by using:

form.backgroundWorker1.RunWorkerAsync();

and when I run debugger it really jumps to background worker

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    logOutputTxt.Text = "\n" + date + " , Message subject: " + subject + " , Attachment name: " + attachment + "\r";
    //backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
}

for some reason Form textbox control is not refreshing output. p.s. I have created also on RunWorkerCompleted method but also without luck...

Any clue how can I work things out?

dovla110010101
  • 411
  • 2
  • 9
  • 21
  • 2
    You cant update a UI control from a background thread like that. You will need to use `Control.Invoke` to update your `TextBox`. – Yuval Itzchakov Sep 27 '14 at 11:31
  • Hi Yuval, can you post some example for it? – dovla110010101 Sep 27 '14 at 11:38
  • Just search it: **"Update the GUI controls from another thread"** – Mehdi Khademloo Sep 27 '14 at 11:38
  • See it: http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c – Mehdi Khademloo Sep 27 '14 at 11:39
  • I have changed part in backgroundWorker in Form class to: public delegate void MethodInvoker(); private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { this.Invoke((MethodInvoker)delegate() { logOutputTxt.Text += "\n" + date + " , Message subject: " + subject + " , Attachment name: " + attachment + "\r"; }); But now i get exception: Invoke or BeginInvoke cannot be called on a control until the window handle has been created. Any idea how to fix this? – dovla110010101 Sep 27 '14 at 15:53

1 Answers1

0

OK, the problem was that I have created another object in form ExchangeDowClass for Form1, instead of passing a reference object into method GetAttachments

complete code for Form1:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DownloadAttachmentExchange
{
public partial class Form1 : Form
{
    private string path = "";
    public string subject = "";
    public string attachment = "";
    public string date = "";
    public string sender = "";
    public Form1()
    {
        InitializeComponent();
    }
    ExchangeDwnClass exchange = new ExchangeDwnClass();
    BackgroundWorker bgrWorker = new BackgroundWorker();
    private void button3_Click(object sender, EventArgs e)
    {
        if(folderBrowserDialog1.ShowDialog(this)== DialogResult.OK)
        {
            path = folderBrowserDialog1.SelectedPath;   
            exchange.Path = path;
            pathTxt.Text = path;
        }
    }

    private void onBtn_Click(object sender, EventArgs e)
    {
        exchange.EmailFetch=Convert.ToInt32(fetchUpDown.Value);
        exchange.FilterSender = fromFilterTxt.Text;
        exchange.Exchange = exchangeTxt.Text;
        exchange.Password = passwdTxt.Text;
        exchange.Username = userTxt.Text;
        backgroundWorker1.RunWorkerAsync();
    }

    private void filterExcelCheck_CheckedChanged(object sender, EventArgs e)
    {
        if (filterExcelCheck.CheckState == CheckState.Checked)
        {
            exchange.FilterExcel = ".xlsx";
        }
        else
        {
            exchange.FilterExcel = "";
        }
    }

    private void filterCSVCheck_CheckedChanged(object sender, EventArgs e)
    {
        if (filterCSVCheck.CheckState == CheckState.Checked)
        {
            exchange.FilterCsv = ".csv";
        }
        else
        {
            exchange.FilterCsv = "";
        }
    }

    private void exchangeTxt_MouseHover(object sender, EventArgs e)
    {
        tipLbl.Visible = true;
        tipLbl.Text = "It is usually same as email address...";
    }

    private void exchangeTxt_MouseLeave(object sender, EventArgs e)
    {
        tipLbl.Visible = false;
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        //logOutputTxt.Text += "\n" + date + " , Message subject: " + subject + " , Attachment name: " + attachment + "\r"
        //backgroundWorker1.ReportProgress(0);
        exchange.GetAttachments(this);
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        logOutputTxt.Text += "\n" + date + " , Sender: "+sender+" , Message subject: " + subject + " , Attachment name: " + attachment + "\r";
    }

}
}

and for ExchangeDwnClass:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Exchange;
using Microsoft.Exchange.WebServices;
using Microsoft.Exchange.WebServices.Data;
using System.Threading;

namespace DownloadAttachmentExchange
{
class ExchangeDwnClass
{
    private string path_ = "";
    private string filterSender_ = "";
    private string subject_ = "";
    private string id_ = "";
    private string username_ = "";
    private string password_ = "";
    private string exchange_ = "";
    private string filterExcel_ = "";
    private string filterCSV_ = "";
    private string attachmentName_ = "";
    private int emailFetch_ = 0;
    private DateTime current_;

    ExchangeService serv = new ExchangeService(ExchangeVersion.Exchange2010_SP1);

    public string Path
    {
        get { return path_; }
        set { path_ = value; }
    }
    public string FilterSender
    {
        get { return filterSender_; }
        set { filterSender_ = value; }
    }
    public string Subject
    {
        get { return subject_; }
        set { subject_ = value; }
    }
    public string ID
    {
        get { return id_; }
        set { id_ = value; }
    }
    public string Username
    {
        get { return username_; }
        set { username_ = value; }
    }
    public string Password
    {
        get { return password_; }
        set { password_ = value; }
    }
    public string Exchange
    {
        get { return exchange_; }
        set { exchange_ = value; }
    }
    public string FilterExcel
    {
        get { return filterExcel_; }
        set { filterExcel_ = value; }    
    }
    public string FilterCsv
    {
        get { return filterCSV_; }
        set { filterCSV_ = value; }
    }
    public string AttachementName
    {
        get { return attachmentName_; }
        set { attachmentName_ = value; }
    }
    public int EmailFetch
    {
        get { return emailFetch_; }
        set { emailFetch_ = value; }
    }
    public DateTime CurrentDate
    {
        get { return current_; }
        set { current_ = value; }
    }

    public void GetAttachments(Form1 form)
    {
        try
        {  
            serv.Credentials = new WebCredentials(Username, Password);
            serv.AutodiscoverUrl("username@domain.lan");

            ItemView view = new ItemView(EmailFetch);
            FindItemsResults<Item> result = serv.FindItems(WellKnownFolderName.Inbox, new ItemView(EmailFetch));

            if (result != null && result.Items != null && result.Items.Count > 0)
            {
                foreach (Item item in result.Items)
                {
                    EmailMessage msg = EmailMessage.Bind(serv, item.Id, new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments, ItemSchema.HasAttachments, EmailMessageSchema.From, EmailMessageSchema.Sender));
                    if (msg.Sender.ToString().ToLower().Contains(FilterSender) && msg.From.ToString().ToLower().Contains(FilterSender))
                    {
                        foreach (Attachment att in msg.Attachments)
                        {
                            if (att is FileAttachment)
                            {
                                FileAttachment file = att as FileAttachment;
                                if (file.Name.Contains(FilterExcel) || file.Name.Contains(FilterCsv))
                                {
                                    file.Load(Path +"\\"+ file.Name);
                                    form.attachment = file.Name.ToString();
                                    form.subject = item.Subject.ToString();
                                    //ID = item.Id.ToString();
                                    form.date = DateTime.Now.ToString();
                                    form.sender = msg.Sender.ToString();
                                    form.backgroundWorker1.ReportProgress(0);
                                    Thread.Sleep(60000);
                                }
                            }
                        }
                    }
                    //item.Delete(DeleteMode.HardDelete);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        Console.ReadLine();
    }
    public void StopDownloadingAttachment()
    { 

    }
}
}

Plus I had to use ProgressChanged method to refresh control... I still have some minor bugs like double output in textbox form, but this is basically small issue. I hope this code will be useful to others.

Cheers.

dovla110010101
  • 411
  • 2
  • 9
  • 21