Tuesday, February 22, 2011

How to manage processes in poweshell

Have you needed to automate little things on your PC. I have a fixed set of things to run in the morning when I start my laptop at work, things like Outlook, IE with yahoo, gmail & facebook, my work diary etc. I find that powershell is very handy at doing this sort of thing. Here's a little script that I use:

[System.Diagnostics.Process]::Start("outlook")
$ie=new-object -com internetexplorer.application
$url1 = "www.google.com/mail/"
$url2 = "www.yahoo.com/mail"
$url3 = "www.facebook.com/yourURL"
$ie.visible=$true
$ie.navigate($url1)
$ie.navigate($url2,0x0800)
$ie.navigate($url3,0x0800)
[System.Diagnostics.Process]::Start("winword.exe", "Full Path to your doc")
[System.Diagnostics.Process]::Start("explorer")

Additionally, check out the following link which explains starting processes in detail:
http://blogs.msdn.com/b/powershell/archive/2007/01/16/managing-processes-in-powershell.aspx

Monday, February 14, 2011

Getting Intellisense with Visual Studio (& a little wiser with your life)

So if you're out there creating a content type programmatically, you know you're up against something formidable. You have to write a bunch of XML & you dont get any help from Visual Studio. Seriously, SharePoint development has to use more classes & less XML.

Fret not though, use the following link to add intellisense to creating SharePoint XML through Visual Studio:

http://www.andrewconnell.com/blog/archive/2006/10/20/4944.aspx

Basically, you just refer to wss.xsd found at 12\Templates\XML\wss.xsd in the schemas property of the XML file in Visual Studio.

Next tip, you know that content types form the base of everything in SharePoint, so if you ever need to find all the content types that SharePoint ships with, here's where you need to look:

12\Template\Features\ctypes\ctypeswss.xml

Easy to remember, if you're looking for the schema, go to hive\templates\XML\wss.xsd & if you're looking for content types definitions, go to hive\temples\features\ctypes & find ctypeswss.xml.

Looking at the content types defined, I realized that many of the fields that we assume exist with a content type, are created because they are defined in this ctypeswss.xml. For e.g. I always wondered about where the created_by & modified_by & modified_date fields were defined with the document library items. I realized that they exist, because they are FieldsRefs by the content type & that they are hidden by definition.

Last tip, if you ever need to find SP logs, they exist at Hive\Logs.

That brings me to getting wiser in life ... it's simple ... in the mad rush of our fast paced lives, you need to find that time of the day where you're alone & calm & then think ... have patience, this too shall pass.

Friday, February 11, 2011

SPListItem SystemUpdate()

SPListItem.SystemUpdate() is an exciting new function that I've learned about today.

SystemUpdate() allows you to update a list item without changing the following fields:
1. Modified Date
2. Modified By
3. And optionally - version of the list item

I just tried this function & it actually works. I will be trying to see if this can work with the document libraries as well as with attachments in a list item (the SPFile object). I've tried to add/delete attachments of a list item with this function, & the results are as the documentation claims it should be.

Thursday, February 10, 2011

Identity and Principal

What's Identity and Principal in .NET terms? What is the significance of something like




AppDomain.CurrentDomain.SetPrinicpalPolicy(PrincipalPolicy.WindowsPrincipal)



I've just started to investigate this while Identity & Principal thing & found the following link to be quite useful:
http://www.codeguru.com/Csharp/.NET/net_security/authentication/article.php/c7415/

Quite a few things from the post below are taken from Klaus' link above, so thanks to Klaus for an excellent article.

Just a few things about what I've learnt from that article:

  1. Identity is who you are. It's used in authentication
  2. Principal = Identity + groups of which you are a member of. Used for authorization.
The IPrincipal has a property that exposes the IIdentity interface as well as the method IsInRole(). This makes it clear that the Principal object can be used to get the identity of the user running the app, as well as the roles that he/she is in.

Now coming to the significance of the line above: Thread.CurrentPrinicpal gives you access to the current principal assigned to the executing thread. By default, this will be an unauthenticated principal. The framework provides two different types of principals, a Windows principal (WindowsPrincipal) and a generic principal (GenericPrincipal).

By calling SetPrincipalPolicy on the current AppDomain, you tell the framework which principal needs to be attached to this thread. You need to set this before you access the principal the first time.

Calling Thread.CurrentPrincipal returns the principal bound to the executing thread. The first time, this tells the framework to go off and query for the Windows user information, create a Windows identity, and then a Windows principal, and bind it to this thread. From the Windows principal, you then can access the Windows identity.

Another way to do this is as follows:

WindowsIdentity Identity = WindowsIdentity.GetCurrent();


WindowsIdentity.GetCurrent() goes off and queries the Windows user information and creates a Windows identity object representing that user. With that, you can create a new Windows principal passing along the Windows identity. The disadvantage of that approach is that each time it goes off and queries for the Windows user information and creates a new principal and identity object. The first approach reuses the same Windows principal and identity each time.

Now the best thing about the Identity & Principal objects, is that it allows you to use the same methods to for different types of identity & principals. For e.g. if you have authentication against a database, then you can use custom identity & principal objects & extend the concept from WindowsPrincipal to your own custom prinicpal. You can create your own Principal & Identity objects & then assign that principal to the current thread:

public class SecurityPrincipal : IPrincipal ...

//assign this principal to the current thread
Thread.CurrentPrincipal = TheSecurityPrincipal;

See Klaus' article for an excellent coverage of how to extend the .NET Identity & Principal concepts to custom principals.

Wednesday, February 9, 2011

Programmatically iterating through discussion lists

On further testing, I've discovered that my last post wasnt quite accurate.

Each post in a discussion thread is actually a folder. Replies to that post are kept in that folder. So if you do a recursive CAML query by ID on the entire list, for some strange reason, you get back all the replies - for other posts as well.

So the better way of doing it is to iterate through the posts by iterating through the ListItemCollection on the discussion list - which gives you all the posts. To get all the replies, use the following simple code:

foreach (int topicID in topics)
{
SPQuery q = new SPQuery();

SPListItem item = list.GetItemById(topicID);
q.Folder = item.Folder;


SPListItemCollection replies = null;

replies = list.GetItems(q);

foreach (SPListItem reply in replies)
{
//There's usually no subject, just the body
Console.WriteLine(reply["Body"].ToString());


Console.WriteLine();
Console.WriteLine();
}
}

Friday, February 4, 2011

Programmatically retrieving discussion list items

I spent the entire day yesterday, trying to figure out how to programmatically retrieve discussion lists. While this is still work in progress, here's some sample code that can help you do this.

using (SPSite site = new SPSite(Constants.siteCollectionURL))
{
using (SPWeb web = site.RootWeb)
{
SPList list = web.Lists["Team Discussion"];

//Get the items in the list
SPListItemCollection listItemCollection = list.GetItems(new SPQuery());

//Either you can get the topics this way or the Query method above. Both work fine.
//SPListItemCollection listItemCollection = list.Folders;

//Store all the topics in a list
List topics = new List();

//Iterate through the items
foreach (SPListItem listItem in listItemCollection)
{
//Display the subject and the body of the topic
Console.WriteLine(listItem["Subject"].ToString());
Console.WriteLine(listItem["Body"].ToString());


if (listItem["Parent Folder Id"] != null)
{
Console.WriteLine(listItem["Parent Folder Id"].ToString());
}
else
{
//Store the topic ID for later
topics.Add((Int32)listItem["ID"]);

}


}


//For each topic get all the replies
foreach (int topicID in topics)
{
//Get all the replies
String strQ = @" @TOKEN";
string sTopicID = Convert.ToString(topicID);
strQ = strQ.Replace("@TOKEN", sTopicID);
SPQuery q = new SPQuery();
q.ViewAttributes = "Scope=\"Recursive\"";
q.Query = strQ;

SPListItemCollection replies = list.GetItems(q);

foreach (SPListItem reply in replies)
{
//There's usually o subject, just the body
Console.WriteLine(reply["Body"].ToString());
}
}

}
}