I'am creating MailItem:
Application outlook = new Application();
_mailItem = outlook.CreateItem(OIItemType.olMailItem);
Inspector inspector = _mailItem .GetInspector;
inspector.Activate();
set recipient, body, etc...
Subscribe to an send event:
((ItemEvents_10_Event)_mailItem).Send += MailItemSendHandler;
void MailItemSendHandler(ref bool isSended) {
_mailItem.SaveAs(filePath);
}
When a user sent the email, I save it. But my email saved in compose mode. If i will open it in OutLook, i can change all information and i can resend it.
If i subscribe to the MailItem Inspector close event:
((InsPectorsEvents_10_Event)inspector).Close += CloseEventHandler;
and saving MailItem in CloseEventHandler, i have an error:
"Item has been moved or deleted".
How can i save my MailItem after it will be sended and moved in "Sent items" Outlook folder? (save in read mode)
EDIT
I'am using Items.AddItem event for saving my sent _mailItem. Get folder:
_sentFolderItems = _mailItem.SaveSentMessageFolder;
subscribe with some logic in _addEventHandler:
_sentFolderItems.Items.ItemAdd += _addEventHandler;
Good:
Outlook main window is running.
Outlook process is displayed in task manager.
I'am generating MailItem, showing it for user. User make some changes if he wish, and press send button.
4. Items.ItemAdd is fired and _addEventHandler is executed.
Outlook mail window is still running, and outlook process is displayed in task manager.
Bad:
Outlook main window is not running, and there is no process in task manager.
I'am generating MailItem, show it for user. There is only window for sending email displayed for user. Outlook process is displayed in task manager. User make some changes if he wish, and press send button. Mail is sended and task Manager does'nt have a OutLook process.
Items.ItemAdd is NOT fired and _addEventHandler is NOT executed.
But of corse sent item is located in sent folder.
public class MailItemWrapper {
public MailItemWrapper(MailItem mailItem, ComposeEmailWrapper composeEmailWrapper, bool isCompose) {
_mailItem = mailItem;
_identifyProperty = Guid.NewGuid();
_mailItem.AddUserProperty(_identifyProperty.ToString(), _identifyProperty.ToString());
_sentFolderItems = _mailItem.SaveSentMessageFolder;
_inspector = _mailItem.GetInspector;
_composeEmailWrapper = composeEmailWrapper;
InComposeMode = isCompose;
SetEventHandlers();
Subscribe();
_isSending = false;
}
private MailItem _mailItem;
private Inspector _inspector;
private MAPIFolder _sentFolderItems;
private InspectorEvents_10_CloseEventHandler _closeEventHandler;
private ItemEvents_10_SendEventHandler _sendEventHandler;
private ItemsEvents_ItemAddEventHandler _addEventHandler;
private readonly ComposeEmailWrapper _composeEmailWrapper;
private string _path;
private bool _isSending;
private Guid _identifyProperty;
public bool InComposeMode {
get; set;
}
public MailItem MailItem {
get {
return _mailItem;
}
}
public void Subscribe() {
((ItemEvents_10_Event) _mailItem).Send += _sendEventHandler;
((InspectorEvents_10_Event) _inspector).Close += _closeEventHandler;
_sentFolderItems.Items.ItemAdd += _addEventHandler;
}
public void UnsubscribeAndRelease() {
if(InComposeMode) {
((ItemEvents_10_Event) _mailItem).Send -= _sendEventHandler;
((InspectorEvents_10_Event) _inspector).Close -= _closeEventHandler;
_sentFolderItems.Items.ItemAdd -= _addEventHandler;
Marshal.ReleaseComObject(_sentFolderItems);
Marshal.ReleaseComObject(_mailItem);
Marshal.ReleaseComObject(_inspector);
_sentFolderItems = null;
_mailItem = null;
_inspector = null;
InComposeMode = false;
_isSending = false;
}
}
private void SetEventHandlers() {
_sendEventHandler = (ref bool cancel) =>{
_isSending = true;
};
_addEventHandler = delegate (object item) {
var mailItem = item as MailItem;
if(mailItem != null) {
var identityer = mailItem.UserProperties.Find(_identifyProperty.ToString());
if(identityer != null && _identifyProperty.ToString() == identityer.Value) {
_path = mailItem.SaveAsInTempFolder(); // extension
if(_composeEmailWrapper != null && _composeEmailWrapper.Callback != null) {
System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (System.Action) ExecuteCallBack);
UnsubscribeAndRelease();
}
}
Marshal.ReleaseComObject(mailItem);
}
};
_closeEventHandler = () => {
// if user close dialog without sending => unsibscribe
if(!_isSending) {
UnsubscribeAndRelease();
}
};
}
private void ExecuteCallBack() {
_composeEmailWrapper.Callback(_path, _composeEmailWrapper.SessionId);
}
}
use Items.ItemAdd event on the Sent Items folder.
Related
I have a button connected to the start and stop below. After a number of button clicks the application hangs on Trace.Listeners.Remove(_listener). Any idea why?
public void StartListener(ITraceTextSink sink)
{
if (_listener != null) return;
_listener = new TraceSource(sink);
Trace.AutoFlush = true;
Trace.Listeners.Add(_listener);
}
public void StopListener()
{
if (_listener == null) return;
Trace.Listeners.Remove(_listener);
_listener.Dispose();
_listener = null;
}
Outlook 2016
.Net Framework 4.5
i encounter a really strange behaviour:
when i iterate through the items collection of a contact folder in some very special undefined cases (which i do not really understand) some userproperties of the first item of the collection fail to load. However the UserProperties are definitly set.
The approach is following:
I open the contact folder (to which the items will be moved) in outlook.
then i execute the "test"
the execution of the test can be suammrized as following:
click button ->
start thread
iterate through the items (on first iteration no items are present).
add new items{
create item
set userproperty PRE before item is initially saved
save item
move item to desired folder
set userproperty POST after item is moved
save item
}
end thread
click button ->
start thread
iterate through the items (here the userproperty POST sometimes fails to load on the first item of the collection, however when i investigate it, it IS there. It only fails for the first item and succeeds for every other following item).
...END
it seems to me that outlook somehow fails to update the userproperty definitions timely. But note that the first BackgroundWorker thread is already finished when iterating through the items with the second backgroundworker thread.
The problem could be related to the fact that iam viewing the folder in the explorer while the items are added and iterated.
This bug is hard to reproduce and does only occur rarely.
however i'm really missing insight into the inner workings of outlook so i can only speculate.
Idea for workarounds:
I could add an item with all userproperties before moving it. the problem here is that i need to add new userproperties, after the item is initially saved and moved to the folder, in some scenarios.
in few cases the userproperty key is dynamically created (with a pattern) so it wouldn't be optimal to predefine all userproperties.
It's very important that the userProperties are reliably loaded because some important features are based upon them.
Does anybody has a clue how the problem is caused and how to solve it? because this behaviour is driving me crazy.
some Code (not the original but it should contain all the relevant aspects)
//Ribbon
TestNS.TestCaller testCaller;
string folderID = "00000000BDB409934ED327439481EB6E1E1CC4D3010055B62301B58E32478DCD8C0D3FA6304600002C4CA4400000";
public void testButton0_Action(Office.IRibbonControl control)
{
if(testCaller == null){
testCaller = new TestNS.TestCaller(ThisAddIn.Outlook,folderID);
}
testCaller.Run();
}
//Ribbon end
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Diagnostics;
using System.Windows.Forms;
using System.ComponentModel;
namespace TestNS
{
public class TestCaller{
private Outlook.Application application;
private BackgroundWorker worker = new BackgroundWorker();
private Test test = null;
private string folderId;
private bool init = true;
private bool busy = false;
public TestCaller(Outlook.Application application, string folderId){
this.application = application;
this.folderId = folderId;
worker.DoWork += new DoWorkEventHandler(DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnCompleted);
}
public void Run()
{
if (!busy)
{
busy = true;
test = new Test(application, folderId, init);
worker.RunWorkerAsync();
}
}
private void DoWork(object sender, DoWorkEventArgs e)
{
test.Process();
test = null;
}
private void OnCompleted(object sender, RunWorkerCompletedEventArgs e)
{
busy = false;
init = false;
}
}
class Test
{
public const string key_preCreateProperty ="preCreate";
public const string key_postCreateProperty = "postCreate";
private Outlook.Application application;
private string folderId;
private bool createData;
public Test(Outlook.Application application,string folderId,bool createData)
{
this.application = application;
this.folderId = folderId;
this.createData = createData;
}
public void Process(){
Examine();
if(createData){
CreateData();
}
}
public void CreateData()
{
List<Poco> pocos = new List<Poco>();
for (int i = 0; i < 10; i++)
{
pocos.Add(
new Poco
{
Pre = "Pre" + i,
Post = "Post" + i
}
);
}
CreateContactItems(folderId,pocos);
}
public void Examine()
{
bool preIsLoaded = false;
bool postIsLoaded = false;
Debug.WriteLine(">>>Examine");
Outlook.MAPIFolder folder = application.Session.GetFolderFromID(folderId);
Outlook.Items folderItems = folder.Items;
int i = 0;
//print UserProperties registered to the items
foreach(Outlook.ContactItem contactItem in folderItems){
var itemUserProperties = contactItem.UserProperties;
string itemUserPropertiesString = "";
foreach (var itemProp in itemUserProperties)
{
Outlook.UserProperty prop = (Outlook.UserProperty)itemProp;
itemUserPropertiesString += " " +prop.Name + " " + prop.Value + " \n";
}
//HERE: sometimes it prints only Pre on the first index of the iteration
Debug.WriteLine(string.Format("i={0} , itemUserProperties Count={1} , following UserProperties: \n{2}", i++, itemUserProperties.Count, itemUserPropertiesString));
string pre = null;
string post = null;
try
{
pre = contactItem.GetUserProperty(key_preCreateProperty);
preIsLoaded = true;
}
catch(KeyNotFoundException ex){
Debug.WriteLine("Error: Pre Not found"); //should not happen - doesn't happen
}
try
{
post = contactItem.GetUserProperty(key_postCreateProperty);
postIsLoaded = true;
}
catch (KeyNotFoundException ex)
{
Debug.WriteLine("Error: Post Not found"); //shoul not happen - happens rarely totally indeterminitic
}
Marshal.ReleaseComObject(itemUserProperties);
}
Debug.WriteLine("<<<Examine");
if (folderItems.Count > 0 && (!preIsLoaded || !postIsLoaded))
{
MessageBox.Show("preIsLoaded="+preIsLoaded +" \n" +"postIsLoaded="+postIsLoaded);
}
Marshal.ReleaseComObject(folderItems);
Marshal.ReleaseComObject(folder);
}
public void CreateContactItems(string folderId,List<Poco> pocos)
{
Outlook.MAPIFolder folder = application.Session.GetFolderFromID(folderId);
foreach(Poco poco in pocos){
CreateContactItem(folder,poco);
}
Marshal.ReleaseComObject(folder);
}
public void CreateContactItem(Outlook.MAPIFolder testFolder,Poco data)
{
Outlook.ContactItem contactItem = application.CreateItem(Outlook.OlItemType.olContactItem);
contactItem.SetUserProperty(key_preCreateProperty, data.Pre);
contactItem.Save();
Outlook.ContactItem movedContactItem = (Outlook.ContactItem)contactItem.Move(testFolder);
Marshal.ReleaseComObject(contactItem);
contactItem = movedContactItem;
contactItem.FirstName = data.Pre;
contactItem.LastName = data.Post;
contactItem.SetUserProperty(key_postCreateProperty, data.Post);
contactItem.Save();
Marshal.ReleaseComObject(contactItem);
}
}
public static class Util
{
public static void SetUserProperty(this Outlook.ContactItem item, string name, dynamic value)
{
Outlook.UserProperty property = item.UserProperties[name];
if (property == null)
{
property = item.UserProperties.Add(name, Outlook.OlUserPropertyType.olText);
}
property.Value = value;
}
public static dynamic GetUserProperty(this Outlook.ContactItem item, string name)
{
Outlook.UserProperty property = item.UserProperties[name];
if (property != null)
{
return property.Value;
}
throw new KeyNotFoundException(string.Format("UserProperty name={0} not found", name));
}
}
public class Poco
{
public string Pre
{
get;
set;
}
public string Post
{
get;
set;
}
}
}
Thank you for any replies
Outlook Object Model cannot be used on a secondary thread within a COM addin. Outlook 2016 will raise an exception as soon as it detects an OOM object being accessed on a secondary thread.
I am trying to implement Adrian Brown's very nice Outlook Add-In code and it works 2 out of 3 times. ItemAdd and ItemChange events are firing as expected, but the event handler for MAPIFolderEvents_12_Event.BeforeItemMove does not appear to be doing anything - I don't even hit a breakpoint on the first line of the event handler.
More Code for Clarity
This is the CalendarMonitor class; it monitors ItemAdd, ItemChange events on the Items collection of the folder, as well as BeforeItemMove on the MAPIFolder:
public class CalendarMonitor
{
private Explorer _explorer;
private List<string> _folderPaths;
private List<MAPIFolder> _calendarFolders;
private List<Items> _calendarItems;
private MAPIFolder _deletedItemsFolder;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentAdded;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentModified;
public event EventHandler<CancelEventArgs<AppointmentItem>> AppointmentDeleting;
public CalendarMonitor(Explorer explorer)
{
_folderPaths = new List<string>();
_calendarFolders = new List<MAPIFolder>();
_calendarItems = new List<Items>();
_explorer = explorer;
_explorer.BeforeFolderSwitch += Explorer_BeforeFolderSwitch;
var session = _explorer.Session;
try
{
_deletedItemsFolder = session.GetDefaultFolder(OlDefaultFolders.olFolderDeletedItems);
HookupDefaultCalendarEvents(session);
}
finally
{
Marshal.ReleaseComObject(session);
session = null;
}
}
private void HookupDefaultCalendarEvents(_NameSpace session)
{
var folder = session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
if (folder == null) return;
try
{
HookupCalendarEvents(folder);
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
private void Explorer_BeforeFolderSwitch(object obj, ref bool cancel)
{
var folder = (obj as MAPIFolder);
if (folder == null) return;
try
{
// Hookup events to any other Calendar folder opened.
if (folder.DefaultItemType == OlItemType.olAppointmentItem)
HookupCalendarEvents(folder);
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
private void HookupCalendarEvents(MAPIFolder calendarFolder)
{
if (calendarFolder.DefaultItemType != OlItemType.olAppointmentItem)
{
throw new ArgumentException("The MAPIFolder must use AppointmentItems as the default type.");
}
// Ignore other user's calendars.
if (_folderPaths.Contains(calendarFolder.FolderPath) || (!IsUsersCalendar(calendarFolder))) return;
var items = calendarFolder.Items;
// Store folder path to prevent repeating listeners
_folderPaths.Add(calendarFolder.FolderPath);
// Store a reference to the folder & items to prevent garbage collection
_calendarFolders.Add(calendarFolder);
_calendarItems.Add(items);
// Add listeners
((MAPIFolderEvents_12_Event)calendarFolder).BeforeItemMove += Calendar_BeforeItemMove;
items.ItemChange += CalendarItems_ItemChange;
items.ItemAdd += CalendarItems_ItemAdd;
}
private void CalendarItems_ItemAdd(object obj)
{
var appointment = (obj as AppointmentItem);
if (appointment == null) return;
try
{
if (AppointmentAdded != null)
AppointmentAdded(this, new EventArgs<AppointmentItem>(appointment));
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
private void CalendarItems_ItemChange(object obj)
{
var appointment = (obj as AppointmentItem);
if (appointment == null) return;
try
{
if (AppointmentModified != null)
AppointmentModified(this, new EventArgs<AppointmentItem>(appointment));
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
private void Calendar_BeforeItemMove(object obj, MAPIFolder moveToFolder, ref bool cancel)
{
if ((moveToFolder != null) && (!IsDeletedItemsFolder(moveToFolder))) return;
var appointment = (obj as AppointmentItem);
if (appointment == null) return;
try
{
if (AppointmentDeleting == null) return;
// Listeners to the AppointmentDeleting event can cancel the move operation if moving
// to the deleted items folder.
var args = new CancelEventArgs<AppointmentItem>(appointment);
AppointmentDeleting(this, args);
cancel = args.Cancel;
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
private bool IsUsersCalendar(MAPIFolder folder)
{
// This is based purely on my observations so far - a better way?
return (folder.Store != null);
}
private bool IsDeletedItemsFolder(MAPIFolder folder)
{
return (folder.EntryID == _deletedItemsFolder.EntryID);
}
public AppointmentItem Item { get; set; }
}
New Information:
I have done some additional "troubleshooting" and come up with more information: on a whim, I created a new calendar in Outlook (while debugging) and lo and behold the BeforeItemMove event fires just like I expect it to when deleting an appointment in the new calendar, but it still doesn't work in the original.
If I exit the debug session and restart, neither calendar's event functions as expected, despite working fine earlier. Any new calendar's BeforeItemMove event will work fine, until I close Outlook - then it's back to not responding.
I am hoping that this additional information will provide insight to those wiser than I. Any assistance is greatly appreciated.
calFolder variable must be declared on the global/class level to avoid being released by the Garbage Collector.
Where did you declare the source object? Is it alive when the event should be fired?
Anyway, you may consider developing an inspector wrapper. See Developing an Inspector Wrapper for Outlook 2010 and How to: Implement a Wrapper for Inspectors and Track Item-Level Events in Each Inspector for more information.
The sample project in C# and VB.NET is also available - Outlook 2010: Developing an Inspector Wrapper.
Afternoon all,
I have a windows service which subscribes to an Office365 email account and awaits new emails, when they arrive it processes their attachments, and all is well with the world.
But... for some reason, the applications stops receiving notifications after an undetermined amount of time.
I have handled the 'OnDisconnect' event and reestablish a connection as shown in the below code, but that doesnt seem to be fixing this issue. The windows service continues to run fine, and if I restart the service everything is good again, until is failed again.
This is the my class for running exchange:
public class ExchangeConnection
{
static readonly ExchangeService Service = Exchange.Service.ConnectToService(UserDataFromConsole.GetUserData(), new TraceListener());
public event EmailReceivedHandler OnEmailReceived;
public ExchangeConnection()
{
}
public void Open()
{
SetStreamingNotifications(Service);
var signal = new AutoResetEvent(false);
signal.WaitOne();
}
private void SetStreamingNotifications(ExchangeService service)
{
var streamingsubscription = service.SubscribeToStreamingNotifications(new FolderId[] { WellKnownFolderName.Inbox }, EventType.NewMail);
var connection = new StreamingSubscriptionConnection(service, 30);
connection.AddSubscription(streamingsubscription);
connection.OnNotificationEvent += OnEvent;
connection.OnSubscriptionError += OnError;
connection.OnDisconnect += OnDisconnect;
connection.Open();
}
public void MoveEmail(ItemId id, String folderName = "Archived Emails")
{
var rootFolder = Folder.Bind(Service, WellKnownFolderName.Inbox);
var archivedFolder = rootFolder.FindFolders(new FolderView(100)).FirstOrDefault(x => x.DisplayName == folderName);
if (archivedFolder == null)
{
archivedFolder = new Folder(Service) { DisplayName = folderName };
archivedFolder.Save(WellKnownFolderName.Inbox);
}
Service.MoveItems(new List<ItemId> {id}, archivedFolder.Id);
}
#region events
private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
//The connection is disconnected every 30minutes, and we are unable to override this,
//so when we get disconnected we just need to reconnect again.
var connection = (StreamingSubscriptionConnection)sender;
connection.Open();
}
private void OnEvent(object sender, NotificationEventArgs args)
{
var subscription = args.Subscription;
// Loop through all item-related events.
foreach (var notification in args.Events)
{
switch (notification.EventType)
{
case EventType.NewMail:
if (notification is ItemEvent)
{
var email = Item.Bind(Service, new ItemId(((ItemEvent) notification).ItemId.UniqueId));
OnEmailReceived(new EmailReceivedArgs((EmailMessage)email));
}
break;
}
}
}
private void OnError(object sender, SubscriptionErrorEventArgs args)
{
var e = args.Exception;
Logger.LogException(e,LogEventType.Error);
}
#endregion events
}
Any help would be great, thanks.
EDIT:
After improving the error logging I have found this exception occuring:
Exception: The specified subscription was not found.
Any ideas what is causing this?
With Office365 you need to make sure you deal with affinity see http://msdn.microsoft.com/en-us/library/office/dn458789(v=exchg.150).aspx . Adding those headers will ensure your requests will always routed to the correct servers.
Cheers
Glen
In fear of asking a question that might have been asked before, but my search skills did not able me to find. Okay, so here goes.
I have Windows Phone 8 App, where I can receive TileUpdates and Notifications, when My app is not running in the foreground. This I did by following http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202940(v=vs.105).aspx
In that link I learned that for getting notifications when app is running I should simply attach an event for the reception case. This I did in my AcquirePushChannel() function, which looks as follows:
public static void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("MyPushChannel");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("MyPushChannel");
CurrentChannel.Open();
if (!CurrentChannel.IsShellToastBound)
{
CurrentChannel.BindToShellTile();
}
CurrentChannel.BindToShellToast();
CurrentChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(Push_NotificationRecieved);
}
if (!CurrentChannel.IsShellTileBound)
{
CurrentChannel.BindToShellToast();
CurrentChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(Push_NotificationRecieved);
}
CurrentChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(Push_NotificationChannelChanged);
}
I have implemented CurrentChannel.ChannelUriUpdated, for the case that channelUri changes and I execute some code to also changes my ChannelsTable in the Cloud.
My Push_NotificationRecieved looks like:
private static void Push_NotificationRecieved(object sender, NotificationEventArgs e)
{
StringBuilder message = new StringBuilder();
string relativeUri = string.Empty;
message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
// Parse out the information that was part of the message.
foreach (string key in e.Collection.Keys)
{
message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);
if (string.Compare(
key,
"wp:Param",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.CompareOptions.IgnoreCase) == 0)
{
relativeUri = e.Collection[key];
}
}
// Display a dialog of all the fields in the toast.
MessageBox.Show(message.ToString());
//Dispatcher.BeginInvoke((message) => MessageBox.Show(message.ToString()));
}
I cannot see why the notification is not registered. Since in my log in the cloud I receive that the Toast Notification was received?
Any Ideas? Furthermore can I display the toast from the code or something similar, as far as I have read it is not possible?
Extra
Have tried changing the functions to public but did not help with the problem.
Anybody have an Idea to why the event is not firing.
The answer you posted is almost correct. From the previous you have:
public static void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("MyPushChannel");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("MyPushChannel");
CurrentChannel.Open();
if (!CurrentChannel.IsShellToastBound)
{
CurrentChannel.BindToShellTile();
}
CurrentChannel.BindToShellToast();
}
if (!CurrentChannel.IsShellTileBound)
{
CurrentChannel.BindToShellToast();
}
CurrentChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(Push_NotificationChannelChanged);
CurrentChannel.ShellToastNotificationReceived += CurrentChannel_ShellToastNotificationReceived;
}
And to that you have to add:
private static void CurrentChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{
StringBuilder message = new StringBuilder();
string relativeUri = string.Empty;
message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
// Parse out the information that was part of the message.
foreach (string key in e.Collection.Keys)
{
message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);
if (string.Compare(
key,
"wp:Param",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.CompareOptions.IgnoreCase) == 0)
{
relativeUri = e.Collection[key];
}
}
// Display a dialog of all the fields in the toast.
MessageBox.Show(message.ToString());
}
So all you send is inside the e.collection. So you can from the server send all kind of parameters.
Of course just after I set a bounty to run I got it working. So here is the updated code.
public static void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("MyPushChannel");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("MyPushChannel");
CurrentChannel.Open();
if (!CurrentChannel.IsShellToastBound)
{
CurrentChannel.BindToShellTile();
}
CurrentChannel.BindToShellToast();
}
if (!CurrentChannel.IsShellTileBound)
{
CurrentChannel.BindToShellToast();
}
CurrentChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(Push_NotificationChannelChanged);
CurrentChannel.ShellToastNotificationReceived += CurrentChannel_ShellToastNotificationReceived;
}
Okay so the reason for this, is that you need to set the events on every startup. Then you will get the wished properties. Then you have to create your own code for getting what you want :)