小枕头你别跑 发表于 2024-6-24 13:59:37

我的Office Outlook插件开发之旅(二)

下面将完成的展示,使用MAPI接口操作Outlook完成通讯录更新。

using Microsoft.Office.Interop.Outlook;
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AddressBookTool2
{
    class Program
    {
      static void Main(string[] args)
      {
            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);

            bool isAlreadyRunning = false;
            foreach (Process process in processes)
            {
                if (process.Id != current.Id)
                {
                  // 检查路径以确保是同一个可执行文件的另一个实例
                  if (process.MainModule.FileName == current.MainModule.FileName)
                  {
                        isAlreadyRunning = true;
                        break;
                  }
                }
            }

            if (isAlreadyRunning)
            {

            }
            else
            {
                while (true)
                {
                  Action();
                  Thread.Sleep(1000 * 60 * 15);
                }
            }
      }
      const string conn = "Server=192.168.100.99;Database=帆软报表;uid=sa;pwd=dsc";

      /// <summary>
      /// 动作
      /// </summary>
      public static void Action()
      {
            string ipAddress = "192.168.100.99";
            Ping ping = new Ping();
            PingReply pingReply = ping.Send(ipAddress);
            if (pingReply.Status != IPStatus.Success) return;
            UpdateClient();
            const string sql = "SELECT Guid,应用名称,版本,备注 FROM 帆软报表.dbo.版本控制 WHERE 应用名称 = N'集团通讯录'";
            List<Dictionary<string, object>> list = SelectList(sql, conn);
            if (list.Count > 0)
            {
                string version = list["版本"].ToString();
                if (string.IsNullOrEmpty(version)) return;
                string path = $"{Environment.CurrentDirectory}\\Version.conf";
                if (!File.Exists(path))
                {
                  UpdateAddressBook();
                  File.WriteAllText(path, version.Trim());
                }
                else
                {
                  string content = "";
                  foreach (string item in File.ReadLines(path))
                  {
                        content += item;
                  }
                  if (content.Trim() != version.Trim())
                  {
                        UpdateAddressBook();
                        File.WriteAllText(path, version.Trim());
                  }
                }
            }
      }

      /// <summary>
      /// 更新客户端
      /// </summary>
      public static void UpdateClient()
      {
            string ipAddress = "192.168.100.18";
            Ping ping = new Ping();
            PingReply pingReply = ping.Send(ipAddress);
            if (pingReply.Status != IPStatus.Success) return;

            const string sql = "SELECT Guid,应用名称,版本,备注 FROM 帆软报表.dbo.版本控制 WHERE 应用名称 = N'集团通讯录客户端'";
            List<Dictionary<string, object>> list = SelectList(sql, conn);
            if (list.Count > 0)
            {
                string version = list["版本"].ToString();
                string path = $"{Environment.CurrentDirectory}\\ClientVersion.conf";
                if (!File.Exists(path))
                {
                  File.WriteAllText(path, version.Trim());
                  UpdateClientAction();
                  Environment.Exit(0);
                }
                else
                {
                  string content = "";
                  foreach (string item in File.ReadLines(path))
                  {
                        content += item;
                  }
                  if (content.Trim() != version.Trim())
                  {
                        File.WriteAllText(path, version.Trim());
                        UpdateClientAction();
                        Environment.Exit(0);
                  }
                }
            }
      }

      /// <summary>
      /// 更新客户端行动
      /// </summary>
      public static void UpdateClientAction()
      {
            string batPath = $"{Environment.CurrentDirectory}\\temp.bat";
            string cmdText = $"@echo off{Environment.NewLine}timeout /t 3 /nobreak >nul{Environment.NewLine}start {Environment.CurrentDirectory}\\updater.bat \"{Environment.CurrentDirectory}\" \"{Environment.CurrentDirectory}\\AddressBookTool2.exe\"{Environment.NewLine}eixt";
            File.WriteAllText(batPath, cmdText, Encoding.UTF8);
            ProcessStartInfo psi = new ProcessStartInfo()
            {
                FileName = batPath,
                CreateNoWindow = true,
                RedirectStandardError = true,
                UseShellExecute = false
            };
            using (Process process = new Process())
            {
                process.StartInfo = psi;
                process.Start();
            }
      }

      /// <summary>
      /// 更新通讯录
      /// </summary>
      public static void UpdateAddressBook()
      {
            const string sql = "SELECT 邮箱地址 AS 'emailAddress',姓氏 AS 'firstName',姓名 AS 'lastName', 群组 AS 'group' FROM [帆软报表]..[集团邮箱通讯录] WHERE 邮箱地址 IS NOT NULL AND (姓氏 IS NOT NULL OR 姓名 IS NOT NULL)";
            List<Dictionary<string, object>> list = SelectList(sql, conn);
            List<Contact> contacts = new List<Contact>();
            list.ForEach(it =>
            {
                string firstName = it["firstName"].ToString()?.Trim();
                string lastName = it["lastName"].ToString()?.Trim();
                string emailAddress = it["emailAddress"].ToString()?.Trim();
                string group = it["group"].ToString()?.Trim();
                int index = group.IndexOf(",");
                if (index >= 0)
                {
                  string[] groupList = group.Split(',');
                  groupList.ToList().ForEach(g =>
                  {
                        Contact contact = new Contact()
                        {
                            FirstName = firstName,
                            LastName = lastName,
                            EmailAddress = emailAddress,
                            Group = g
                        };
                        contacts.Add(contact);
                  });
                }
                else
                {
                  Contact contact = new Contact()
                  {
                        FirstName = firstName,
                        LastName = lastName,
                        EmailAddress = emailAddress,
                        Group = group
                  };
                  contacts.Add(contact);
                }
            });

            if (contacts.Count == 0) return;
            GeneractionStroe(contacts, false, "通讯录", true, "汤石集团通讯录");
            GeneractionStroe(contacts, false, "通讯录", false, "湯石集團通訊錄");
      }



      public static void GeneractionStroe(List<Contact> contacts, bool order, string fileName, bool CH_zh, string addressBookName)
      {
            // 繁简转换
            contacts = ContactsLang(contacts, CH_zh);

            // 创建Store,也就是PST档
            Microsoft.Office.Interop.Outlook.Application outlookApp = new Microsoft.Office.Interop.Outlook.Application();
            NameSpace session = outlookApp.GetNamespace("MAPI");
            string path = $"{Environment.CurrentDirectory}\\{fileName}.pst";
            Store store = GetStore(session, path, 5);

            MAPIFolder contactFolder = GetAddressBookFolder(store, addressBookName);
            // 移除就的联系人
            int count = contactFolder.Items.Count;
            for (int i = 0; i < count; i++)
            {
                contactFolder.Items.Remove(1);
            }
            MAPIFolder deteledItems = store.GetDefaultFolder(OlDefaultFolders.olFolderDeletedItems);
            count = deteledItems.Items.Count;
            for (int i = 0; i < count; i++)
            {
                deteledItems.Items.Remove(1);
            }

            // 新增联系人
            contacts.Distinct(new ContactEqualityComparer()).ToList().ForEach(contact =>
            {
                if (!string.IsNullOrEmpty(contact.FirstName) && !string.IsNullOrEmpty(contact.LastName))
                {
                  ContactItem newContact = contactFolder.Items.Add(OlItemType.olContactItem);
                  OrderContactItem(contact.FirstName, contact.LastName, order, newContact);
                  newContact.Email1Address = contact.EmailAddress;
                  newContact.Save();
                  System.Runtime.InteropServices.Marshal.ReleaseComObject(newContact);
                  newContact = null;
                }
            });

            // 新增群组
            contacts.GroupBy(it => it.Group).Select(it => new
            ContactGroup()
            {
                Group = it.Key,
                Contacts = it.ToList()
            }).ToList().ForEach(it =>
            {
                if (!string.IsNullOrEmpty(it.Group))
                {
                  DistListItem dist = contactFolder.Items.Add(OlItemType.olDistributionListItem);
                  it.Contacts.ForEach(contact =>
                  {
                        Recipient recipient = outlookApp.Session.CreateRecipient(contact.FirstName + contact.LastName + "(" + contact.EmailAddress + ")");
                        if (recipient.Resolve())
                        {
                            dist.AddMember(recipient);
                        }
                  });
                  dist.DLName = it.Group;
                  dist.Save();
                  // 确保所有项已从新创建的PST中释放
                  System.Runtime.InteropServices.Marshal.ReleaseComObject(dist);
                  dist = null;
                }
            });

            // 清理Outlook对象,避免内存泄漏
            System.Runtime.InteropServices.Marshal.ReleaseComObject(session);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(outlookApp);
            outlookApp = null;
            session = null;
      }


      /// <summary>
      /// 获取Store
      /// </summary>
      /// <param name="session">命名控件</param>
      /// <param name="target">目标pst档</param>
      /// <param name="count">最大递归次数</param>
      /// <returns></returns>
      public static Store GetStore(NameSpace session, string target, int count)
      {
            Store store = null;
            foreach (Store it in session.Stores)
            {
                if (it.FilePath == target)
                {
                  store = it;
                  break;
                }
            }
            if (store == null && count > 0)
            {
                session.AddStore(target);
                return GetStore(session, target, count--);
            }
            return store;
      }

      /// <summary>
      /// 获取联系人文件夹
      /// </summary>
      /// <param name="store">Store实例</param>
      /// <param name="name">文件夹名称</param>
      /// <returns></returns>
      public static MAPIFolder GetAddressBookFolder(Store store, string name)
      {
            MAPIFolder folder = null;
            Folders folders = store.GetDefaultFolder(OlDefaultFolders.olFolderContacts).Folders;
            foreach (MAPIFolder item in folders)
            {
                if (item.Name == name)
                {
                  folder = item;
                  break;
                }
            }
            if (folder == null)
            {
                folder = store.GetDefaultFolder(OlDefaultFolders.olFolderContacts).Folders.Add(name);
                folder.ShowAsOutlookAB = true;// 设置成联系人
            }
            return folder;
      }

      /// <summary>
      /// 转换语言,简体转繁体
      /// </summary>
      /// <param name="contacts">联系人信息集合</param>
      /// <param name="lang">是否转繁体</param>
      /// <returns></returns>
      public static List<Contact> ContactsLang(List<Contact> contacts, bool lang)
      {
            List<Contact> result = new List<Contact>();
            if (lang)
            {
                return contacts;
            }
            else
            {
                contacts.ForEach(it =>
                {
                  it.FirstName = Strings.StrConv(it.FirstName, VbStrConv.TraditionalChinese);
                  it.LastName = Strings.StrConv(it.LastName, VbStrConv.TraditionalChinese);
                  it.Group = Strings.StrConv(it.Group, VbStrConv.TraditionalChinese);
                  result.Add(it);
                });
            }

            return result;
      }

      /// <summary>
      /// 转换联系人的姓与名位置
      /// </summary>
      /// <param name="firstName">姓氏</param>
      /// <param name="lastName">名字</param>
      /// <param name="order">顺序</param>
      /// <param name="contact">联系人实例</param>
      public static void OrderContactItem(string firstName, string lastName, bool order, ContactItem contact)
      {
            if (order)
            {
                contact.FirstName = firstName;
                contact.LastName = lastName;
            }
            else
            {
                contact.LastName = firstName;
                contact.FirstName = lastName;
            }
      }

      public struct Contact
      {
            public string FirstName;
            public string LastName;
            public string EmailAddress;
            public string Group;
      }

      public struct ContactGroup
      {
            public string Group;
            public List<Contact> Contacts;
      }

      public class ContactEqualityComparer : IEqualityComparer<Contact>
      {
            public bool Equals(Contact x, Contact y)
            {
                return x.FirstName == y.FirstName && x.LastName == y.LastName && x.EmailAddress == y.EmailAddress;
            }

            public int GetHashCode(Contact obj)
            {
                return obj.FirstName.GetHashCode() ^ obj.LastName.GetHashCode() ^ obj.EmailAddress.GetHashCode();
            }
      }

      /// <summary>
      /// 执行select语句
      /// </summary>
      /// <param name="sql">select语句</param>
      /// <param name="connection">数据库链接语句</param>
      /// <returns>List的结果</returns>
      /// <exception cref="System.Exception"></exception>
      public static List<Dictionary<string, object>> SelectList(string sql, string connection)
      {
            if (sql == null || connection == null || sql == "" || connection == "")
                throw new System.Exception("未传入SQL语句或者Connection链接语句");
            List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
            SqlConnection conn = new SqlConnection(connection);
            SqlCommand cmd = new SqlCommand(sql, conn);
            try
            {
                conn.Open();
                SqlDataReader sqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                while (sqlDataReader.Read())
                {
                  int count = sqlDataReader.FieldCount;
                  if (count <= 0) continue;
                  Dictionary<string, object> map = new Dictionary<string, object>();
                  for (int i = 0; i < count; i++)
                  {
                        string name = sqlDataReader.GetName(i);
                        object value = sqlDataReader.GetValue(i);
                        map.Add(name, value);
                  }
                  list.Add(map);
                }
                conn.Close();
                return list;
            }
            catch (System.Exception)
            {
                conn.Close();
                return null;
            }
      }
    }
}start.bat 启动用
@echo off
set "source=\\192.168.100.18\mis\21.email-plugin\AddressBookTool"

:: 使用Robocopy复制除了version.conf之外的所有文件和目录
robocopy "%source%" "%1%" /E /XD Version.conf ClientVersion.conf

:: 检查并有条件地复制version.conf
if not exist "%1%\Version.conf" (
    copy /Y "%source%\Version.conf" "%1%"
)

:: 启动程序
cd /d "%1%"
start "" "%2%"

exit
来源:https://www.cnblogs.com/heirem/p/17788638.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 我的Office Outlook插件开发之旅(二)