C# - Outlook VSTO - 让 AdvancedSearchComplete 触发
C# - Outlook VSTO - Getting AdvancedSearchComplete to trigger
我正在将我创建的旧 Outlook VBA 宏转换为 C# VSTO 加载项。此工具用于将电子邮件批量归档到各种 public 文件夹和本地 .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
触发并且我收到 "Search Complete!" 消息。
我在这里遗漏了什么阻止事件触发以结束搜索(及时)?
使用backgroundwork可以参考以下代码:
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(); }));
}
}
看来,启动 AdvancedSearch 方法后的任何代码基本上都会结束搜索,而不会触发 AdvancedSearchComplete 或 AdvancedSearchStopped 事件。
相反,我现在在 ThisAddIn class 中有以下内容:
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 Class(以前的 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 中 Class:
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;
}
我正在将我创建的旧 Outlook VBA 宏转换为 C# VSTO 加载项。此工具用于将电子邮件批量归档到各种 public 文件夹和本地 .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
触发并且我收到 "Search Complete!" 消息。
我在这里遗漏了什么阻止事件触发以结束搜索(及时)?
使用backgroundwork可以参考以下代码:
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(); }));
}
}
看来,启动 AdvancedSearch 方法后的任何代码基本上都会结束搜索,而不会触发 AdvancedSearchComplete 或 AdvancedSearchStopped 事件。
相反,我现在在 ThisAddIn class 中有以下内容:
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 Class(以前的 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 中 Class:
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;
}