using System; using System.Collections.Specialized; using System.IO; using System.IO.Pipes; using System.Text; using System.Web; using System.Windows.Forms; namespace OutlookAddinProtocolHandler { /// /// Tiny shim launched when the user clicks an outlookaddin:// URL. /// Parses the URL and forwards a one-line command over the named pipe /// owned by the in-process VSTO add-in. If Outlook isn't running, the /// pipe connect will fail and we surface a MessageBox. /// public static class Program { private const string PipeName = "MarcusLaw.OutlookAddin"; [STAThread] public static int Main(string[] args) { try { if (args.Length == 0) { return Fail("השימוש: outlookaddin://compose?caseId="); } var raw = args[0]; if (!raw.StartsWith("outlookaddin://", StringComparison.OrdinalIgnoreCase)) { return Fail("URL לא תקין: " + raw); } var uri = new Uri(raw); var command = (uri.Host ?? "").ToLowerInvariant(); var query = HttpUtility.ParseQueryString(uri.Query ?? string.Empty); switch (command) { case "compose": return SendCompose(query); default: return Fail("פעולה לא ידועה: " + command); } } catch (Exception ex) { return Fail("שגיאה: " + ex.Message); } } private static int SendCompose(NameValueCollection query) { var caseId = query["caseId"]; if (string.IsNullOrWhiteSpace(caseId)) { return Fail("חסר caseId בכתובת ה-URL"); } var payload = "COMPOSE " + caseId.Trim() + "\n"; try { using var pipe = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut); pipe.Connect(timeout: 3000); var bytes = Encoding.UTF8.GetBytes(payload); pipe.Write(bytes, 0, bytes.Length); pipe.Flush(); return 0; } catch (TimeoutException) { return Fail("Outlook אינו פתוח, או שהתוסף עדיין לא נטען."); } catch (IOException ex) { return Fail("תקלת תקשורת עם התוסף: " + ex.Message); } } private static int Fail(string message) { MessageBox.Show(message, "Marcus-Law OutlookAddin", MessageBoxButtons.OK, MessageBoxIcon.Warning); return 1; } } }