skype for business automation to outlook - skype-for-business

I have to add a feature in Skype for Business to open automatically a new Outlook task window when a call starts, with the phone number of the called/calling contact in the subject field. Is there any addin or api in order to do this?
Thank you

With the help of Lync SDK 2013, new conversation added event can be handled where you can also get participant related information. Inside conversation added event handler listen for AVModality state changes. When AVModality state is changed to connected, using Microsoft.Office.Interop.Outlook outlook application can be automated and new task window can be created as given below
LyncClient lyncClient = new LyncClient();
lyncClient.ConversationManager.ConversationAdded += OnConversationAdded;
private void OnConversationAdded(object sender, Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs e)
{
e.Conversation.Modalities[ModalityTypes.AudioVideo].ModalityStateChanged += OnAudioVideoModalityStateChanged;
}
private void OnAudioVideoModalityStateChanged(object sender, ModalityStateChangedEventArgs e)
{
switch(e.NewState)
{
case ModalityState.Connected:
Application oOutlook = null;
oOutlook = new Application();
TaskItem oTask = (TaskItem)oOutlook.CreateItem(OlItemType.olTaskItem);
oTask.Subject = "Testing";
oTask.StartDate = DateTime.Now;
oTask.Display(true);
break;
}
}
For more information :
Microsoft.Office.Interop.Outlook,
Lync SDK 2013

Related

How detect when user choose NEW or OPEN mail in Outlook VSTO

I'm programming a VSTO in Outlook 2016 and I would like to enable/disable buttons in a Ribbon, based on the user's action of START A NEW MESSAGE or just OPEN/READ a message.
My problem is HOW detect when the user pressed NEW MAIL or just open a sent/received one message.
Could anyone help me?
Thanks!
This tutorial actually deals with this exact scenario:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
inspectors = this.Application.Inspectors;
inspectors.NewInspector +=
new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
}
Specifically, you attach to this.Appliaction.Inspectors. The tutorial takes the opportunity to modify the Subject and Body properties of the new MailItem:
void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
Outlook.MailItem mailItem = Inspector.CurrentItem as Outlook.MailItem;
if (mailItem != null)
{
if (mailItem.EntryID == null)
{
mailItem.Subject = "This text was added by using code";
mailItem.Body = "This text was added by using code";
}
}
}

Email sent from C# OOM stays in Outbox if Outlook is closed until next Outlook start

I'm trying to send emails from a .NET application using Outlook Object Model.
My application displays the Outlook message window so the user can see what we're sending and edit it first. When the user hits the Send button, the Outlook window closes, and the message gets sent. This works perfectly as long as the Outlook application is already running.
If the Outlook application isn't already running, the message gets stuck in the Outbox, and will not send until I start Outlook. When I start Outlook, I can see the message sitting in the Outbox folder for a few seconds, then it gets sent.
I need to show the New Message form to Outlook user to select the recipient(s) and possibly edit the message before sending.
Note: I know that this question was already asked here Email sent with Outlook Object Model stays in Outbox until I start Outlook
and the solution exists, but it is not provided (only the small hint is provided) and unfortunately I cannot ask for clarification / code example because I have not enough "reputation".
I tried to write my own implementation of the hint provided, but the SyncEnd event is fired only when Outlook is already open (just to remind, the question is about the case then Outlook is closed).
My code below. What is wrong?
using Microsoft.Office.Interop.Outlook;
using OutlookApp = Microsoft.Office.Interop.Outlook.Application;
class Mailer
{
AutoResetEvent mailSentEvent = new AutoResetEvent(false);
public void CreateMail()
{
OutlookApp outlookApp = null;
MailItem mailItem = null;
try
{
outlookApp = new OutlookApp();
mailItem = outlookApp.CreateItem(OlItemType.olMailItem);
mailItem.Subject = "Test Message";
mailItem.Body = "This is the message.";
string reportPath = #"C:\temp\aaaaa.pdf";
mailItem.Attachments.Add(reportPath);
mailItem.Display(true);
StartSync(outlookApp);
bool result = mailSentEvent.WaitOne();
}
catch (System.Exception)
{
throw;
}
finally
{
if (mailItem != null) Marshal.ReleaseComObject(mailItem);
if (outlookApp != null) Marshal.ReleaseComObject(outlookApp);
}
}
private static SyncObject _syncObject = null;
private void StartSync(OutlookApp outlookApp)
{
var nameSpace = outlookApp.GetNamespace("MAPI");
_syncObject = nameSpace.SyncObjects[1];
_syncObject.SyncEnd += new Microsoft.Office.Interop.Outlook.SyncObjectEvents_SyncEndEventHandler(OnSyncEnd);
_syncObject.Start();
}
private void OnSyncEnd()
{
mailSentEvent.Set();
}
}
the SyncEnd event is fired only when Outlook is already open
That is not true. The SyncObjects collection contains all Send\Receive groups. You need to iterate over all objects in the collection and call the Start method, for example:
Set sycs = nsp.SyncObjects
For i = 1 To sycs.Count
Set syc = sycs.Item(i)
strPrompt = MsgBox("Do you wish to synchronize " &; syc.Name &;"?", vbYesNo)
If strPrompt = vbYes Then
syc.Start
End If
Next

NetOffice - Custom Task Pane in a Appointment window in Outlook

I found out that it's possible to add custom task panes to individual windows like e.g. the appointment with this code snippet:
public void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
Microsoft.Office.Tools.CustomTaskPane myCustomTaskPane;
if(Inspector.CurrentItem is Microsoft.Office.Interop.Outlook.AppointmentItem ) {
UserControl uc1 = MyUserControl();
myCustomTaskPane = getAddIn().CustomTaskPanes.Add(uc1, "MyPanel",Inspector);
myCustomTaskPane.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionRight;
myCustomTaskPane.DockPositionRestrict = Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
myCustomTaskPane.Visible = true;
}
//Additionally You can add a property change listener to the current Item here
}
however, I use 'NetOffice' instead of VSTO to have the add-in compatible with various Outlook versions. And there the add-in doesn't have the CustomTaskPanes property, and the TaskPanes.Add property isn't overloaded to allow adding custom panes on other window than the main explorer.
Ok, worked it out in following way.
In the ComAddin class I have a local variable
Office._CustomTaskPane _taskPane;
and I set the variable on the overriden CTPFactoryAvailable method:
public override void CTPFactoryAvailable(object CTPFactoryInst)
{
_ctpFactory = new NetOffice.OfficeApi.ICTPFactory(this.Application, CTPFactoryInst);
}
Then - when the addin is loaded - I'm adding an event handler to the NewInspectorEvent event:
private void Addin_OnStartupComplete(ref Array custom)
{
var inspectors = Application.Inspectors as NetOffice.OutlookApi.Inspectors;
inspectors.NewInspectorEvent += Inspectors_NewInspectorEvent;
}
In the event handler for creating a new inspector window, I'm creating the pane:
private void Inspectors_NewInspectorEvent(_Inspector Inspector)
{
var ai = Inspector.CurrentItem as AppointmentItem;
if (ai == null)
return;
var ins = Inspector as NetOffice.OutlookApi.Inspector;
_taskPane = _ctpFactory.CreateCTP(typeof(Addin).Assembly.GetName().Name + ".UserControl1", "My title", Inspector);
_taskPane.DockPosition = MsoCTPDockPosition.msoCTPDockPositionTop;
_taskPane.Height = 50;
_taskPane.Visible = true;
}
This draft proof of concept works for me.

Disable send update to all attendees VSTO

I'm using VSTO to develop add-in for Outlook.
When using Send method of MeetingItem (AppointmentItem), how can I disable Send Update to All Attendees popup? It always show when I call Send of existing meeting.
I only found ForceUpdateToAllAttendees property but it make the update send to all attendees, that would be wrong if user don't want to send updates to all attendees.
EDIT:
This is my code
void Application_ItemSend(object item, ref bool Cancel)
{
var form = new SC01(item);
form.Show();
Cancel = true; // prevent mail sending
}
...
in SC01 form:
private void btn_OK_Click(object sender, EventArgs e)
{
var meetingItem = _item As MeetingItem; // _item is private field of SC01
meetingItem.GetAssociatedAppointment(false).Send(); // this Send() will make sending option (to update attendees only or to all attendees
}
sorry I was away some days. I think I have the solution, althuogh I only "speak" vba - but in the end it is all the same...
leave away the line:
Cancel = true; // prevent mail sending
and also the line:
meetingItem.GetAssociatedAppointment(false).Send();
as far as I know the item will not be sent anyway as long as the form is not hidden again.
I hope this works!
Max
just had another idea that should solve your Problem:
void Application_ItemSend(object item, ref bool Cancel)
{
var form = new SC01(item);
form.Show();
'''next line is new and prevents the first popup
item.ForceUpdateToAllAttendees = TRUE
Cancel = true; // prevent mail sending
}
... in SC01 form:
private void btn_OK_Click(object sender, EventArgs e)
{
var meetingItem = _item As MeetingItem; // _item is private field of SC01
'''next line is new => popup Comes now
meetingItem.ForceUpdateToAllAttendees = FALSE
meetingItem.GetAssociatedAppointment(false).Send(); // this Send() will make sending option (to update attendees only or to all attendees
}

SharePoint 2010 Sequential Workflow associated with Content Type Retention policy

Hi: I've built a simple sequential workflow that is triggered by the retention policy used by a content type. The workflow takes the metadata of the current item and copies it to a purge log list located on a different site collection.
Having a hard time debugging this because of the retention policy relies on two timer jobs: information management and expiration policy. Attach the degugger to the w3wp and owetimer process but does not reliably catch the activated workflow.
My workflow history list for each file shows the workflow completed successfully. The meat of the workflow is a codeactivity that collects the data from the current item and updates a central list. That list is showing zero items after the process completes. Is it the code located in the codeactivity?
I removed all of the exception handling to simplify what's being shown.
Code
public Workflow1()
{
InitializeComponent();
}
public Guid workflowId = default(System.Guid);
public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
string purgeLogListPath = #"http://shptserver/sites/sp";
string listPath = #"http://shptserver/sites/sp/Lists/PurgeLog/AllItems.aspx";
private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{
}
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(purgeLogListPath))
{
try
{
SPWeb web = site.OpenWeb("/");
SPList list = web.GetListFromUrl(listPath);
DateTime today = DateTime.Now;
SPListItem item = list.Items.Add();
item["Title"] = onWorkflowActivated1.WorkflowProperties.Item.DisplayName;
item["Encoded Absolute URL"] = onWorkflowActivated1.WorkflowProperties.ItemUrl;
item["Content Type"] = onWorkflowActivated1.WorkflowProperties.Item.ContentType.Name;
item["Date Purged"] = today.ToString("MMMM dd yyyy");
item["DateTime Purged"] = today.ToString("MMMM dd yyyy hh:mm:ss");
item.Update();
}
catch (Exception ex)
{
string errorEntry = ex.Message;
}
}
});
}
}
Don't really see what you question is, but for the debugging troubles try doing it like this:
1) After you deploy you should restart the Timer Service
2) Via the Central Admin you can go to Timer Jobs and choose 'Run now' to trigger the job and start debugging