using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; namespace SetAlertTemplate { // This console application is used in CustomAlertHandler.AlertTemplateConfigurator in order to update // list's alert template for using custom alert handler for it. Direct update of alert template's xml // throws Access denied exception so we need to do it in separate process without Sharepoint context class Program { private const int CODE_SUCCESS = 0; private const int CODE_ERROR = 1; private static int Main(string[] args) { log("=================================="); if (args.Length != 2) { log("Arguments missing. Correct usage: .exe {templateId} {templateXml}"); return CODE_ERROR; } string farmAdminDomain = ConfigurationManager.AppSettings["FarmAdminDomain"]; if (string.IsNullOrEmpty(farmAdminDomain)) { log("FarmAdminDomain not specified"); return CODE_ERROR; } string farmAdminUsername = ConfigurationManager.AppSettings["FarmAdminUsername"]; if (string.IsNullOrEmpty(farmAdminUsername)) { log("FarmAdminUsername not specified"); return CODE_ERROR; } string farmAdminPwdEncrypted = ConfigurationManager.AppSettings["FarmAdminPwd"]; if (string.IsNullOrEmpty(farmAdminPwdEncrypted)) { log("FarmAdminPwd not specified"); return CODE_ERROR; } string farmAdminPwd = CredentialsCryptographer.Decrypt(farmAdminPwdEncrypted); if (string.IsNullOrEmpty(farmAdminPwd)) { log("FarmAdminPwd not correct"); return CODE_ERROR; } string templateID = args[0]; if (string.IsNullOrEmpty(templateID)) { log("templateID not specified"); return CODE_ERROR; } string templateXml = args[1]; if (string.IsNullOrEmpty(templateXml)) { log("templateXml not specified"); return CODE_ERROR; } log("Current process identity: '{0}'", WindowsIdentity.GetCurrent().Name); log("Template id: '{0}'", templateID); log("Template xml: '{0}'", templateXml); try { bool result = true; foreach (var template in new SPAlertTemplateCollection(SPWebService.ContentService)) { if (template != null && template.Properties.ContainsKey("FriendlyName") && string.Compare(template.Properties["FriendlyName"].ToString(), templateID, true) == 0) { try { // code for updating alert templates (SPPersistedObjects) should run under farm admin using (new Impersonator(farmAdminUsername, farmAdminDomain, farmAdminPwd)) { log("Impersonated process identity: '{0}'", WindowsIdentity.GetCurrent().Name); log("Updating template '{0}'", (template.Properties.ContainsKey("FriendlyName") ? template.Properties["FriendlyName"].ToString() : template.DisplayName)); templateXml.Replace("'", "\""); template.Xml = templateXml; template.Update(); log("Templated updated"); } } catch (Exception x) { log("Error occured during updating of alert template: {0}\n{1}", x.Message, x.StackTrace); result = false; } } } return (result ? CODE_SUCCESS : CODE_ERROR); } catch (Exception x) { log("Error occured during enumerating alert templates: {0}\n{1}", x.Message, x.StackTrace); return CODE_ERROR; } } internal static void log(string msg, params object[] args) { try { if (args.Length > 0) { msg = string.Format(msg, args); } msg = string.Format("{0} (thread id: {1})\t{2}\n", DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss"), Thread.CurrentThread.ManagedThreadId, msg); File.AppendAllText("c:/temp/_customalerthandler_setalerttemplate.txt", msg); } catch (Exception x) { Console.WriteLine("{0}\n{1}", x.Message, x.StackTrace); } } } }