Tuesday, January 25, 2011

Recursively set SharePoint MasterPages and CSS

Here is a quick sample of how to set master pages and CSS recursively and make sure that they are inherited from the parent site. This would be used within a SharePoint project’s FeatureEventReceiver class.

using System;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
namespace Acme.Intranet.Ui.Features.Feature1
public class Feature1EventReceiver : SPFeatureReceiver
public override void FeatureActivated(SPFeatureReceiverProperties properties)
using (SPSite site = (SPSite)properties.Feature.Parent)
using (SPWeb web = site.RootWeb)
string masterPageUrl = new Uri(web.Url + "/_catalogs/masterpage/Custom.master").AbsolutePath;
web.MasterUrl = masterPageUrl;
web.CustomMasterUrl = masterPageUrl;
foreach (SPWeb childWeb in web.Webs)
SetMasterPagesAndCss(site.Url, childWeb.ServerRelativeUrl, masterPageUrl, true);

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
using (SPSite site = (SPSite)properties.Feature.Parent)
using (SPWeb web = site.RootWeb)
string masterPageUrl = new Uri(web.Url + "/_catalogs/masterpage/v4.master").AbsolutePath;
web.MasterUrl = masterPageUrl;
web.CustomMasterUrl = masterPageUrl;
foreach (SPWeb childWeb in web.Webs)
SetMasterPagesAndCss(site.Url, childWeb.ServerRelativeUrl, masterPageUrl, false);

public void SetMasterPagesAndCss(string siteUrl, string webUrl, string masterPageUrl, bool inheritsMasterAndCss)
string boolVal = "False";
if (inheritsMasterAndCss)
boolVal = "True";
using (SPSite site = new SPSite(siteUrl))
using (SPWeb web = site.OpenWeb(webUrl))
web.Navigation.UseShared = true;
web.MasterUrl = masterPageUrl;
web.AllProperties["__InheritsMasterUrl"] = boolVal;
web.CustomMasterUrl = masterPageUrl;
web.AllProperties["__InheritsCustomMasterUrl"] = boolVal;
web.AlternateCssUrl = web.ParentWeb.AlternateCssUrl;
web.AllProperties["__InheritsAlternateCssUrl"] = boolVal;
foreach (SPWeb childWeb in web.Webs)
SetMasterPagesAndCss(siteUrl, childWeb.ServerRelativeUrl, masterPageUrl, inheritsMasterAndCss);

Friday, January 21, 2011

Create AD Users in bulk with PowerShell

This code snippet allows you to easily create multiple users. This is helpful when you need a bunch of test accounts on your DEV environment.

function CreateUser($userName, $password)
$adObject = "WinNT://" + [System.Environment]::MachineName + ",computer" #Assumes computer name
$AD = New-Object System.DirectoryServices.DirectoryEntry($adObject)
$NewUser = $AD.Children.Add($userName, "user")
$NewUser.Invoke("SetPassword", $password)
Write-Host "User " + $username" + created successfully."


CreateUser "IntranetOwner" "pass@word1"
CreateUser "IntranetMember" "pass@word1"
CreateUser "IntranetVisitor" "pass@word1"

CreateUser "FIOwner" "pass@word1"
CreateUser "FIMember" "pass@word1"
CreateUser "FIVisitor" "pass@word1"

CreateUser "HROwner" "pass@word1"
CreateUser "HRMember" "pass@word1"
CreateUser "HRVisitor" "pass@word1"

CreateUser "ISOwner" "pass@word1"
CreateUser "ISMember" "pass@word1"
CreateUser "ISVisitor" "pass@word1"

CreateUser "MKTOwner" "pass@word1"
CreateUser "MKTMember" "pass@word1"
CreateUser "MKTVisitor" "pass@word1"

Use SharePoint Web Services to export all User Profile data to CSV

Here is a an easy way to get user profile data out of SharePoint. The solution uses web services so you don’t have to worry about having access to the server. It will work with SharePoint 2007 and SharePoint 2010.

1. Create a Visual Studio Console Application.
Make a web service reference to the following web services:

http://portalname/_vti_bin/usergroup.asmx (Name it UserGroupWs)
http://portalname/_vti_bin/userprofileservice.asmx (Name it UserProfileServiceWs)

3. Copy the following code and run it! It will save a file to your desktop called SharePointUserData.csv.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using ConsoleApplication1.UserGroupWs;
using ConsoleApplication1.UserProfileServiceWs;

namespace ConsoleApplication1
class Program
static void Main(string[] args)
UserInfo ui = new UserInfo();
List<UserInfo> userInfo = ui.GetUserInfo();
StringBuilder sb = new StringBuilder();
foreach (UserInfo u in userInfo)
sb.Append(u.AboutMe + ",");
sb.Append(u.AccountName + ",");
sb.Append(u.ADGuid + ",");
sb.Append(u.Assistant + ",");
sb.Append(u.CellPhone + ",");
sb.Append(u.Department + ",");
sb.Append(u.Fax + ",");
sb.Append(u.FirstName + ",");
sb.Append(u.HomePhone + ",");
sb.Append(u.LastName + ",");
sb.Append(u.Manager + ",");
sb.Append(u.Office + ",");
sb.Append(u.PersonalSpace + ",");
sb.Append(u.PictureURL + ",");
sb.Append(u.PreferredName + ",");
sb.Append(u.PublicSiteRedirect + ",");
sb.Append(u.QuickLinks + ",");
sb.Append(u.SID + ",");
sb.Append(u.SPSAboutUs + ",");
sb.Append(u.SPSBirthday + ",");
sb.Append(u.SPSClaimID + ",");
sb.Append(u.SPSClaimProviderID + ",");
sb.Append(u.SPSClaimProviderType + ",");
sb.Append(u.SPSDataSource + ",");
sb.Append(u.SPSDisplayOrder + ",");
sb.Append(u.SPSDistinguishedName + ",");
sb.Append(u.SPSDontSuggestList + ",");
sb.Append(u.SPSDottedline + ",");
sb.Append(u.SPSEmailOptin + ",");
sb.Append(u.SPSFormerNames + ",");
sb.Append(u.SPSHireDate + ",");
sb.Append(u.SPSInterests + ",");
sb.Append(u.SPSJobTitle + ",");
sb.Append(u.SPSLastColleagueAdded + ",");
sb.Append(u.SPSLastKeywordAdded + ",");
sb.Append(u.SPSLocation + ",");
sb.Append(u.SPSLogoURL + ",");
sb.Append(u.SPSMasterAccountName + ",");
sb.Append(u.SPSMemberOf + ",");
sb.Append(u.SPSMySiteUpgrade + ",");
sb.Append(u.SPSObjectExists + ",");
sb.Append(u.SPSOWAUrl + ",");
sb.Append(u.SPSParent + ",");
sb.Append(u.SPSParentType + ",");
sb.Append(u.SPSPastProjects + ",");
sb.Append(u.SPSPeers + ",");
sb.Append(u.SPSPhoneticDisplayName + ",");
sb.Append(u.SPSPhoneticFirstName + ",");
sb.Append(u.SPSPhoneticLastName + ",");
sb.Append(u.SPSProxyAddresses + ",");
sb.Append(u.SPSResourceAccountName + ",");
sb.Append(u.SPSResourceSID + ",");
sb.Append(u.SPSResponsibility + ",");
sb.Append(u.SPSSavedAccountName + ",");
sb.Append(u.SPSSavedSID + ",");
sb.Append(u.SPSSchool + ",");
sb.Append(u.SPSSectionBasicInfo + ",");
sb.Append(u.SPSSectionContactInfo + ",");
sb.Append(u.SPSSectionCustomProperties + ",");
sb.Append(u.SPSSectionDelegation + ",");
sb.Append(u.SPSSectionDetails + ",");
sb.Append(u.SPSSectionOrganizationMembers + ",");
sb.Append(u.SPSSectionPreferences + ",");
sb.Append(u.SPSSipAddress + ",");
sb.Append(u.SPSSkills + ",");
sb.Append(u.SPSSourceObjectDN + ",");
sb.Append(u.SPSStatustes + ",");
sb.Append(u.SPSTeamSite + ",");
sb.Append(u.SPSTimeZone + ",");
sb.Append(u.Title + ",");
sb.Append(u.UserName + ",");
sb.Append(u.UserProfile_GUID + ",");
sb.Append(u.WebSite + ",");
sb.Append(u.WorkEmail + ",");
TextWriter tw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + "SharePointUserData.csv");

public class UserInfo
public int counter { get; set; }
public string AboutMe {get;set;}
public string AccountName {get;set;}
public string ADGuid {get;set;}
public string Assistant {get;set;}
public string CellPhone {get;set;}
public string Department {get;set;}
public string Fax {get;set;}
public string FirstName {get;set;}
public string HomePhone {get;set;}
public string LastName {get;set;}
public string Manager {get;set;}
public string Office {get;set;}
public string PersonalSpace {get;set;}
public string PictureURL {get;set;}
public string PreferredName {get;set;}
public string PublicSiteRedirect {get;set;}
public string QuickLinks {get;set;}
public string SID {get;set;}
public string SPSAboutUs {get;set;}
public string SPSBirthday {get;set;}
public string SPSClaimID {get;set;}
public string SPSClaimProviderID {get;set;}
public string SPSClaimProviderType {get;set;}
public string SPSDataSource {get;set;}
public string SPSDisplayOrder {get;set;}
public string SPSDistinguishedName {get;set;}
public string SPSDontSuggestList {get;set;}
public string SPSDottedline {get;set;}
public string SPSEmailOptin {get;set;}
public string SPSFormerNames {get;set;}
public string SPSHireDate {get;set;}
public string SPSInterests {get;set;}
public string SPSJobTitle {get;set;}
public string SPSLastColleagueAdded {get;set;}
public string SPSLastKeywordAdded {get;set;}
public string SPSLocation {get;set;}
public string SPSLogoURL {get;set;}
public string SPSMasterAccountName {get;set;}
public string SPSMemberOf {get;set;}
public string SPSMySiteUpgrade {get;set;}
public string SPSObjectExists {get;set;}
public string SPSOWAUrl {get;set;}
public string SPSParent {get;set;}
public string SPSParentType {get;set;}
public string SPSPastProjects {get;set;}
public string SPSPeers {get;set;}
public string SPSPhoneticDisplayName {get;set;}
public string SPSPhoneticFirstName {get;set;}
public string SPSPhoneticLastName {get;set;}
public string SPSProxyAddresses {get;set;}
public string SPSResourceAccountName {get;set;}
public string SPSResourceSID {get;set;}
public string SPSResponsibility {get;set;}
public string SPSSavedAccountName {get;set;}
public string SPSSavedSID {get;set;}
public string SPSSchool {get;set;}
public string SPSSectionBasicInfo {get;set;}
public string SPSSectionContactInfo {get;set;}
public string SPSSectionCustomProperties {get;set;}
public string SPSSectionDelegation {get;set;}
public string SPSSectionDetails {get;set;}
public string SPSSectionOrganizationMembers {get;set;}
public string SPSSectionPreferences {get;set;}
public string SPSSipAddress {get;set;}
public string SPSSkills {get;set;}
public string SPSSourceObjectDN {get;set;}
public string SPSStatustes {get;set;}
public string SPSTeamSite {get;set;}
public string SPSTimeZone {get;set;}
public string Title {get;set;}
public string UserName {get;set;}
public string UserProfile_GUID {get;set;}
public string WebSite {get;set;}
public string WorkEmail {get;set;}
public string WorkPhone {get;set;}

public List<UserInfo> GetUserInfo()
UserGroup userGroup = new UserGroup();
userGroup.UseDefaultCredentials = true;
XmlNode allUsers = userGroup.GetAllUserCollectionFromWeb();
XNode xNode = XDocument.Parse(allUsers.OuterXml);
return (from root in xNode.Document.Elements()
from users in root.Elements()
from user in users.Elements()
let loginName = (string)user.Attribute("LoginName")
let userInfo = GetUserInfoDetails(loginName)
select new UserInfo()
AboutMe = userInfo.AboutMe,
AccountName = userInfo.AccountName,
ADGuid = userInfo.ADGuid,
Assistant = userInfo.Assistant,
CellPhone = userInfo.CellPhone,
Department = userInfo.Department,
Fax = userInfo.Fax,
FirstName = userInfo.FirstName,
HomePhone = userInfo.HomePhone,
LastName = userInfo.LastName,
Manager = userInfo.Manager,
Office = userInfo.Office,
PersonalSpace = userInfo.PersonalSpace,
PictureURL = userInfo.PictureURL,
PreferredName = userInfo.PreferredName,
PublicSiteRedirect = userInfo.PublicSiteRedirect,
QuickLinks = userInfo.QuickLinks,
SID = userInfo.SID,
SPSAboutUs = userInfo.SPSAboutUs,
SPSBirthday = userInfo.SPSBirthday,
SPSClaimID = userInfo.SPSClaimID,
SPSClaimProviderID = userInfo.SPSClaimProviderID,
SPSClaimProviderType = userInfo.SPSClaimProviderType,
SPSDataSource = userInfo.SPSDataSource,
SPSDisplayOrder = userInfo.SPSDisplayOrder,
SPSDistinguishedName = userInfo.SPSDistinguishedName,
SPSDontSuggestList = userInfo.SPSDontSuggestList,
SPSDottedline = userInfo.SPSDottedline,
SPSEmailOptin = userInfo.SPSEmailOptin,
SPSFormerNames = userInfo.SPSFormerNames,
SPSHireDate = userInfo.SPSHireDate,
SPSInterests = userInfo.SPSInterests,
SPSJobTitle = userInfo.SPSJobTitle,
SPSLastColleagueAdded = userInfo.SPSLastColleagueAdded,
SPSLastKeywordAdded = userInfo.SPSLastKeywordAdded,
SPSLocation = userInfo.SPSLocation,
SPSLogoURL = userInfo.SPSLogoURL,
SPSMasterAccountName = userInfo.SPSMasterAccountName,
SPSMemberOf = userInfo.SPSMemberOf,
SPSMySiteUpgrade = userInfo.SPSMySiteUpgrade,
SPSObjectExists = userInfo.SPSObjectExists,
SPSOWAUrl = userInfo.SPSOWAUrl,
SPSParent = userInfo.SPSParent,
SPSParentType = userInfo.SPSParentType,
SPSPastProjects = userInfo.SPSPastProjects,
SPSPeers = userInfo.SPSPeers,
SPSPhoneticDisplayName = userInfo.SPSPhoneticDisplayName,
SPSPhoneticFirstName = userInfo.SPSPhoneticFirstName,
SPSPhoneticLastName = userInfo.SPSPhoneticLastName,
SPSProxyAddresses = userInfo.SPSProxyAddresses,
SPSResourceAccountName = userInfo.SPSResourceAccountName,
SPSResourceSID = userInfo.SPSResourceSID,
SPSResponsibility = userInfo.SPSResponsibility,
SPSSavedAccountName = userInfo.SPSSavedAccountName,
SPSSavedSID = userInfo.SPSSavedSID,
SPSSchool = userInfo.SPSSchool,
SPSSectionBasicInfo = userInfo.SPSSectionBasicInfo,
SPSSectionContactInfo = userInfo.SPSSectionContactInfo,
SPSSectionCustomProperties = userInfo.SPSSectionCustomProperties,
SPSSectionDelegation = userInfo.SPSSectionDelegation,
SPSSectionDetails = userInfo.SPSSectionDetails,
SPSSectionOrganizationMembers = userInfo.SPSSectionOrganizationMembers,
SPSSectionPreferences = userInfo.SPSSectionPreferences,
SPSSipAddress = userInfo.SPSSipAddress,
SPSSkills = userInfo.SPSSkills,
SPSSourceObjectDN = userInfo.SPSSourceObjectDN,
SPSStatustes = userInfo.SPSStatustes,
SPSTeamSite = userInfo.SPSTeamSite,
SPSTimeZone = userInfo.SPSTimeZone,
Title = userInfo.Title,
UserName = userInfo.UserName,
UserProfile_GUID = userInfo.UserProfile_GUID,
WebSite = userInfo.WebSite,
WorkEmail = userInfo.WorkEmail,
WorkPhone = userInfo.WorkPhone


private UserInfo GetUserInfoDetails(string loginName)
Console.WriteLine(counter++.ToString() + " - " + loginName);
UserInfo userInfo = new UserInfo();
UserProfileService userProfileService = new UserProfileService();
userProfileService.UseDefaultCredentials = true;
PropertyData[] data = userProfileService.GetUserProfileByName(loginName);
string pictureUrl = GetPropertyData(data, "PictureURL");
userInfo.AboutMe = GetPropertyData(data, "AboutMe");
userInfo.AccountName = GetPropertyData(data, "AccountName");
userInfo.ADGuid = GetPropertyData(data, "ADGuid");
userInfo.Assistant = GetPropertyData(data, "Assistant");
userInfo.CellPhone = GetPropertyData(data, "CellPhone");
userInfo.Department = GetPropertyData(data, "Department");
userInfo.Fax = GetPropertyData(data, "Fax");
userInfo.FirstName = GetPropertyData(data, "FirstName");
userInfo.HomePhone = GetPropertyData(data, "HomePhone");
userInfo.LastName = GetPropertyData(data, "LastName");
userInfo.Manager = GetPropertyData(data, "Manager");
userInfo.Office = GetPropertyData(data, "Office");
userInfo.PersonalSpace = GetPropertyData(data, "PersonalSpace");
userInfo.PictureURL = GetPropertyData(data, "PictureURL");
userInfo.PreferredName = GetPropertyData(data, "PreferredName");
userInfo.PublicSiteRedirect = GetPropertyData(data, "PublicSiteRedirect");
userInfo.QuickLinks = GetPropertyData(data, "QuickLinks");
userInfo.SID = GetPropertyData(data, "SID");
userInfo.SPSAboutUs = GetPropertyData(data, "SPS-AboutUs");
userInfo.SPSBirthday = GetPropertyData(data, "SPS-Birthday");
userInfo.SPSClaimID = GetPropertyData(data, "SPS-ClaimID");
userInfo.SPSClaimProviderID = GetPropertyData(data, "SPS-ClaimProviderID");
userInfo.SPSClaimProviderType = GetPropertyData(data, "SPS-ClaimProviderType");
userInfo.SPSDataSource = GetPropertyData(data, "SPS-DataSource");
userInfo.SPSDisplayOrder = GetPropertyData(data, "SPS-DisplayOrder");
userInfo.SPSDistinguishedName = GetPropertyData(data, "SPS-DistinguishedName");
userInfo.SPSDontSuggestList = GetPropertyData(data, "SPS-DontSuggestList");
userInfo.SPSDottedline = GetPropertyData(data, "SPS-Dotted-line");
userInfo.SPSEmailOptin = GetPropertyData(data, "SPS-EmailOptin");
userInfo.SPSFormerNames = GetPropertyData(data, "SPS-FormerNames");
userInfo.SPSHireDate = GetPropertyData(data, "SPS-HireDate");
userInfo.SPSInterests = GetPropertyData(data, "SPS-Interests");
userInfo.SPSJobTitle = GetPropertyData(data, "SPS-JobTitle");
userInfo.SPSLastColleagueAdded = GetPropertyData(data, "SPS-LastColleagueAdded");
userInfo.SPSLastKeywordAdded = GetPropertyData(data, "SPS-LastKeywordAdded");
userInfo.SPSLocation = GetPropertyData(data, "SPS-Location");
userInfo.SPSLogoURL = GetPropertyData(data, "SPS-LogoURL");
userInfo.SPSMasterAccountName = GetPropertyData(data, "SPS-MasterAccountName");
userInfo.SPSMemberOf = GetPropertyData(data, "SPS-MemberOf");
userInfo.SPSMySiteUpgrade = GetPropertyData(data, "SPS-MySiteUpgrade");
userInfo.SPSObjectExists = GetPropertyData(data, "SPS-ObjectExists");
userInfo.SPSOWAUrl = GetPropertyData(data, "SPS-OWAUrl");
userInfo.SPSParent = GetPropertyData(data, "SPS-Parent");
userInfo.SPSParentType = GetPropertyData(data, "SPS-ParentType");
userInfo.SPSPastProjects = GetPropertyData(data, "SPS-PastProjects");
userInfo.SPSPeers = GetPropertyData(data, "SPS-Peers");
userInfo.SPSPhoneticDisplayName = GetPropertyData(data, "SPS-PhoneticDisplayName");
userInfo.SPSPhoneticFirstName = GetPropertyData(data, "SPS-PhoneticFirstName");
userInfo.SPSPhoneticLastName = GetPropertyData(data, "SPS-PhoneticLastName");
userInfo.SPSProxyAddresses = GetPropertyData(data, "SPS-ProxyAddresses");
userInfo.SPSResourceAccountName = GetPropertyData(data, "SPS-ResourceAccountName");
userInfo.SPSResourceSID = GetPropertyData(data, "SPS-ResourceSID");
userInfo.SPSResponsibility = GetPropertyData(data, "SPS-Responsibility");
userInfo.SPSSavedAccountName = GetPropertyData(data, "SPS-SavedAccountName");
userInfo.SPSSavedSID = GetPropertyData(data, "SPS-SavedSID");
userInfo.SPSSchool = GetPropertyData(data, "SPS-School");
userInfo.SPSSectionBasicInfo = GetPropertyData(data, "SPS-Section-BasicInfo");
userInfo.SPSSectionContactInfo = GetPropertyData(data, "SPS-Section-ContactInfo");
userInfo.SPSSectionCustomProperties = GetPropertyData(data, "SPS-Section-CustomProperties");
userInfo.SPSSectionDelegation = GetPropertyData(data, "SPS-Section-Delegation");
userInfo.SPSSectionDetails = GetPropertyData(data, "SPS-Section-Details");
userInfo.SPSSectionOrganizationMembers = GetPropertyData(data, "SPS-Section-OrganizationMembers");
userInfo.SPSSectionPreferences = GetPropertyData(data, "SPS-Section-Preferences");
userInfo.SPSSipAddress = GetPropertyData(data, "SPS-SipAddress");
userInfo.SPSSkills = GetPropertyData(data, "SPS-Skills");
userInfo.SPSSourceObjectDN = GetPropertyData(data, "SPS-SourceObjectDN");
userInfo.SPSStatustes = GetPropertyData(data, "SPS-Statustes");
userInfo.SPSTeamSite = GetPropertyData(data, "SPS-Team-Site");
userInfo.SPSTimeZone = GetPropertyData(data, "SPS-TimeZone");
userInfo.Title = GetPropertyData(data, "Title");
userInfo.UserName = GetPropertyData(data, "UserName");
userInfo.UserProfile_GUID = GetPropertyData(data, "UserProfile_GUID");
userInfo.WebSite = GetPropertyData(data, "WebSite");
userInfo.WorkEmail = GetPropertyData(data, "WorkEmail");
userInfo.WorkPhone = GetPropertyData(data, "WorkPhone");

catch (System.Web.Services.Protocols.SoapException ex)
//It appears that an exception gets generated for users
//that have not logged into SharePoint yet.
//They must logon for a profile to be created.
if (!ex.Message.Contains("A user with the account name"))
return userInfo;

private string GetPropertyData(PropertyData[] data, string columnName)
//Delimit properties with a semi-colon or comma.
string returnValue = string.Empty;
returnValue = string.Join("; ",
(from v in
((PropertyData)data.Where(x => x.Name == columnName).Single()).Values
select v.Value.ToString()).ToArray());
catch (Exception ex)

return returnValue;

Monday, January 17, 2011

Use PowerShell to easily disable or enable SharePoint Publishing site workflows, moderation, and checkout

SharePoint Publishing Sites are strict by their very nature and have a number of security controls enabled by default such as approval workflows, moderation, and checkout. Obviously these features are important and are there for good reason, but they also have the potential to slow down the development and even the deployment process. Oftentimes you need to be able easily edit a masterpage or add a bunch of sample documents for testing. While you can disable workflows, moderation, and checkout through the user interface, it’s not something you can do very quickly, especially if you need it done recursively. The following script makes this much easier and allows you to disable or re-enable all of these features.


  1. Copy the following in Notepad.
  2. Update the last function $siteUrl and $webUrls variables.
    • $siteUrl – This is the site collection URL. For example, http://portalname
    • $webUrls – This is an array that you can use target subsites. For example, in the case of a Departments subsite with HR, IT, and Marketing subsites: "/dep", "/dep/hr","/dep/it","/dep/mkt"
  3. Toggle between $true and $false statements at the bottom of the script to disable or enable. You could also create two separate scripts.
  4. Save the file as a “.ps1” file.
  5. Run as an Administrator on your SharePoint environment.

Source Code

function RemoveApprovalWorkflow($siteUrl, $webUrl, $listName, $workFlowName)
$site = Get-SPSite $siteUrl
$web = $site.OpenWeb($webUrl)
$list = $web.Lists[$listName]
if(!($list -eq $null))
$wa = $list.WorkflowAssociations.GetAssociationByName($workFlowName, [System.Globalization.CultureInfo]::CurrentCulture)
if(!($wa -eq $null))
Write-Host "Removing " $wa.Name " from " $listName
Write-Host "Finished Removing Workflow "$workFlowName" from "$siteUrl$webUrl"/"$listName

function AddApprovalWorkflow($siteUrl, $webUrl, $listName, $workflowTemplateName, $workflowName, $workflowTaskName, $workflowHistoryName)
$site = Get-SPSite $siteUrl
$web = $site.OpenWeb($webUrl)
$list = $web.Lists[$listName]
if(!($list -eq $null))
$wfTemp = $web.WorkflowTemplates.GetTemplateByName($workflowTemplateName, [System.Globalization.CultureInfo]::CurrentCulture);
$wf = [Microsoft.SharePoint.Workflow.SPWorkflowAssociation]::CreateListAssociation($wfTemp, $workflowName, $web.Lists[$workflowTaskName], $web.Lists[$workflowHistoryName]);
$list.DefaultContentApprovalWorkflowId = $wf.Id
Write-Host "Finished Adding Workflow "$workflowTemplateName" to "$siteUrl$webUrl"/"$listName

function EnableMasterPageModerationCheckout($siteUrl, $enable)
$site = Get-SPSite $siteUrl
$list = $site.GetCatalog([Microsoft.SharePoint.SPListTemplateType]::MasterPageCatalog)
$list.EnableModeration = $enable
$list.ForceCheckout = $enable
Write-Host "MasterPage Moderation and Checkout on "$siteUrl" set to "$enable

function EnablePublishingWorkflowsModeration($enable)
$siteUrl = http://portalurl #CHANGE VARIABLE
$webUrls = @("/dep", "/dep/hr","/dep/it","/dep/mkt") #CHANGE VARIABLE
$listNames = @("Pages", "Documents", "Images") #Publishing Site Default Lists
EnableMasterPageModerationCheckout $siteUrl $enable
foreach($webUrl in $webUrls)
EnableMasterPageModerationCheckout $siteUrl $enable
foreach($listName in $listNames)
AddApprovalWorkflow $siteUrl $webUrl $listName "Publishing Approval" "Page Approval" "Workflow Tasks" "Workflow History"
RemoveApprovalWorkflow $siteUrl $webUrl $listName "Page Approval"

EnablePublishingWorkflowsModeration $false
#EnablePublishingWorkflowsModeration $true #Comment / UnComment


Tuesday, January 11, 2011

SharePoint SPRegionalSettings.GlobalTimeZones ID List

I couldn't find a reference for this anywhere, so decided to create my own.

2(UTC) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London
3(UTC+01:00) Brussels, Copenhagen, Madrid, Paris
4(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
5(UTC+02:00) Athens, Bucharest, Istanbul
6(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
7(UTC+02:00) Minsk
8(UTC-03:00) Brasilia
9(UTC-04:00) Atlantic Time (Canada)
10(UTC-05:00) Eastern Time (US and Canada)
11(UTC-06:00) Central Time (US and Canada)
12(UTC-07:00) Mountain Time (US and Canada)
13(UTC-08:00) Pacific Time (US and Canada)
14(UTC-09:00) Alaska
15(UTC-10:00) Hawaii
16(UTC-11:00) Midway Island, Samoa
17(UTC+12:00) Auckland, Wellington
18(UTC+10:00) Brisbane
19(UTC+09:30) Adelaide
20(UTC+09:00) Osaka, Sapporo, Tokyo
21(UTC+08:00) Kuala Lumpur, Singapore
22(UTC+07:00) Bangkok, Hanoi, Jakarta
23(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi
24(UTC+04:00) Abu Dhabi, Muscat
25(UTC+03:30) Tehran
26(UTC+03:00) Baghdad
27(UTC+02:00) Jerusalem
28(UTC-03:30) Newfoundland and Labrador
29(UTC-01:00) Azores
30(UTC-02:00) Mid-Atlantic
31(UTC) Monrovia, Reykjavik
32(UTC-03:00) Cayenne
33(UTC-04:00) Georgetown, La Paz, San Juan
34(UTC-05:00) Indiana (East)
35(UTC-05:00) Bogota, Lima, Quito
36(UTC-06:00) Saskatchewan
37(UTC-06:00) Guadalajara, Mexico City, Monterrey
38(UTC-07:00) Arizona
39(UTC-12:00) International Date Line West
40(UTC+12:00) Fiji Is., Marshall Is.
41(UTC+11:00) Magadan, Solomon Is., New Caledonia
42(UTC+10:00) Hobart
43(UTC+10:00) Guam, Port Moresby
44(UTC+09:30) Darwin
45(UTC+08:00) Beijing, Chongqing, Hong Kong S.A.R., Urumqi
46(UTC+06:00) Novosibirsk
47(UTC+05:00) Tashkent
48(UTC+04:30) Kabul
49(UTC+02:00) Cairo
50(UTC+02:00) Harare, Pretoria
51(UTC+03:00) Moscow, St. Petersburg, Volgograd
53(UTC-01:00) Cape Verde Is.
54(UTC+04:00) Baku
55(UTC-06:00) Central America
56(UTC+03:00) Nairobi
57(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb
58(UTC+05:00) Ekaterinburg
59(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius
60(UTC-03:00) Greenland
61(UTC+06:30) Yangon (Rangoon)
62(UTC+05:45) Kathmandu
63(UTC+08:00) Irkutsk
64(UTC+07:00) Krasnoyarsk
65(UTC-04:00) Santiago
66(UTC+05:30) Sri Jayawardenepura
67(UTC+13:00) Nuku'alofa
68(UTC+10:00) Vladivostok
69(UTC+01:00) West Central Africa
70(UTC+09:00) Yakutsk
71(UTC+06:00) Astana, Dhaka
72(UTC+09:00) Seoul
73(UTC+08:00) Perth
74(UTC+03:00) Kuwait, Riyadh
75(UTC+08:00) Taipei
76(UTC+10:00) Canberra, Melbourne, Sydney
77(UTC-07:00) Chihuahua, La Paz, Mazatlan
78(UTC-08:00) Tijuana, Baja California
79(UTC+02:00) Amman
80(UTC+02:00) Beirut
81(UTC-04:00) Manaus
82(UTC+04:00) Tbilisi
83(UTC+02:00) Windhoek
84(UTC+04:00) Yerevan
85(UTC-03:00) Buenos Aires
86(UTC) Casablanca
87(UTC+05:00) Islamabad, Karachi
88(UTC-04:30) Caracas
89(UTC+04:00) Port Louis
90(UTC-03:00) Montevideo
91(UTC-04:00) Asuncion
92(UTC+12:00) Petropavlovsk-Kamchatsky
93(UTC) Coordinated Universal Time
94(UTC+08:00) Ulaanbaatar

Source Code
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint;

namespace ConsoleApplication1
class Program
static void Main(string[] args)
SPTimeZoneCollection timeZones = SPRegionalSettings.GlobalTimeZones;
Dictionary timeZoneList = new Dictionary();
Console.WriteLine("\r\nSharePoint Global Time Zones");
foreach (SPTimeZone timeZone in timeZones)
timeZoneList.Add(timeZone.ID, timeZone.Description);
foreach (KeyValuePair time in timeZoneList.OrderBy(x => x.Key))
Console.WriteLine(time.Key.ToString() + "\t" + time.Value);
Console.WriteLine("\r\nHTML Format");
foreach (KeyValuePair time in timeZoneList.OrderBy(x => x.Key))
Console.WriteLine("" + time.Key.ToString() + "" + time.Value + "");


Saturday, January 8, 2011

Learn Japanese Kanji 常用漢字 with Microsoft Pivot Viewer

As a lifetime student of Japanese, I have always been interested in different ways to study and learn Japanese Kanji. Through the years the Japanese Ministry of Education has maintained a list of "jōyō kanji" or standard Chinese characters that were expected for students to learn through the years. Since 1981 this list was 1,945 characters, but in 2009 they added more characters and they now total a whopping 2,136.

Needless to say, learning these is is a huge undertaking and is especially daunting to non-native speakers. Although some characters can be easily identified as more ideographical in nature and contain concrete meanings (木 for tree), most characters are not and contain more abstract ideas or are only used in names. Unlike Chinese character readings, Japanese characters can also have multiple readings and maintain a separate reading called "on" (音) for the Chinese historical reading and "kun" (訓) for the Japanese reading . These readings can also change based on where they are used within a character compound or historical context. In fact, there are some characters that are not Chinese and were invented natively by the Japanese. One interesting example is the word "work" (働く). Besides all of this, there is also number of strokes and stroke order to worry about. Characters are written in a particular way and there are things like trailing strokes that must adhere to specific tools.

The beauty of the PivotViewer tool is that it allows you to slice and dice these characters in different ways. From an academic perspective it can be interesting to see things like how many characters contain a certain amount of strokes or how many are learned in the 3rd grade. Keep in mind takes a little time to load the tool the first time. Once you start using it, it will speed up.

  • 学年 - Scholastic year or year that the character is learned in school. 中高 means that the character is learned in middle or high school.
  • 画 - Number of strokes
  • 英語 - English description
  • 音読み - Onyomi or Chinese reading.
  • 訓読み - Kunyomi or Japanese reading.
  • 音読みローマ字 - Romanized onyomi rendering.
  • 訓読みローマ字 - Romanized kunyomi rendering
  • 音読み印引き - Onyomi index
  • 訓読み印引き - Kunyomi index

Pivot Viewer

Jōyō Kanji
- All of the information was taken from Wikipedia. I had to do some serious formatting to create a Pivot Collection.

Epson Fonts - I used EPSON太行書体B

Fun Fact
I use Microsoft, Google, and Amazon technologies for this page. Microsoft for PivotViewer, Google for Blogspot, and Amazon for hosting the xap and cxml files (DropBox uses Amazon cloud services).


Tuesday, January 4, 2011

SharePoint 2007 / 2010 - Silverlight Slide Show Web Part for Images and Videos

For those familiar with SharePoint 2007, you know that a slide show web part is nonexistent and in order to get this functionality you would either have to resort to a 3rd party web part or do some custom web part development. SharePoint 2010 does provide some out of the box web parts like the Picture Library Slide Show Web Part and the Media Web Part, however these do have limitations. Neither provide the ability for albums, the ability to mix video and images, or full screen functionality. The Media Web Part also only allows a single video to be embedded. Furthermore, getting the web part’s width and heights properties to render properly can be challenging. This web part mitigates all of these issues and provides the following functionality:

    • Web Part Configuration – Using out of the box SharePoint functionality, you can simply add this web part to a web part zone. The web part properties are context sensitive and will display appropriate SharePoint webs and Picture Libraries and Asset Libraries that can be used for the slide show.
    • Mixed Media – This slide show web part allows video and/or images within slide shows.
    • Album View– An album view allows you to create multiple albums within the slide show. Albums are based on the SharePoint library’s root level folders.
    • SharePoint 2007 and 2010 Compatible – I have created two projects since each platform has different deployment requirements and other subtle differences.
    • Embed Slide Show – If you have non SharePoint web pages, the slide show has a feature that allows you to easily copy and paste HTML code to be used for embedding in other web sites.
    • Full Screen Mode – Any slide show can be viewed in full screen mode simply by clicking a button on the web part.
    • Other – For a full list of slide show features, see the Slide.Show link in References below.


This web part was based on the popular and open source Vertigo Slide.Show project in CodePlex, which also has an XML and Flickr data provider. All images used within the screenshots below can be found within the CodePlex source code. For the SharePoint data provider code, I made just a few changes to the code provided in Mathew McDermott’s blog post on the subject. See References below for more details.

Installation Overview

I am not going to provide complete instructions here as both projects will use standard deployment steps, but I have outlined a few things that you should probably know.

Visual Studio Solution and Projects

When you open either solution, you will see that there are three projects: Samples, SlideShow, and SharePoint20xx.CustomControls. The Samples and SlideShow projects are a customized versions of Vertigo’s Slide.Show CodePlex source code. The SlideShow project is the Silverlight project and has been changed to add the SPDataProvider code, remove some of the out of the box branding, and a few other minor changes. I have also created post build events that copy the XAP file to the SharePoint20xx.CustomControls project since this is used by the web part. In this project, the most important file is the SPDataProvider.cs file. If Vertigo provides an update to the CodePlex project, you could copy this over and rebuild the project. Just make sure that the XAP file makes it way into the Web Part project. The SharePoint20xx.CustomControls contains all of the Web Part specific information and deploys the XAP and a png file to the SharePoint hive within CONTROLTEMPLATES\SharePoint20xx.CustomControls directory. The XAP file contains all of the Silverlight code and the png file is used for video thumbnails. (SharePoint actually has one, but since it is a GIF file and thus unsupported by Silverlight.) You may also want to change things like the elements.xml file as I kept the name and group of the web part generic.


The best way to debug is to set the Samples project as your StartUp project and the default.html page in the SharePoint folder as your Start Page in Visual Studio. Be sure to open the default.html file first and change the Web and List parameters appropriately. In order to play with the XML data providers, you are also going to need to download the original CodePlex project and add the Samples project’s Assets folder. This has an excellent collection of Silverlight compatible images and videos, but I have removed them from the download as they took up too much space.


For either 2008 or 2010 projects, you can simply use STSADM and the WSP file. If you are a development machine, you can use WSPBuilder for 2008 or for 2010, Visual Studio 2010. The SharePoint 2008 source code utilizes Visual Studio 2008, WSPBuilder extensions, and Silverlight 2.0 development tools. You are welcome to use Silverlight 3.0 or 4.0 development tools as well, but will be prompted to upgrade the project. The SharePoint 2010 source code was developed in Visual Studio 2010 and Silverlight 4.0 development tools. Once you have deployed the feature, you will need to make sure it is activated on the site it has been deployed at. Once the feature has been activated, it can be added as a web part, by default under Custom Controls –> Silverlight Slide Show.

Silverlight / SharePoint Cross Domain Requirements – IMPORTANT!

In order for Silverlight to access SharePoint web services (“Lists.asmx” in this case), you will need to create a file called clientaccesspolicy.xml and save it to the SharePoint wwwroot directory (C:\inetpub\wwwroot\wss\VirtualDirectories\80). You can find a copy of this in the Slide.Show Sample project or use the text below. See References below for more details.

<?xml version="1.0" encoding="utf-8"?>
      <allow-from http-request-headers="*">
        <domain uri="*"/>
        <resource path="/" include-subpaths="true"/>


In order to use the web part, you will first need to create a SharePoint Picture Library where you will be storing your images and/or videos. If you are using SharePoint 2010, you can alternatively create an Asset Library. You can then add images and videos (wmv format) to the library. In order to create albums, you can create folders at the root level. The name of the folder will be the name of the web album respectively. You can also set the Title and Description as these will be used when you mouse over a slide. If you do not provide a Title and Description, the image path will be used. One other minor thing I noticed is that the Title and Description change as soon as the transition starts, so depending on how you set up your Wait Times and Transition durations, it may appear that the these values are wrong. Also, keep in mind that the web part will resize pictures based on the height and width you provide in the web part properties, so it is recommended that you use images of equal size and aspect ratio. In order to configure the web part, open the page in edit mode, click on Modify Shared Web Part from the Web Part Edit drop down.

Supported Formats

Silverlight only accepts JPG and PNG for image formats and WMV for video formats. See MSDN References below for more details.

Web Part Configuration Properties

  • Web – This is used to filter the lists.
  • List – This is the Picture Library that will be used in the slide show.
  • Width – Image / Video width. Pictures and videos will be resized to fit this.
  • Height – Image / video height. Pictures and videos will be resized to fit this.
  • Transition Duration – Time in milliseconds that it takes to transition between slides.
  • Wait Time – Time in milliseconds that the slide stays in one place.
  • Theme – Theme to be used. Dark and Light are the only two themes.
  • Transition Type – These are the types of transitions that can be used between slides.
  • Start In Album View – This indicates whether or not you want the web part to default to album view.


Web Part Properties

Based on the web you pick, the list will be populated with Picture Libraries and/or Asset Libraries.


Screenshots (SharePoint 2010)

Slide Show View
Slide Show View – On Mouse Over
Slide Show View – Mouse Hover


Album View


Source Code

SkyDrive – SharePoint 2008 / SharePoint 2010



CodePlex – Vertigo Slide.Show – Original Source Code for Samples and SlideShow projects. This is a great place for understanding the features and troubleshooting issues.

Building Blocks #1: Silverlight Slideshow Viewer for SharePoint  - Matthew provided the original SPDataProvider class that I borrowed from heavily.

Supported Media Formats, Protocols, and Log Fields – Silverlight compatible video formats

BitMap Image Class – Silverlight compatible image formats

Making a Service Available Across Domain Boundaries – Information on clientaccesspolicy.xml. I also recommend Jesse Liberty and Tim Heuer’s blogs.

WSPBuilder – Visual Studio Extension required by the SharePoint 2007 project.