iTranslated by AI
Common Pitfalls When Reading Outlook Calendars via COM (.NET 8 / WPF)
Why I started doing this
Honestly, with just task management, I often miss "what I have today."
I have tasks in TODAY.
But, there are meetings on my schedule.
And I get sucked into meetings, and my tasks die.
I thought, "Why not display my schedule on the same screen?"
So, I added Outlook Calendar reading to tsk.
What I built (Goal for this time)
-
c1: Display today's schedule (NOW / TODAY / TOMORROW) -
c2: Display weekly schedule - As a bonus, I made it possible to ON/OFF c1/c2 from /config
I implemented this using Outlook COM (Interop).
I know "Graph API is the correct way," but I wanted to keep it local-only this time.
That's the official reason, but the real reason is that due to company PC restrictions, I had to keep it local.
How it works (Overview)
What I did is simple.
- Create
Outlook.Application - Get the calendar folder with
Namespace("MAPI") - Filter
Itemsand readAppointmentItem
However, even though it's simple, there are many pitfalls.
This is where the real story begins.
Pitfall 1: Microsoft.Office not found (Reference hell)
The first thing that happens.
-
Microsoft.Officedoes not exist -
office, Version=15.0.0.0not found at runtime
✅ The solution is to "Add COM Reference" + adjust "Embed Interop Types / Copy Local."
❌ Relying solely on NuGet's interop usually fails due to environmental differences.
(This is highly environment-dependent, so it was the right decision to make the feature toggleable via /config for general users.)
Pitfall 2: Logs appear but nothing shows on screen (Count == 0)
"It seems to be retrieved, but 0 items displayed."
This took the most time.
Conclusion: The date filter is off.
Common mistake
if (appt.Start >= from && appt.Start < to)
{
// add
}
This is usually correct.
However, there are rounding or precision issues with date/times on the Outlook side, so exact matching or boundaries are suspicious.
-
=doesn't match - It fails if you specify down to the second
- Ultimately, you have no choice but to take it as a "range"
This is the same for Restrict / Find, and there's talk that "since equivalence matching doesn't work, use a range."
👉 First, how you log is important.
If I logged inside the if, the log wouldn't appear unless the condition was met.
So, initially, I did a full-item log to verify the actual data.
Pitfall 3: Picking up the wrong calendar when I should be picking up my personal one
I thought I retrieved it with GetDefaultFolder(olFolderCalendar), but:
- Only old appointments appear
- It says there are no appointments
👉 This is an Outlook Profile/Store issue.
Outlook has multiple Stores such as:
- Mailbox
- Archive
- pst
- Shared
If the default is different from what you expect, the calendar will naturally be different.
✅ Solution: Enumerate Stores and grab the calendar from the correct Store.
(The correct way varies depending on the environment, so I focused the implementation on "adopt what is retrieved" + verify with logs.)
Pitfall 4: c1/c2 is slow (takes about 10 seconds)
The cause is almost always this.
- Launching Outlook every time
- Enumerating all
Itemsand then filtering with C#
It is clearly stated that Outlook's Items.Restrict is significantly faster when there are many items.
✅ Strategy adopted
- Reduce the number of retrievals (for
c1, fetch 2 days' worth at once and split them locally) - If further optimization is needed, use Restrict (though it ended up being "good enough as is" this time)
👉 "Improve the user experience first, then use Restrict if necessary" was the right balance.
Pitfall 5: Deadlines are all red/all white (UI state bug)
This wasn't Outlook; it was a bug on the tsk side.
- When I set
OverdueDays >= 0, "today" was treated as overdue, turning everything red - When I corrected it to
> 0, everything became "not overdue"
The cause was:
- I was copying
OverdueDaysintoDisplayRowby value - I changed the design mid-way, and the value stopped being updated
✅ Solution adopted: DisplayRow derives its state by referencing the Task
public int OverdueDays => Task?.OverdueDays ?? -1;
"Don't maintain state, derive it."
This was the correct answer.
Summary (Lessons learned)
The biggest takeaway was this:
- Outlook COM "looks simple but is full of landmines."
- However, the types of landmines are generally predictable.
✅ References
✅ Stores
✅ Date/time filters
✅ Performance
If you master these, you can make it work.
As for how it changed my work, the number of times I have to open Outlook just to check "today's meetings" has dropped dramatically.
Just that alone is a big win.
Download
GitHub
Download tsk_v130.zip, extract it, and run tsk.exe.
Author: mitsukida
Contact: mmitsuki0806@gmail.com
🔗 Related Articles
- 🧩 Black background x Green text. Built a tool for task management with a hacker feel
- 🧲 Snapping windows to screen edges in WPF (Magnet Snap)
- 📅 "Fri Review" for this Friday. Built a parser that analyzes dates with natural Japanese input
- 🧩 Added a View feature to the terminal-style task management tool (v1.1.1)
- 🖥 Techniques for seriously creating a black background x green text terminal-style UI in WPF
- 🌀 The story of how I forgot to call RenderDisplay and everything turned into bugs (WPF)
Discussion