C # - Outlook VSTO - Получение AdvancedSearchComplete для запуска - PullRequest
0 голосов
/ 10 октября 2018

Я преобразую старый макрос Outlook VBA, который я создал, в надстройку C # VSTO.Этот инструмент предназначен для массового архивирования электронных писем в различные общие папки и локальный файл PST и должен иметь возможность находить электронные письма на основе критериев поиска пользователя.У меня было огромное количество времени для получения события AdvancedSearchComplete для запуска в VBA, но в конце концов оно заработало.Конечно, теперь у меня такая же проблема в надстройке C # VSTO.

Чтобы использовать инструмент, пользователь вводит свои критерии в пользовательской форме, а затем нажимает Найти электронные письма кнопка, чтобы выполнить поиск с результатами, заполняющими представление данных.

public partial class Email_Archiver : Form
{

    public Email_Archiver()
    {
        InitializeComponent();

        //Add event handlers
        Globals.ThisAddIn.Application.AdvancedSearchComplete += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_AdvancedSearchCompleteEventHandler(Application_AdvancedSearchComplete);
    }

    public void Application_AdvancedSearchComplete(Microsoft.Office.Interop.Outlook.Search SearchObject)
    { //Handles AdvancedSearchComplete event

        if (SearchObject.Tag == "Archiver Search")
        {
            OutlookFunctions.SearchComplete = true;
            MessageBox.Show(this, "Search Complete!","Email Search Error",MessageBoxButtons.OK);
        }

    }

    private void Find_Button_Click(object sender, EventArgs e)
    {

        //Set datagridview datasource
        EmailList.DataSource = FindEmails();
        EmailList.Columns["EntryID"].Visible = false;

    }

    public DataTable FindEmails()
    {
        var dt = new DataTable();

        //Format DataTable
        dt.Columns.Add("EntryID", typeof(string));
        dt.Columns.Add("Project No.", typeof(int));
        dt.Columns.Add("Subject", typeof(string));
        dt.Columns.Add("Sender", typeof(string));
        dt.Columns.Add("Recipient", typeof(string));
        dt.Columns.Add("Time Sent", typeof(DateTime));
        dt.Columns.Add("Size", typeof(decimal));

        //Do stuff to get "searchFolders" and "searchCriteria" from form
        //...

        dt = OutlookFunctions.RunAdvancedSearch(searchFolders, searchCriteria);

        return dt;
    }
}


class OutlookFunctions
{

    public static bool SearchComplete;

    public static DataTable RunAdvancedSearch(string[] searchFolders, string[] searchCriteria)
    {

        //Get Outlook namespace
        var oApp = Globals.ThisAddIn.Application;
        var oNS = oApp.GetNamespace("mapi");
        Microsoft.Office.Interop.Outlook.Search advSearch = null;

        //Do other stuff to properly set up the scope and filter
        //...

        //Perform search
        SearchComplete = false;
        try
        {
            advSearch = oApp.AdvancedSearch(scope, filter, false, "Archiver Search");
        }
        catch (System.Exception ex)
        {
            MessageBox.Show("An error has occurred during the search for emails. \n \n"
                    + ex.Message);
            return null;
        }

        Stopwatch timer = new Stopwatch();
        timer.Start();

        while (!SearchComplete && timer.Elapsed.TotalSeconds < 10)
        {
            //Do nothing
        }

        if (!SearchComplete)
        {
            advSearch.Stop();
        }

        if (advSearch != null)
        {
            var resultTable = new DataTable();

            //Send results to resultTable

            return resultTable;
        }

        return null;

    }

}

Поиск работает, и я получаю правильные результаты, но мне пришлось добавить в таймер, чтобы все пошло дальше, иначе код никогда не завершитсяпотому что AdvancedSearchComplete не срабатывает.Я по-прежнему получаю все электронные письма, которые я ищу, и выполняю по существу один и тот же поиск только в проводнике Outlook, я получаю те же результаты за доли секунды.

После того, как таймер завершит поиск иdatagridview заполнен результатами, ТОГДА AdvancedSearchComplete срабатывает, и я получаю "Поиск завершен!"сообщение.

Что мне здесь не хватает, что мешает событию инициировать поиск (своевременно)?

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Похоже, что любой код, следующий за инициацией для метода AdvancedSearch, по существу завершит поиск, не вызывая события AdvancedSearchComplete или AdvancedSearchStopped.

Вместо этого у меня теперь есть следующее в классе ThisAddIn:

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    //Create task pane object
    archiverTaskPane1 = new ArchiverTaskPane();
    customTaskPane = this.CustomTaskPanes.Add(archiverTaskPane1, "Title");

    //Add event handler for opening task pane
    customTaskPane.VisibleChanged += new EventHandler(customTaskPane_VisibleChanged);

    //Add event handler for Outlook's AdvancedSearch
    Globals.ThisAddIn.Application.AdvancedSearchComplete += new Outlook.ApplicationEvents_11_AdvancedSearchCompleteEventHandler(Application_AdvancedSearchComplete);
}

public void Application_AdvancedSearchComplete(Microsoft.Office.Interop.Outlook.Search SearchObject)
{
    DataTable dt = new DataTable();
    OutlookFunctions oFunctions = new OutlookFunctions();
    dt = oFunctions.BuildResults(SearchObject.Results);
    this.archiverTaskPane1.DataGridFiller(dt);
}

В классе ArchiverTaskPane (ранее форма Email_Archiver - мне очень понравилась идея панели задач)

private void Find_Button_Click(object sender, EventArgs e)
{
    FindEmails();
}

public void FindEmails()
{
    DataTable dt = new DataTable();

    //Add columns to DataTable

    //Do stuff to get "searchFolders" and "searchCriteria" from form
    //...

    //Create OutlookFunctions instance
    OutlookFunctions oFunctions = new OutlookFunctions();
    oFunctions.RunAdvancedSearch(searchFolders, searchCriteria);
}

public void DataGridFiller(DataTable results)
{
    EmailList.DataSource = results;
}

В классе OutlookFunctions:

public static DataTable RunAdvancedSearch(string[] searchFolders, string[] searchCriteria)
{
    //Get Outlook namespace
    var oApp = Globals.ThisAddIn.Application;
    var oNS = oApp.GetNamespace("mapi");
    Microsoft.Office.Interop.Outlook.Search advSearch = null;

    //Do other stuff to properly set up the scope and filter
    //...

    //Perform search
    SearchComplete = false;
    try
    {
        advSearch = oApp.AdvancedSearch(scope, filter, false, "Archiver Search");
    }
    catch (System.Exception ex)
    {
        MessageBox.Show("An error has occurred during the search for emails. \n \n"
                + ex.Message);
    }
}

public DataTable BuildResults(Results searchResults)
{
    DataTable resultTable = new DataTable();

    //Do stuff to build DataTable from search results
    //...

    return resultTable;
}
0 голосов
/ 12 октября 2018

Вы можете обратиться к следующему коду об использовании фоновой работы:

BackgroundWorker bw = new BackgroundWorker();
    private void button1_Click(object sender, EventArgs e)
    {
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        if (bw.IsBusy != true)
        {
            bw.RunWorkerAsync();
        }
    }
    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        //
        // Boring.... Do your long work
        //
        System.Threading.Thread.Sleep(20000);
    }
    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (this.InvokeRequired)
        {
            //Hide your form here
            this.Invoke(new MethodInvoker(delegate { this.Close(); }));
        }
    }
...