I'm working with the Audit framework in MOSS 2007, and I've programatically enabled Auditing for 2 specific lists in a bunch of sites in a site collection(meaning the sites all have their own two lists). I've only enabled the update mask, as I only want to know when something's been changed or added.
However, I'm only able to log when something's been added, with my current setup. To allow for seeing changes to the list items, I'm aware that the list item itself has to have auditing enabled. But when adding a new item to the list, how do I automatically enable Auditing for the item? If possible, I'd prefer to avoid creating an event receiver to accomplish this.
*EDIT
The code I use to enable auditing looks something like this:
foreach (SPSite site in webApp.Sites) {
foreach (SPWeb website in site.AllWebs) {
website.Lists["MyList"].Audit.AuditFlags = SPAuditMaskType.Update;
website.Lists["MyList"].Audit.Update();
}
}
And to read it:
SPUserToken sysAdmin = website.Site.SystemAccount.UserToken;
using (SPSite elevatedSite = new SPSite(website.Site.ID,sysAdmin)) {
using (SPWeb elevatedWeb = elevatedSite.OpenWeb(website.ID)) {
SPAuditQuery auditQuery = new SPAuditQuery(elevatedSite);
auditQuery.SetRangeStart(myDatetime);
auditQuery.RestrictToList(elevatedWeb.Lists["MyList"]);
listChanges = elevatedWeb.Lists["MyList"].Audit.GetEntries(auditQuery);
}
}
I realize I'm restricting to list here, but when I didn't I got changes from other lists on the site as well. Even though logically I'd assume I only got the changes from the list I called "GetEntries" on...
Thanks
If the library has auditing enabled, then new items will be audited. I'm not aware of any document-specific auditing
A little late in replying to this, but here is some additional information in case others find this post.
It is possible to track the auditing events at the document level. This link explains how it can be done. They use an event handler to make it work. I know you mention you do not want to do it this way, but this is what is needed to automatically track document events. Setting the audit mask type on the document library appears to only track the DL events, not the individual items.
Related
I am performing custom action on all incoming replies through VSTO add-in. The add-in will compare ConversationID of incoming reply with existing email. It works fine if I have to search inside one folder but my problem is email can be in any folder in store. Here is my code.
void items_ItemAdd(object Item)
{
Outlook.Application application = new Outlook.Application();
string filter = "RE: ";
Outlook.MailItem mail = (Outlook.MailItem)Item;
Outlook.Folder folder = mail.Parent as Outlook.Folder;
if (Item != null)
{
if (mail.MessageClass == "IPM.Note" && mail.Subject.ToUpper().Contains(filter.ToUpper()))
{
var RequiredMail = (from e in folder.Items.Cast<Outlook.MailItem>().OrderBy(X => X.ReceivedTime).Where(C => C.ConversationID == mail.ConversationID) select mail).FirstOrDefault();
// Perform custom action
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
Also, I have read that searching for an email using Linq is not very efficient. Is there any other more efficient way to get RequiredMail?
Any help will be highly appreciated.
Thank you.
First of all, you must be aware that ItemAdd event may not be fired if more than sixteen items are added to the collection. This is a known issue in Outlook. The following series of articles describes possible workarounds for that:
Outlook NewMail event unleashed: the challenge (NewMail, NewMailEx, ItemAdd)
Outlook NewMail event: solution options
Outlook NewMail event and Extended MAPI: C# example
Outlook NewMail unleashed: writing a working solution (C# example)
Mixing LINQ and COM objects is not a really good idea. You should release underlying COM objects instantly to prevent any known issues.
If you need to search for items in all folders you may use the AdvancedSearch method of the Application class which allows to perform a search based on a specified DAV Searching and Locating (DASL) search string.
The key benefits of using the AdvancedSearch method in Outlook are:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
You can stop the search process at any moment using the Stop method of the Search class.
Read more about that in the Advanced search in Outlook programmatically: C#, VB.NET article.
I have run into a problem where I need to manually click the clear cache button for a specific product to appear correct on a specific page after it's saved.
I'm wondering how I can go about this with code, but only clear the cache for that product.
clearing complete cache can be done like this:
var _cacheManager = EngineContext.Current.Resolve<ICacheManager>();
_cacheManager.Clear();
I have tried doing it like this but it didn't work.
var product = _productService.GetProductById(productModel.Id);
var productTemplateCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_TEMPLATE_MODEL_KEY,
productModel.Id);
_cacheManager.Remove(productTemplateCacheKey);
Not sure how to go about this, anyone got any ideas?
Thanks
If you view a SharePoint calendar in MS Outlook and change the color of that item in Outlook, the SharePoint ows_MetaInfo gets changed from this:
2362;#
to This:
2362;#vti_encoding:SR|utf8-nl
FollowUp:SW|
vti_serverversion:SW|2
vti_versionhistory:SW|473e1c0c47cf034d9969c8513def1903:4
vti_clientversion:SW|4
BusyStatus:SW|2
Categories:SW|Red Category
Priority:SW|
IntendedBusyStatus:SW|
vti_externalversion:IW|3
I have a C# program that creates the SP calendar entry but I would like to be able to modify this ows_MetaInfo Categories property so that I can color code these items so that users that view this in Outlook will see these color codes.
I have searched on everything that I can thing of. I have seen people reading this ows_MetaInfo data but nothing that says how it can be changed. As stated earlier, I'm doing this in C# and I would like to change the ows_MetInfo Categories property so that Outlook users will see color coded calendar entries.
Any help would be Greatly Appreciated!
I've been searching around for quite some time to figure this out and I overlooked the most obvious answer... :) All I had to do was ask for help for me to finally figure it out! LOL :D
MetaInfo is just another String field. When you make a color change in Outlook to a SharePoint attached calendar item it, just adds text to that field that specifies the color along with some other default items. To change the color you can just specify it with something like cListItem["MetaInfo"] = "Categories:SW|Red Category\r\n"; and it will just change the Categories field leaving the others alone.
For completeness, I'm going to post my entire test example. (Because I hate it when I find the answer to a problem but only part of the answer is posted leaving me to guess at what else was in the code that made the example actually work :) )
This is done is VS2013 using a Console App
using Microsoft.SharePoint.Client;
using SP = Microsoft.SharePoint.Client;
using System.Net;
namespace SharePointSetMetaInfo
{
class Program
{
static void Main(string[] args)
{
using (ClientContext context = new ClientContext("https://mySharePointServer/sites/MySite/"))
{
context.Credentials = new NetworkCredential("myUserName", "myPassword", "MYDOMAIN");
SP.List calendarList = context.Web.Lists.GetByTitle("Calendar");
ListItem cListItem = calendarList.GetItemById(2301);//This is one way to retrieve an item for update. You can also use a Caml Query
context.Load(cListItem);
cListItem["MetaInfo"] = "Categories:SW|Red Category\r\n";
cListItem.Update();
context.ExecuteQuery();
}
}
}
}
Hopefully this helps someone else who is trying to programmatically change the colors on SharePoint calendar items as they show up in Outlook. This is not applicable to how SharePoint calendar items appear in SharePoint, only Outlook.
I've been getting a list of folders and files from Sharepoint (on Office 365) by using the following code...
...
var folders = ListFolders(libraryName, clientContext, web);
...
public List<Folder> ListFolders(string libraryName, ClientContext clientContext, Web web)
{
var list = GetDocumentLibrary(libraryName, clientContext, web);
var folders = list.RootFolder.Folders;
clientContext.Load(folders);
clientContext.ExecuteQuery();
return folders.ToList();
}
public List GetDocumentLibrary(string libraryName, ClientContext clientContext, Web web)
{
var query = clientContext.LoadQuery(web.Lists.Where(p => p.Title == libraryName));
clientContext.ExecuteQuery();
return query.FirstOrDefault();
}
It was working fine until I rebooted my computer (it installed a Windows Update), I strongly suspect, based on some testing I've done, it seems this is caused by http://support.microsoft.com/kb/2964358.
When the clientContext.ExecuteQuery() statement is reached in GetDocumentLibrary(), the
following exception is thrown.
An unhandled exception of type 'System.Xml.XmlException' occurred in System.Xml.dll
Additional information: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.
I'm wondering how I can work around this, as I'm not consciously using System.XML, it's a background function or process when the ExecuteQuery runs.
Can I pass some additional XMLReader info to this or clientContext (I'm assuming not), so I'm not sure how to execute this query to prevent the DTD error. I have also tried accessing the list in a different manner, by using this code... (from Microsoft's MSDN pages)
List list = clientContext.Web.Lists.GetByTitle(libraryName);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View/>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(list); clientContext.Load(listItems);
clientContext.ExecuteQuery();
This works on a computer without the KB above, however on my PC it doesn't (I get the same exception as my other code) , obviously uninstalling the KB will make things work in the short term, but its no good in the longer term. Any advice on how to avoid this error would be greatly appreciated. I can only assume there will be a "preferred" way from Microsoft for accessing lists now this KB is implemented, but I'm clueless as to what it is.
Thanks
Dougie
I was using a 2nd router as a WiFi extender, this seemed to have an odd, but reproducable effect when connecting to sharepoint, I stopped using it and used my main router/wifi box and my problem disappeared.
I had this same issue on a Virgin Media (UK based ISP) internet connection. It turns out that Virgin Media intercept web calls for the purpose of "advanced network error search". Luckily you can opt out from this. As soon as I did that it worked fine.
More details on the cause and how to opt out from Virgin Media's advanced search here: http://pryankrohilla.blogspot.co.uk/2014/05/error-resolved-connect-sposervice-for.html
I'm not happy about this, I left tweaking my program with a view to doing more diagnostics this morning, but now the issue seems to have mysteriously stopped happening, whether this has been tweaking at the MS end or not, or perhaps a glitch in SharePoint I've no idea, I don't think it's been my laptop since it's been on since I had the issue.
I need to get the direct reports from a logged in user (MVC 4)
I don't need the names of the direct reports but I do need their email addresses including their proxy addresses.
So for this reason I need to search through Exchange. I personally have never attempted to search Exchange in the past and everything I find out there tells me how to get from step 8 to the finish line but says nothing about how to go from step 1 to 8.
I can get the current users user name by simply
User.Identity.Name.Replace(#"yourdomain\", "")
and I have found this example which so far is probably the best example I have found
http://msdn.microsoft.com/en-us/library/office/ff184617(v=office.15).aspx
but even with that example the line
Outlook.AddressEntry currentUser =
Application.Session.CurrentUser.AddressEntry;
is not actually getting the current user logged into the site.
I really hope someone out there is familiar with this and can get me past this point.
I reworked the sample from the URL as the following LINQPad 4 query. I've found that LINQPad is a great way to experiment because it is very scripty, allowing quick experimentation, and you can easily view data by using the Dump() extension method. Purchasing intellisense support is totally worthwhile.
Also, I noticed there is a lot of fine print like:
The logged-on user must be online for this method to return an AddressEntries collection; otherwise, GetDirectReports returns a null reference. For production code, you must test for the user being offline by using the _NameSpace.ExchangeConnectionMode property, or the _Account.ExchangeConnectionMode property for multiple Exchange scenarios.
and
If the current user has a manager, GetDirectReports() is called to return an AddressEntries collection that represents the address entries for all the direct reports of user’s manager. If the manager has no direct reports, GetDirectReports returns an AddressEntries collection that has a count of zero.
So there are a lot of assumptions like Exchange is configured properly with Direct Report relationships, and the current user is online...which I believe brings Lync into the equation. Hopefully this LINQPad query will be useful to you. Just copy and paste it into a text editor and name it with the .linq file extension. You'll then be able to open it in LINQPad 4. BTW: You're question caught my attention because there was talk recently at my work of pulling direct reports from Active Directory. I wish I could be more helpful...good luck.
<Query Kind="Program">
<Reference><ProgramFilesX86>\Microsoft Visual Studio 12.0\Visual Studio Tools for Office\PIA\Office15\Microsoft.Office.Interop.Outlook.dll</Reference>
<Reference><ProgramFilesX86>\Microsoft Visual Studio 12.0\Visual Studio Tools for Office\PIA\Office15\Microsoft.Office.Interop.OutlookViewCtl.dll</Reference>
<Namespace>Microsoft.Office.Interop.Outlook</Namespace>
</Query>
void Main()
{
GetManagerDirectReports();
}
// Define other methods and classes here
private void GetManagerDirectReports()
{
var app = new Microsoft.Office.Interop.Outlook.Application();
AddressEntry currentUser = app.Session.CurrentUser.AddressEntry;
if (currentUser.Type == "EX")
{
ExchangeUser manager = currentUser.GetExchangeUser().GetExchangeUserManager();
manager.Dump();
if (manager != null)
{
AddressEntries addrEntries = manager.GetDirectReports();
if (addrEntries != null)
{
foreach (AddressEntry addrEntry in addrEntries)
{
ExchangeUser exchUser = addrEntry.GetExchangeUser();
StringBuilder sb = new StringBuilder();
sb.AppendLine("Name: " + exchUser.Name);
sb.AppendLine("Title: " + exchUser.JobTitle);
sb.AppendLine("Department: " + exchUser.Department);
sb.AppendLine("Location: " + exchUser.OfficeLocation);
sb.Dump();
}
}
}
}
}
I would suggest using EWS Managed API in conjunction with your code to get the direct reports for a user. As Jeremy mentioned in his response that you need to have your direct report relationships already set up. To help you get started, here some steps to get EWS Managed API up and running:
Download the latest version of EWS Managed API
Get started with EWS Managed API client applications to learn about how to reference the assembly, set the service URL, and communicate with EWS.
Start working with your code. If you need some functioning code to get you going, check out the Exchange 2013 101 Code Samples that has some authentication code already written and a bunch of examples you can modify to make your own.
If you have the email address or user name of the current user you can use the ResolveName() method to get to their mailbox to retrieve additional information. Here is an article to help with that method: How to: Resolve ambiguous names by using EWS in Exchange 2013
Essentially you want to get to the point where you can run a command similar to this:
NameResolutionCollection coll = service.ResolveName(NameToResolve, ResolveNameSearchLocation.DirectoryOnly, true, new PropertySet(BasePropertySet.FirstClassProperties));
If you give a unique enough value in the NameToResolve parameter you should only get back one item in the collection. With that, you can look at the direct reports collection within that one item and see not only the names of their direct reports, but their email addresses as well.
I hope this information helps. If this does resolve your problem, please mark the post as answered.
Thanks,
--- Bob ---