private async void DiscoverResourcesAsync() { _discoverResourcesCommand.SetCanExecute(false); try { var serverResources = await _serverSettingsViewModel.GetServerResources(); var calendars = serverResources.Calendars.Select(c => new CalendarDataViewModel(c)).ToArray(); var addressBooks = serverResources.AddressBooks.Select(a => new AddressBookDataViewModel(a)).ToArray(); var taskLists = serverResources.TaskLists.Select(d => new TaskListDataViewModel(d)).ToArray(); using (var selectResourcesForm = SelectResourceForm.CreateForFolderAssignment(_optionTasks, ConnectionTests.ResourceType.Calendar, calendars, addressBooks, taskLists)) { if (selectResourcesForm.ShowDialog() == System.Windows.Forms.DialogResult.OK) { var optionList = new List <OptionsModel>(); foreach (var resource in calendars.Where(c => c.SelectedFolder != null)) { var options = CreateOptionsWithCategory(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); _optionTasks.ValidateBulkProfile(options, resource.Model.Privileges, resource.Model.OwnerProperties); optionList.Add(options); } foreach (var resource in addressBooks.Where(c => c.SelectedFolder != null)) { var options = CreateOptions(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); _optionTasks.ValidateBulkProfile(options, resource.Model.Privileges, null); optionList.Add(options); } foreach (var resource in taskLists.Where(c => c.SelectedFolder != null)) { var options = CreateOptions(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); optionList.Add(options); } _parent.RequestAdd(optionList); _parent.RequestRemoval(this); } } } catch (Exception x) { s_logger.Error("Exception while DiscoverResourcesAsync.", x); string message = null; for (Exception ex = x; ex != null; ex = ex.InnerException) { message += ex.Message + Environment.NewLine; } MessageBox.Show(message, OptionTasks.ConnectionTestCaption); } finally { _discoverResourcesCommand.SetCanExecute(true); } }
private async void DiscoverResourcesAsync() { _discoverResourcesCommand.SetCanExecute(false); try { var serverResources = await _serverSettingsViewModel.GetServerResources(); var calendars = serverResources.Calendars.Select(c => new CalendarDataViewModel(c)).ToArray(); var addressBooks = serverResources.AddressBooks.Select(a => new AddressBookDataViewModel(a)).ToArray(); var taskLists = serverResources.TaskLists.Select(d => new TaskListDataViewModel(d)).ToArray(); if (OnlyAddNewUrls) { // Exclude all resourcres that have already been configured var options = (_parent as OptionsCollectionViewModel).Options; var configuredUrls = new HashSet <String>(options.Select(o => o.Model.CalenderUrl)); calendars = calendars.Where(c => !configuredUrls.Contains(c.Uri.ToString())).ToArray(); addressBooks = addressBooks.Where(c => !configuredUrls.Contains(c.Uri.ToString())).ToArray(); taskLists = taskLists.Where(c => !configuredUrls.Contains(c.Id)).ToArray(); } // --- Create folders if requested and required if (AutoCreateOutlookFolders) { // https://docs.microsoft.com/en-us/visualstudio/vsto/how-to-programmatically-create-a-custom-calendar // https://msdn.microsoft.com/en-us/library/office/ff184655.aspx // Get Outlook's default calendar folder (this is where we create the Kolab folders) GenericComObjectWrapper <Folder> defaultCalendarFolder = new GenericComObjectWrapper <Folder>(Globals.ThisAddIn.Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar) as Folder); // Find all Kolab calendars that are not yet synced to an outlook folder foreach (var resource in calendars.Where(c => c.SelectedFolder == null)) { string newCalendarName = resource.Name + " (" + Name + ")"; GenericComObjectWrapper <Folder> newCalendarFolder = null; try { // Use existing folder if it does exist newCalendarFolder = new GenericComObjectWrapper <Folder>(defaultCalendarFolder.Inner.Folders[newCalendarName] as Folder); } catch { // Create missing folder newCalendarFolder = new GenericComObjectWrapper <Folder>(defaultCalendarFolder.Inner.Folders.Add(newCalendarName, OlDefaultFolders.olFolderCalendar) as Folder); // Make sure it has not been renamed to "name (this computer only)" newCalendarFolder.Inner.Name = newCalendarName; } // use the selected folder for syncing with kolab resource.SelectedFolder = new OutlookFolderDescriptor(newCalendarFolder.Inner.EntryID, newCalendarFolder.Inner.StoreID, newCalendarFolder.Inner.DefaultItemType, newCalendarFolder.Inner.Name, 0); } // Create and assign all Kolab address books that are not yet synced to an outlook folder GenericComObjectWrapper <Folder> defaultAddressBookFolder = new GenericComObjectWrapper <Folder>(Globals.ThisAddIn.Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts) as Folder); foreach (var resource in addressBooks.Where(c => c.SelectedFolder == null)) { string newAddressBookName = resource.Name + " (" + Name + ")"; GenericComObjectWrapper <Folder> newAddressBookFolder = null; try { newAddressBookFolder = new GenericComObjectWrapper <Folder>(defaultAddressBookFolder.Inner.Folders[newAddressBookName] as Folder); } catch { newAddressBookFolder = new GenericComObjectWrapper <Folder>(defaultAddressBookFolder.Inner.Folders.Add(newAddressBookName, OlDefaultFolders.olFolderContacts) as Folder); newAddressBookFolder.Inner.Name = newAddressBookName; } resource.SelectedFolder = new OutlookFolderDescriptor(newAddressBookFolder.Inner.EntryID, newAddressBookFolder.Inner.StoreID, newAddressBookFolder.Inner.DefaultItemType, newAddressBookFolder.Inner.Name, 0); } // Create and assign all Kolab address books that are not yet synced to an outlook folder GenericComObjectWrapper <Folder> defaultTaskListsFolder = new GenericComObjectWrapper <Folder>(Globals.ThisAddIn.Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderTasks) as Folder); foreach (var resource in taskLists.Where(c => c.SelectedFolder == null)) { string newTaskListName = resource.Name + " (" + Name + ")"; GenericComObjectWrapper <Folder> newTaskListFolder = null; try { newTaskListFolder = new GenericComObjectWrapper <Folder>(defaultTaskListsFolder.Inner.Folders[newTaskListName] as Folder); } catch { newTaskListFolder = new GenericComObjectWrapper <Folder>(defaultTaskListsFolder.Inner.Folders.Add(newTaskListName, OlDefaultFolders.olFolderTasks) as Folder); newTaskListFolder.Inner.Name = newTaskListName; } resource.SelectedFolder = new OutlookFolderDescriptor(newTaskListFolder.Inner.EntryID, newTaskListFolder.Inner.StoreID, newTaskListFolder.Inner.DefaultItemType, newTaskListFolder.Inner.Name, 0); } } using (var selectResourcesForm = SelectResourceForm.CreateForFolderAssignment(_optionTasks, ConnectionTests.ResourceType.Calendar, calendars, addressBooks, taskLists)) { if (selectResourcesForm.ShowDialog() == System.Windows.Forms.DialogResult.OK) { var optionList = new List <OptionsModel>(); foreach (var resource in calendars.Where(c => c.SelectedFolder != null)) { var options = CreateOptions(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); _optionTasks.ValidateBulkProfile(options, resource.Model.Privileges, resource.Model.OwnerProperties); optionList.Add(options); } foreach (var resource in addressBooks.Where(c => c.SelectedFolder != null)) { var options = CreateOptions(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); _optionTasks.ValidateBulkProfile(options, resource.Model.Privileges, null); optionList.Add(options); } foreach (var resource in taskLists.Where(c => c.SelectedFolder != null)) { var options = CreateOptions(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); optionList.Add(options); } _parent.RequestAdd(optionList); _parent.RequestRemoval(this); } } } catch (Exception x) { s_logger.Error("Exception while DiscoverResourcesAsync.", x); string message = null; for (Exception ex = x; ex != null; ex = ex.InnerException) { message += ex.Message + Environment.NewLine; } MessageBox.Show(message, OptionTasks.ConnectionTestCaption); } finally { _discoverResourcesCommand.SetCanExecute(true); } }
public async Task <ServerResources> DiscoverResourcesAsync() { _discoverResourcesCommand.SetCanExecute(false); ServerResources serverResources = new ServerResources(); try { s_logger.Debug("Get CalDAV/CardDAV data from Server"); serverResources = await _serverSettingsViewModel.GetServerResources(); if (!serverResources.ContainsResources) { return(serverResources); } var calendars = serverResources.Calendars.Select(c => new CalendarDataViewModel(c)).ToArray(); var addressBooks = serverResources.AddressBooks.Select(a => new AddressBookDataViewModel(a)).ToArray(); var taskLists = serverResources.TaskLists.Select(d => new TaskListDataViewModel(d)).ToArray(); var existingOptions = (_parent as OptionsCollectionViewModel).Options; if (OnlyAddNewUrls) { s_logger.Debug("Exclude all server resources that have already been configured"); var configuredUrls = new HashSet <String> (existingOptions.Select(o => o.Model.CalenderUrl)); calendars = calendars.Where(c => !configuredUrls.Contains(c.Uri.ToString())).ToArray(); addressBooks = addressBooks.Where(c => !configuredUrls.Contains(c.Uri.ToString())).ToArray(); taskLists = taskLists.Where(c => !configuredUrls.Contains(c.Id)).ToArray(); } // --- Create folders if requested and required if (AutoCreateOutlookFolders) { s_logger.Debug("Auto-create outlook folders"); // https://docs.microsoft.com/en-us/visualstudio/vsto/how-to-programmatically-create-a-custom-calendar // https://msdn.microsoft.com/en-us/library/office/ff184655.aspx // Get Outlook's default calendar folder (this is where we create the Kolab folders) GenericComObjectWrapper <Folder> defaultCalendarFolder = new GenericComObjectWrapper <Folder> (Globals.ThisAddIn.Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar) as Folder); // Detect wether we have a sync option that syncs the default Outlook calendar bool defaultCalendarFolderIsSynced = existingOptions.Any(o => o.Model.SelectedFolderOrNull?.EntryId == defaultCalendarFolder.Inner.EntryID); // Create and assign all Kolab calendars that are not yet synced to an outlook folder foreach (var resource in calendars.Where(c => c.SelectedFolder == null)) { string newCalendarName = resource.Name + " (" + Name + ")"; GenericComObjectWrapper <Folder> newCalendarFolder = null; if (resource.Model.IsDefault && !defaultCalendarFolderIsSynced) { s_logger.Info($"Sync Calendar '{newCalendarName}' with default outlook calendar"); newCalendarFolder = defaultCalendarFolder; } else { s_logger.Debug($"Find folder for calendar '{newCalendarName}'"); newCalendarFolder = findOrCreateFolder(defaultCalendarFolder, newCalendarName, OlDefaultFolders.olFolderCalendar); } // use the selected folder for syncing with kolab if (newCalendarFolder != null) { s_logger.Info($"Use calendar folder '{newCalendarFolder.Inner.Name}' in Sync setting"); resource.SelectedFolder = new OutlookFolderDescriptor(newCalendarFolder.Inner.EntryID, newCalendarFolder.Inner.StoreID, newCalendarFolder.Inner.DefaultItemType, newCalendarFolder.Inner.Name, 0); } } // Create and assign all Kolab address books that are not yet synced to an outlook folder GenericComObjectWrapper <Folder> defaultAddressBookFolder = new GenericComObjectWrapper <Folder> (Globals.ThisAddIn.Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts) as Folder); foreach (var resource in addressBooks.Where(c => c.SelectedFolder == null)) { string newAddressBookName = resource.Name + " (" + Name + ")"; s_logger.Debug($"Find folder for address book '{newAddressBookName}'"); GenericComObjectWrapper <Folder> newAddressBookFolder = findOrCreateFolder(defaultAddressBookFolder, newAddressBookName, OlDefaultFolders.olFolderContacts); if (newAddressBookFolder != null) { newAddressBookFolder.Inner.ShowAsOutlookAB = true; // Special handling for GAL delivered by CardDAV: set as default address list if (resource.Uri.Segments.Last() == "ldap-directory/") { var _session = Globals.ThisAddIn.Application.Session; foreach (AddressList ali in _session.AddressLists) { GenericComObjectWrapper <AddressList> al = new GenericComObjectWrapper <AddressList>(ali); if (al.Inner.Name == newAddressBookName) { // We need to set it in the registry, as there does not seem to exist an appropriate API // http://www.ericwoodford.com/2016/06/set-default-outlook-address-book-script.html string regPath = @"Software\Microsoft\Office\" + Globals.ThisAddIn.Application.Version.Split(new char[] { '.' })[0] + @".0" + @"\Outlook\Profiles\" + _session.CurrentProfileName + @"\9207f3e0a3b11019908b08002b2a56c2"; // Outlook default address key var key = Registry.CurrentUser.OpenSubKey(regPath, true); if (key != null) { s_logger.Info($"Configure LDAP GAL '{newAddressBookName}' as default address book."); // Turn ID into byte array byte[] bytes = new byte[al.Inner.ID.Length / 2]; for (int i = 0; i < al.Inner.ID.Length; i += 2) { bytes[i / 2] = Convert.ToByte(al.Inner.ID.Substring(i, 2), 16); } // Set Outlook default address book subKey key.SetValue("01023d06", bytes); } } } } s_logger.Debug($"Use address book folder '{newAddressBookFolder.Inner.Name}' in Sync setting"); resource.SelectedFolder = new OutlookFolderDescriptor(newAddressBookFolder.Inner.EntryID, newAddressBookFolder.Inner.StoreID, newAddressBookFolder.Inner.DefaultItemType, newAddressBookFolder.Inner.Name, 0); } } // Create and assign all Kolab task lists that are not yet synced to an outlook folder GenericComObjectWrapper <Folder> defaultTaskListsFolder = new GenericComObjectWrapper <Folder> (Globals.ThisAddIn.Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderTasks) as Folder); foreach (var resource in taskLists.Where(c => c.SelectedFolder == null)) { string newTaskListName = resource.Name + " (" + Name + ")"; s_logger.Debug($"Find folder for task list '{newTaskListName}'"); GenericComObjectWrapper <Folder> newTaskListFolder = findOrCreateFolder(defaultTaskListsFolder, newTaskListName, OlDefaultFolders.olFolderTasks); if (newTaskListFolder != null) { s_logger.Info($"Use task list folder '{newTaskListFolder.Inner.Name}' in Sync setting"); resource.SelectedFolder = new OutlookFolderDescriptor(newTaskListFolder.Inner.EntryID, newTaskListFolder.Inner.StoreID, newTaskListFolder.Inner.DefaultItemType, newTaskListFolder.Inner.Name, 0); } } } using (var selectResourcesForm = SelectResourceForm.CreateForFolderAssignment(_optionTasks, ConnectionTests.ResourceType.Calendar, calendars, addressBooks, taskLists)) { // Create and add new sync profiles s_logger.Debug("Create and add all new sync profiles"); if (AutoConfigure || selectResourcesForm.ShowDialog() == System.Windows.Forms.DialogResult.OK) { var optionList = new List <OptionsModel>(); foreach (var resource in calendars.Where(c => c.SelectedFolder != null)) { var options = CreateOptions(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); GenericComObjectWrapper <Folder> folder = new GenericComObjectWrapper <Folder>( Globals.ThisAddIn.Application.Session.GetFolderFromID(resource.SelectedFolder.EntryId) as Folder); if (resource.Model.ReadOnly) { options.SynchronizationMode = SynchronizationMode.ReplicateServerIntoOutlook; folder.Inner.Description = Strings.Get($"Read-only calendar") + $" »{options.Name}«:\n" + Strings.Get($"local changes made in Outlook are discarded and replaced by data from the server."); try { // Setting the icon might fail if we sync with the default Outlook calendar folder folder.Inner.SetCustomIcon( PictureDispConverter.ToIPictureDisp(Resources.CalendarReadOnly) as stdole.StdPicture); } catch { } } else { options.SynchronizationMode = SynchronizationMode.MergeInBothDirections; folder.Inner.Description = Strings.Get($"Read-write calendar") + $" »{options.Name}«:\n" + Strings.Get($"local changes made in Outlook and remote changes from the server are merged."); try { // Setting the icon might fail if we sync with the default Outlook calendar folder folder.Inner.SetCustomIcon( PictureDispConverter.ToIPictureDisp(Resources.CalendarReadWrite) as stdole.StdPicture); } catch { } } optionList.Add(options); } foreach (var resource in addressBooks.Where(c => c.SelectedFolder != null)) { var options = CreateOptions(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); GenericComObjectWrapper <Folder> folder = new GenericComObjectWrapper <Folder>( Globals.ThisAddIn.Application.Session.GetFolderFromID(resource.SelectedFolder.EntryId) as Folder); if (resource.Model.ReadOnly) { options.SynchronizationMode = SynchronizationMode.ReplicateServerIntoOutlook; folder.Inner.Description = Strings.Get($"Read-only address book") + $" »{options.Name}«:\n" + Strings.Get($"local changes made in Outlook are discarded and replaced by data from the server."); folder.Inner.SetCustomIcon( PictureDispConverter.ToIPictureDisp(Resources.AddressbookReadOnly) as stdole.StdPicture); } else { options.SynchronizationMode = SynchronizationMode.MergeInBothDirections; folder.Inner.Description = Strings.Get($"Read-write address book") + $" »{options.Name}«:\n" + Strings.Get($"local changes made in Outlook and remote changes from the server are merged."); folder.Inner.SetCustomIcon( PictureDispConverter.ToIPictureDisp(Resources.AddressbookReadWrite) as stdole.StdPicture); } optionList.Add(options); } foreach (var resource in taskLists.Where(c => c.SelectedFolder != null)) { var options = CreateOptions(resource); _serverSettingsViewModel.SetResourceUrl(options, resource.Model); GenericComObjectWrapper <Folder> folder = new GenericComObjectWrapper <Folder>( Globals.ThisAddIn.Application.Session.GetFolderFromID(resource.SelectedFolder.EntryId) as Folder); if (resource.Model.ReadOnly) { options.SynchronizationMode = SynchronizationMode.ReplicateServerIntoOutlook; folder.Inner.Description = Strings.Get($"Read-only task list") + $" »{options.Name}«:\n" + Strings.Get($"local changes made in Outlook are discarded and replaced by data from the server."); folder.Inner.SetCustomIcon( PictureDispConverter.ToIPictureDisp(Resources.TasklistReadOnly) as stdole.StdPicture); } else { options.SynchronizationMode = SynchronizationMode.MergeInBothDirections; folder.Inner.Description = Strings.Get($"Read-write task list") + $" »{options.Name}«:\n" + Strings.Get($"local changes made in Outlook and remote changes from the server are merged."); folder.Inner.SetCustomIcon( PictureDispConverter.ToIPictureDisp(Resources.TasklistReadWrite) as stdole.StdPicture); } optionList.Add(options); } _parent.RequestAdd(optionList); _parent.RequestRemoval(this); } } } catch (Exception x) { s_logger.Error("Exception while DiscoverResourcesAsync.", x); /*string message = null; * for (Exception ex = x; ex != null; ex = ex.InnerException) * message += ex.Message + Environment.NewLine; * MessageBox.Show (message, OptionTasks.ConnectionTestCaption);*/ } finally { _discoverResourcesCommand.SetCanExecute(true); } return(serverResources); }