Sample Visual Studio 2010 project for creating a custom SharePoint 2010 Ribbon tab on runtime (!)

The related articles on my blog are:


I wanted to create a sample project to show you who you can create a custom SharePoint 2010 Ribbon tab at runtime! – Especially: How to active the custom ribbon tab on “page loaded” (no need to click it!) So this article is an addition to my explanations in my previous article “How To Activate SharePoint Ribbon Tab by JavaScript Code”.

You can download the project from Codeplex:

http://spcustomribbondemo.codeplex.com

You are invited to download / update / improve the project! – I’d like to insert more samples in the project about how to deploy Ribbon customizations. In the sample I created a ribbon in a custom list view web page. (You’ll see in the code).

To use the project you need a SharePoint web application named “http://sharepoint.local” and a site collection named “ribbon”.

Deploy the project.

Open the SharePoint site and it’s list in your browser.

image

You’ll see:

image

This tab is actived automatically on page load!!!

The source code of my project is inspired by some blog post of this people:

These are the steps of development I’ve done:

1. Create an empty SharePoint 2010 project in Visual Studio 2010

2. Create an “List Definition” project item.

3. Add a “Application Page” project item.

4. Move the new application page to the “List Definition” project item.

5. Change the base class to “WebPartPage”

6. Modify the “Page” tag of the aspx page: replace “DynamicalMasterPageFile” with “MasterPageFile”

7. Replace the content of the aspx file with this code:

 

1: <asp:Content  ContentPlaceHolderID="PlaceHolderAdditionalPageHead"  runat="server"> 

2: </asp:Content> 

3:

4: <asp:Content  ContentPlaceHolderID="PlaceHolderMain"  runat="server"> 

5:     <WebPartPages:WebPartZone  runat="server"  FrameType="None"  ID="Main2"  Title="loc:Main"> 

6:         <ZoneTemplate> 

7:         </ZoneTemplate> 

8:     </WebPartPages:WebPartZone> 

9: </asp:Content> 

10: <asp:Content  ContentPlaceHolderID="PlaceHolderPageTitle"  runat="server"> 

11: </asp:Content> 

12: <asp:Content  ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea"  runat="server"> 

13: </asp:Content>

14:

8. Insert the following code into the CS file of the ASPX file. This code will create the custom Ribbon tab. (The Ribbon tab XML definition code could be created dynamically!!!)

 

1: using  System;

2: using  System.Security.Permissions;

3: using  Microsoft.SharePoint.Security;

4: using  Microsoft.SharePoint.WebPartPages;

5: using  Microsoft.SharePoint;

6: using  Microsoft.SharePoint.WebControls;

7: using  System.Web.UI.WebControls.WebParts;

8: using  System.Diagnostics;

9: using  System.Xml;

10: using  System.Collections.Generic;

11: using  System.Reflection;

12: using  System.Text;

13:

14: namespace  ik.SharePoint2010.SPCustomTabRibbonDemo.Layouts.SPCustomTabRibbonDemo

15: {

16:     public  partial  class  AllItems  : WebPartPage 

17:     {

18:         protected  void  Page_Load(object  sender, EventArgs  e)

19:         {

20:         }

21:

22:         private  string  tab = @" 

23:           <Tab Id=""ik.SharePoint2010.Ribbon.CustomTab"" Title=""ik-ribbon"" Description=""Ingo's Command Group"" Sequence=""501""> 

24:             <Scaling Id=""ik.SharePoint2010.Ribbon.CustomTab.Scaling""> 

25:               <MaxSize Id=""ik.SharePoint2010.Ribbon.CustomTab.Group1.MaxSize"" 

26:                        GroupId=""ik.SharePoint2010.Ribbon.CustomTab.Group1"" 

27:                        Size=""OneLarge""/> 

28:               <Scale Id=""ik.SharePoint2010.Ribbon.CustomTab.Group1.Scaling.CustomTabScaling"" 

29:                      GroupId=""ik.SharePoint2010.Ribbon.CustomTab.Group1"" 

30:                      Size=""OneLarge""/> 

31:               <MaxSize Id=""ik.SharePoint2010.Ribbon.CustomTab.Group2.MaxSize"" 

32:                        GroupId=""ik.SharePoint2010.Ribbon.CustomTab.Group2"" 

33:                        Size=""OneLarge""/> 

34:               <Scale Id=""ik.SharePoint2010.Ribbon.CustomTab.Group2.Scaling.CustomTabScaling"" 

35:                      GroupId=""ik.SharePoint2010.Ribbon.CustomTab.Group2"" 

36:                      Size=""OneLarge""/> 

37:               <MaxSize Id=""ik.SharePoint2010.Ribbon.CustomTab.Group3.MaxSize"" 

38:                        GroupId=""ik.SharePoint2010.Ribbon.CustomTab.Group3"" 

39:                        Size=""OneLarge""/> 

40:               <Scale Id=""ik.SharePoint2010.Ribbon.CustomTab.Group3.Scaling.CustomTabScaling"" 

41:                      GroupId=""ik.SharePoint2010.Ribbon.CustomTab.Group3"" 

42:                      Size=""OneLarge""/> 

43:             </Scaling> 

44:             <Groups Id=""ik.SharePoint2010.Ribbon.CustomTab.Groups""> 

45:               <Group Id=""ik.SharePoint2010.Ribbon.CustomTab.Group1"" 

46:                      Description=""Ingo's Custom Ribbon Demo 1"" 

47:                      Title=""Ingo's Custom Ribbon Demo 1"" 

48:                      Sequence=""10"" 

49:                      Template=""ik.SharePoint2010.Ribbon.Templates.OneLarge""> 

50:                 <Controls Id=""ik.SharePoint2010.Ribbon.CustomTab.Group1.Controls""> 

51:                   <Button Id=""ik.SharePoint2010.Ribbon.CustomTab.Group1.Button1"" 

52:                           Command=""ik.SharePoint2010.Command.Button1"" 

53:                           Description=""Do something"" 

54:                           Sequence=""10"" 

55:                           LabelText=""Do something"" 

56:                           Image16by16=""/_layouts/images/DOC16.GIF"" 

57:                           Image32by32=""/_layouts/images/DOC32.GIF"" 

58:                           TemplateAlias=""cust1""/> 

59:                 </Controls> 

60:               </Group> 

61:               <Group Id=""ik.SharePoint2010.Ribbon.CustomTab.Group3"" 

62:                      Description=""Ingo's Custom Ribbon Demo 3"" 

63:                      Title=""Ingo's Custom Ribbon Demo 3"" 

64:                      Sequence=""30"" 

65:                      Template=""ik.SharePoint2010.Ribbon.Templates.OneLarge""> 

66:                 <Controls Id=""ik.SharePoint2010.Ribbon.CustomTab.Group3.Controls""> 

67:                   <Button Id=""ik.SharePoint2010.Ribbon.CustomTab.Group3.Button3"" 

68:                           Command=""ik.SharePoint2010.Command.Button3"" 

69:                           Description=""Do more"" 

70:                           Sequence=""10"" 

71:                           LabelText=""Do more"" 

72:                           Image32by32=""/_layouts/images/PPEOPLE.GIF"" 

73:                           TemplateAlias=""cust1""/> 

74:                 </Controls> 

75:               </Group> 

76:               <Group Id=""ik.SharePoint2010.Ribbon.CustomTab.Group2"" 

77:                      Description=""Ingo's Custom Ribbon Demo 2"" 

78:                      Title=""Ingo's Custom Ribbon Demo 2"" 

79:                      Sequence=""20"" 

80:                      Template=""ik.SharePoint2010.Ribbon.Templates.OneLarge""> 

81:                 <Controls Id=""ik.SharePoint2010.Ribbon.CustomTab.Group2.Controls""> 

82:                   <Button Id=""ik.SharePoint2010.Ribbon.CustomTab.Group2.Button2"" 

83:                           Command=""ik.SharePoint2010.Command.Button2"" 

84:                           Description=""Do nothing"" 

85:                           Sequence=""10"" 

86:                           LabelText=""Do nothing"" 

87:                           Image32by32=""/_layouts/images/PPEOPLE.GIF"" 

88:                           TemplateAlias=""cust1""/> 

89:                 </Controls> 

90:               </Group> 

91:             </Groups> 

92:           </Tab> 

93:

94: " ;

95:         private  string  tabTempl = @" 

96:           <GroupTemplate Id=""ik.SharePoint2010.Ribbon.Templates.OneLarge""> 

97:             <Layout Title=""OneLarge"" LayoutTitle=""OneLarge""> 

98:               <Section Alignment=""Top"" Type=""OneRow""> 

99:                 <Row> 

100:                   <ControlRef DisplayMode=""Large"" TemplateAlias=""cust1"" /> 

101:                 </Row> 

102:               </Section> 

103:             </Layout> 

104:           </GroupTemplate> 

105: " ;

106:

107:         protected  override  void  OnPreRender(EventArgs  e)

108:         {

109:             //Debugger.Break(); 

110:             SPRibbon  r = Microsoft.SharePoint.WebControls.SPRibbon .GetCurrent(this .Page);

111:             XmlDocument  rx = new  XmlDocument ();

112:             rx.LoadXml(tab);

113:             r.RegisterDataExtension(rx.FirstChild, "Ribbon.Tabs._children" );

114:             rx.LoadXml(tabTempl);

115:             r.RegisterDataExtension(rx.FirstChild, "Ribbon.Templates._children" );

116:

117:             List <IRibbonCommand > commands = new  List <IRibbonCommand >();

118:             commands.Add(new  SPRibbonCommand ("ik.SharePoint2010.Command.Button1" , "ikSharePoint2010CommandButton1Action()" , "true" ));

119:             commands.Add(new  SPRibbonCommand ("ik.SharePoint2010.Command.Button2" , "ikSharePoint2010CommandButton2Action()" , "ikSharePoint2010CommandButton2Enable()" ));

120:             commands.Add(new  SPRibbonCommand ("ik.SharePoint2010.Command.Button3" , "ikSharePoint2010CommandButton3Action()" , "ikSharePoint2010CommandButton3Enable()" ));

121:

122:             SPRibbonScriptManager  rsm = new  SPRibbonScriptManager ();

123:

124:             ScriptLink .RegisterScriptAfterUI(this .Page, "SP.Runtime.js" , false , true );

125:             ScriptLink .RegisterScriptAfterUI(this .Page, "SP.js" , false , true );

126:             ScriptLink .RegisterScriptAfterUI(this .Page, "CUI.js" , false , true );

127:             ScriptLink .RegisterScriptAfterUI(this .Page, "SP.Ribbon.js" , false , true );

128:             ScriptLink .RegisterScriptAfterUI(this .Page, "ik.SharePoint2010.SPCustomTabRibbonDemo/ikactions.js" , false , true );

129:             ScriptLink .RegisterScriptAfterUI(this .Page, "ik.SharePoint2010.SPCustomTabRibbonDemo/ikribbon.UI.js" , false , true );

130:

131:             rsm.RegisterGetCommandsFunction(this .Page, "getGlobalCommands" , commands);

132:             rsm.RegisterCommandEnabledFunction(this .Page, "commandEnabled" , commands);

133:             rsm.RegisterHandleCommandFunction(this .Page, "handleCommand" , commands);

134:

135:             string  script = @" 

136:                 <script language=""javascript"" defer=""true""> 

137:                 //<![CDATA[ 

138:                    function ikribbonInit1() {  

139:                      ikribbonInit(); 

140:                    } 

141:                    ExecuteOrDelayUntilScriptLoaded(ikribbonInit1,'); 

142:                 //]]> 

143:                 </script>" ;

144:             ClientScript.RegisterClientScriptBlock(this .GetType(), "InitPageComponent" , script);

145:

146:             r.MakeTabAvailable("ik.SharePoint2010.Ribbon.CustomTab" );

147:             r.SetInitialTabId("ik.SharePoint2010.Ribbon.CustomTab" , "" );

148:             base .OnPreRender(e);

149:         }

150:

151:         protected  override  void  OnInitComplete(EventArgs  e)

152:         {

153:             base .OnInitComplete(e);

154:         }

155:     }

156: }

157:

158:

9. You need two JavaScript files in the project’s sub folder in the SharePoint’s hive folder “Layouts”.

This file contains code for the Ribbon:

 

1: function  ULS_SP() {

2:     if  (ULS_SP.caller) {

3:         ULS_SP.caller.ULSTeamName = "Windows SharePoint Services 4" ;

4:         ULS_SP.caller.ULSFileName = "ikribbon.UI.js" ;

5:     }

6: }

7:

8: Type.registerNamespace(< span> );

9:

10: //  Page Component 

11: ikribbon.UI.PageComponent = function  () {

12:     ULS_SP();

13:     ikribbon.UI.PageComponent.initializeBase(this );

14: }

15: ikribbon.UI.PageComponent.initialize = function  () {

16:     ULS_SP();

17:     ExecuteOrDelayUntilScriptLoaded(Function.createDelegate(null , ikribbon.UI.PageComponent.initializePageComponent), < span> );

18: }

19: ikribbon.UI.PageComponent.initializePageComponent = function  () {

20:     ULS_SP();

21:     var  ribbonPageManager = SP.Ribbon.PageManager.get_instance();

22:     if  (null  !== ribbonPageManager) {

23:         ribbonPageManager.addPageComponent(ikribbon.UI.PageComponent.instance);

24:         ribbonPageManager.get_focusManager().requestFocusForComponent(ikribbon.UI.PageComponent.instance);

25:     }

26: }

27: ikribbon.UI.PageComponent.refreshRibbonStatus = function  () {

28:     SP.Ribbon.PageManager.get_instance().get_commandDispatcher().executeCommand(Commands.CommandIds.ApplicationStateChanged, null );

29: }

30: ikribbon.UI.PageComponent.prototype = {

31:     getFocusedCommands: function  () {

32:         ULS_SP();

33:         return  [];

34:     },

35:     getGlobalCommands: function  () {

36:         ULS_SP();

37:         return  getGlobalCommands();

38:     },

39:     isFocusable: function  () {

40:         ULS_SP();

41:         return  true ;

42:     },

43:     receiveFocus: function  () {

44:         ULS_SP();

45:         return  true ;

46:     },

47:     yieldFocus: function  () {

48:         ULS_SP();

49:         return  true ;

50:     },

51:     canHandleCommand: function  (commandId) {

52:         ULS_SP();

53:         return  commandEnabled(commandId);

54:     },

55:     handleCommand: function  (commandId, properties, sequence) {

56:         ULS_SP();

57:         return  handleCommand(commandId, properties, sequence);

58:     }

59: }

60:

61: var  ikribbonActiveInterval = null ;

62:

63: function  ikribbonActiveRibbonTab() {

64:     try  {

65:         window.clearInterval(ikribbonActiveInterval);

66:

67:         if  (typeof  (_ribbonStartInit) == "function" ) {

68:             _ribbonStartInit(< span> , false , null );

69:         }

70:

71:         if  (true  && typeof  (_ribbonReadyForInit) == < span>  && !_ribbonReadyForInit()) {

72:             ikribbonActiveInterval = window.setInterval("ikribbonActiveRibbonTab()" , 100);

73:         }

74:     } catch  (e2) {

75:     };

76: };

77:

78: function  ikribbonInit() {

79:     alert(< span> );

80:     ikribbon.UI.PageComponent.registerClass(< span> , CUI.Page.PageComponent);

81:     ikribbon.UI.PageComponent.instance = new  ikribbon.UI.PageComponent();

82:     ikribbon.UI.PageComponent.initialize();

83:

84:     ExecuteOrDelayUntilScriptLoaded(ikribbonActiveRibbonTab, < span> );

85: }

86:

87: NotifyScriptLoadedAndExecuteWaitingJobs("ikribbon.UI.js" );

88:

89:

90:

91:

This file contains code for the actions executed on clicking the custom Ribbon buttons:

 

1: function  ikSharePoint2010CommandButton1Action() {

2:     alert("Button 1 pressed" );

3: }

4:

5: function  ikSharePoint2010CommandButton1Enable() {

6:     return  true ;

7: }

8:

9: function  ikSharePoint2010CommandButton2Action() {

10:     alert("Button 2 pressed" );

11: }

12:

13: function  ikSharePoint2010CommandButton2Enable() {

14:     return  true ;

15: }

16:

17: function  ikSharePoint2010CommandButton3Action() {

18:     alert("Button 3 pressed" );

19: }

20:

21: function  ikSharePoint2010CommandButton3Enable() {

22:     return  true ;

23: }

24:

25:

10. Modify the list definitions “schema.xml” file: Edit the following line:

<View BaseViewID=”1″ Type=”HTML” WebPartZoneID=”Main2″ DisplayName=”$Resources:core,objectiv_schema_mwsidcamlidC24;”

DefaultView=”TRUE” MobileView=”TRUE” MobileDefaultView=”TRUE” ImageUrl=”/_layouts/images/generic.png” Url=”AllItems.aspx”>

Remove the SetupPath attribute!

11. Set the view pages “DeploymentType” property to “NoDeployment”:

image

12. That’s all Hot smile

How to upload user profile pictures in SharePoint 2010 using PowerShell

I’ve created a script for uploading user pictures to the SharePoint 2010 User Profile system.

For me it worked very well. But: Use it at your own risk!

Here is the script:

#written by ingo karstein
#region Check x64 host
    if( [System.IntPtr]::Size -ne 8) {
      Write-Error "Please use a x64 PowerShell host!"
      return
    }
#endregion

#region Load SharePoint SnapIn and DLL
  Remove-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
  Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

  [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")  | out-null
  Add-Type -AssemblyName System.DirectoryServices
  Add-Type -AssemblyName System.DirectoryServices.AccountManagement 

  #Check available SharePoint Cmdlets
  if( (Get-Command -Noun SPWeb*) -eq $null ) {
    Write-Error "SharePoint SnapIn not loaded. SharePoint cmdlets missing!"
    return
  }
#endregion

cls

#region Config Section
    $dom = "sharepoint.local"
    $dom2 = "dc=sharepoint, dc=local"
    $ad = @("ou=Users,dc=sharepoint,dc=local",
            "ou=Users2,dc=sharepoint,dc=local")
    $ldapFilter = "(&(objectcategory=user))"
    $testuser = $null
    #for testing purpose uncomment the following line and add the sAMAccountName of the test user
    #$testuser="ikarstein"

    #the web application url of the profile system
    $personalSiteHost="http://sharepoint.farm/mysitehost"
    #the intranet/homepage web application url
    $intranetSiteHost="http://sharepoint.farm"

    #the path to the user profile pictures. the files must be named like the sAMAccountName and with extension .jpg
    #  example: ikarstein.jpg
    $imagePath="\servershareuser_pictures"
#endregion

$ErrorActionPreference = "Stop"

#This function reads name of the folder where the pictures will be stored
function GetProfilePicturesFolderName {
  try {
    $a = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Portal")
    $name = $a.GetName()
    $assemblyRef = new-object System.Reflection.AssemblyName
    $assemblyRef.Name = "Microsoft.Office.Server.intl"
    $assemblyRef.Version = $name.Version
    $assemblyRef.SetPublicKey($name.GetPublicKey())
    $assemblyRef.CultureInfo = [System.Globalization.CultureInfo]::InvariantCulture
    $assembly = [System.Reflection.Assembly]::Load($assemblyRef)
    $s_rmLocStrings = new-object System.Resources.ResourceManager ("Microsoft.Office.Server.Strings", $assembly)
    $s_rmLocStrings.GetString("UserProfile_UploadPicture_FolderName")
  } catch {
    $null
  }
}

#This function reads name of the SharePoint list where the pictures will be stored
function GetProfilePicturesListName {
  try {
    $a = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Portal")
    $name = $a.GetName()
    $assemblyRef = new-object System.Reflection.AssemblyName
    $assemblyRef.Name = "Microsoft.Office.Server.intl"
    $assemblyRef.Version = $name.Version
    $assemblyRef.SetPublicKey($name.GetPublicKey())
    $assemblyRef.CultureInfo = [System.Globalization.CultureInfo]::InvariantCulture
    $assembly = [System.Reflection.Assembly]::Load($assemblyRef)
    $s_rmLocStrings = new-object System.Resources.ResourceManager ("Microsoft.Office.Server.Strings", $assembly)
    $s_rmLocStrings.GetString("MyPage_MyLists_ProfilePicture_Text")
  } catch {
    $null
  }
}

#This function returns the object for the profile picture list
function GetProfilePicturesList {
  try {
    $profilePicturesListName = GetProfilePicturesListName
    $profileWeb.Lists | ? { $_.get_BaseTemplate() -eq 0x6d -and $_.get_Title() -ieq $profilePicturesListName }
  } catch {
    $null
  }
}

#This function removes special characters from the file name  
function ConvertToLegalFileName($inputName, $replacementChar) {
    $l = $inputName.Length;
    $builder = New-Object System.Text.StringBuilder($inputName)
    for ($i = 0; $i -lt $l; $i++) {
        if ([Microsoft.SharePoint.Utilities.SPUrlUtility]::IsLegalCharInUrl($inputName[$i]) -ne $true)
        {
            $builder.set_chars($i, $replacementChar)
        }
    }
    return $builder.ToString()
}

#This function returns the sub folder for pictures in the picture list
function GetSubfolderForPictures {
  $folderName = GetProfilePicturesFolderName
  try {
      $subfolder = $profilePicturesList.get_RootFolder().Get_SubFolders().get_Item($folderName)
      if( $subfolder -eq $null ) {
        $subfolder = $profilePicturesList.get_RootFolder()
      }
  } catch {
    try {
        $subfolder = $profilePicturesList.get_RootFolder().get_SubFolders().Add($folderName)
    } catch {
        $subfolder = $null
    }
  }
  return $subfolder
}

#this function returns *multiple* objects:
# 1. the MethodInfo object for "CreateThumbnail"
# 2. the size of the large thumbnal picture
# 3. the size of the medium thumbnail picture
# 4. the size of the small thumbnail picture
function InitializeUserProfilePhotosType {
    $a = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles")
    $userPofilePhotosType = $a.GetType("Microsoft.Office.Server.UserProfiles.UserProfilePhotos")

    #outputs:
    $userPofilePhotosType.GetMethod("CreateThumbnail", [System.Reflection.BindingFlags]([System.Reflection.BindingFlags]::Static -bor  [System.Reflection.BindingFlags]::NonPublic))
    $userPofilePhotosType.InvokeMember("LargeThumbnailSize", [System.Reflection.BindingFlags]([System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::GetProperty  ), $null, $null, @() )
    $userPofilePhotosType.InvokeMember("MediumThumbnailSize", [System.Reflection.BindingFlags]([System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::GetProperty  ), $null, $null, @() )
    $userPofilePhotosType.InvokeMember("SmallThumbnailSize", [System.Reflection.BindingFlags]([System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::GetProperty  ), $null, $null, @() )
}

#this function returns a MethodInfo object for "EnsureTrailingSlash" method
function InitializePersonalSpaceGlobalType {
    $a = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles")
    $personalSpaceGlobalType = $a.GetType("Microsoft.Office.Server.WebControls.UserProfileHelper.PersonalSpaceGlobal")

    #outputs:
    $personalSpaceGlobalType.GetMethod("EnsureTrailingSlash", [System.Reflection.BindingFlags]([System.Reflection.BindingFlags]::Static -bor  [System.Reflection.BindingFlags]::NonPublic))
}

#thid function returns a MethodInfo object for "GetSmallThumbnailUrl" method
function InitializeUserProfileGlobalType {
    $a = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles")
    $userProfileGlobalType = $a.GetType("Microsoft.Office.Server.UserProfiles.UserProfileGlobal")

    #outputs:
    $userProfileGlobalType.GetMethod("GetSmallThumbnailUrl", [System.Reflection.BindingFlags]([System.Reflection.BindingFlags]::Static -bor  [System.Reflection.BindingFlags]::NonPublic))
}

#this function creates an absolute url for the given relative url
function MakeFullUrl {
  param($url)
  return "$($temp)$($Url)"
}

#this function reads the users from the Active Directory
function GetUsers {
    $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Domain
    $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $dom, $dom2

    $l = @()

    $ad | % { $domain = [ADSI]("LDAP://"+$_)
              $filter = $ldapFilter
              $ds = new-object System.DirectoryServices.DirectorySearcher($domain,$filter)
              $users = $ds.Findall()
              $users | % { $l = $l + $_ }
        }

    $identityParam = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName

    $m = @()

    if( $testuser -ne $null ) {
      Write-Host "Test mode!" -ForegroundColor Red
    }

    $l | % {
      $san = $_.properties["samaccountname"]
      if( $testuser -eq $null -or $testuser -ieq $san) {
        $m = $m + $san[0]
      }
    }

    #output:
    $m
}

$profileSite = (Get-SPSite $personalSiteHost)
$profileWeb = $profileSite.RootWeb

$site=(Get-SPSite $intranetSiteHost)
$sc = [Microsoft.Office.Server.ServerContext]::GetContext($site)

$upm = New-Object "Microsoft.Office.Server.UserProfiles.UserProfileManager" -ArgumentList ($sc)
$mysiteHostUrl = $upm.MySiteHostUrl

$ensureTrailingSlashMethod = (InitializePersonalSpaceGlobalType)
$mysiteHostUrl = $ensureTrailingSlashMethod.Invoke($null, @(, $mysiteHostUrl))

$createThumbnailMethod, $largeThumbnailSize, $mediumThumbnailSize, $smallThumbnailSize = (InitializeUserProfilePhotosType)
$getSmallThumbnailUrlMethod = (InitializeUserProfileGlobalType)

$profilePicturesList = GetProfilePicturesList
$profilePicturesFolder = GetSubfolderForPictures

$users=(GetUsers)

$users | % {
  $currentUser = $_
  Write-Host "Processing user $($currentUser)"
  $up=$null
  try {
    $up = $upm.GetUserProfile($currentUser)
  } catch {
    #this exception handler may be called for "renamend" users: In the AD the account name was changed but not in the SharePoint User Profil system
    $e=$upm.GetEnumerator()
    $e.reset()
    while( $e.movenext() ) {
      $u = $e.current
      if( $u["UserName"] -ieq $currentUser ) {
        $up = $u
        break
      }
    }
  }

  if( $up -ne $null ) {
    Write-Host "  User found in profile store"
    $picture = [byte[]](Get-Content -path "$($imagePath)$($currentUser).jpg" -Encoding Byte -ErrorAction SilentlyContinue)
    if( $picture -ne $null ) {
        Write-Host "  User picture found: ""$($imagePath)$($currentUser).jpg"""

        $dstFileName = (ConvertToLegalFileName $up["AccountName"].Value.ToString() "_")

        $flag = $profileWeb.get_AllowUnsafeUpdates()
        try
        {
          $profileWeb.set_AllowUnsafeUpdates($true)

          try
          {
            $stream = $bitmap = $ps = $null

            try {
              $stream = New-Object System.IO.MemoryStream @(, $picture)
              if( $stream -ne $null ) {
                  $bitmap = New-Object System.Drawing.Bitmap ($stream, $true)
                  if( $bitmap -ne $null ) {
                     Write-Host "  starting photo creation..."
                     $p = ([System.Drawing.Bitmap]$bitmap, $largeThumbnailSize, $largeThumbnailSize, [Microsoft.SharePoint.SPFolder]$profilePicturesFolder, "$($dstFileName)_LThumb.jpg")
                     $file = $createThumbnailMethod.Invoke($null, $p )
                     Write-Host "    large thumnail created..."
                     $p = ([System.Drawing.Bitmap]$bitmap, $smallThumbnailSize, $smallThumbnailSize, [Microsoft.SharePoint.SPFolder]$profilePicturesFolder, "$($dstFileName)_SThumb.jpg")
                     $file = $createThumbnailMethod.Invoke($null, $p )
                     Write-Host "    small thumnail created..."
                     $p = ([System.Drawing.Bitmap]$bitmap, $mediumThumbnailSize, $mediumThumbnailSize, [Microsoft.SharePoint.SPFolder]$profilePicturesFolder, "$($dstFileName)_MThumb.jpg")
                     $file = $createThumbnailMethod.Invoke($null, $p )
                     Write-Host "    medium thumnail created..."

                     $mediumUrl = $profileSite.MakeFullUrl( (MakeFullUrl $file.get_Url()) )

                     $smallThumbUrl = $getSmallThumbnailUrlMethod.Invoke($null, ([string]$mediumUrl))

                     [Microsoft.SharePoint.SPSecurity]::RunWithElevatedPrivileges( {
                         $ps = $up.PersonalSite
                         if( $ps -ne $null ) {
                             $ps.get_RootWeb().set_SiteLogoUrl($smallThumbUrl)
                             $ps.get_RootWeb().Update()
                         }

                         $up["PictureURL"].Value = $mediumUrl
                         $up.Commit()
                     } );
                  }
              }
            } catch {
              Write-Host "    error occured!"
              Write-Error $Error[0]
            } finally {
              if( $bitmap -ne $null ) {
                $bitmap.dispose()
              }
              if( $stream -ne $null ) {
                $stream.close()
                $stream.dispose()
              }
            }
          } catch {
          }
        } finally{
          $profileWeb.set_AllowUnsafeUpdates($flag)
        }
    } else {
      Write-Host "  Users picture not found" -ForegroundColor Red
    }
  } else {
    Write-Host "  User not found in profile store" -ForegroundColor Red
  }
}

How to have a look behind the data source of the XsltListViewWebPart of SharePoint 2010

I want to create a custom field type in a SharePoint 2010 development project (which I want to publish as as “walkthrough” on this blog Smile )

Therefore I need to inspect the source XML data that is used for XSLT rendering on a lists view page, e.g. “AllItems.aspx”

This is the result:

image

You see here for each field (column): The source XML and the items field value behind the XML data.

For the demo above I created a new custom list. It has some fields:

  • Title : Single line of text
  • Choice Field : Choice field with 3 choice values
  • Date Field : Date only field
  • Lookup Field: Lookup field to the “Start Time” field of the standard Team Site “Calendar” list. (Additional field in view: “End Time”)
  • People Picker Field: People or Group field with “People only”.

I added a single item.

That’s the set.

For the lookup field you get this result XML data:

<FieldRef Name="Lookup_x0020_Field" Type="Lookup" FieldType="Lookup" Encoded="TRUE" DisplayName="Lookup Field" ID="da1fb516-3300-47e9-8734-33db5479876e" />

For the “Title” field you get this result XML data:

<FieldRef Name="LinkTitle" ListItemMenu="TRUE" Type="Computed" FieldType="Computed" DisplayName="Title" ID="82642ec8-ef9b-478f-acf9-31f7d45fbc31" ClassInfo="Menu" ListItemMenuAllowed="Required" LinkToItemAllowed="Prohibited" />Test Text

(This field is “Computed”. In the view you do not see the “Title” field itself. You see a “computed” field named “LinkTitle” instead.)

If I want to develop a custom field type I need to create a XSL transformation for the field data. Therefore I need to refer to the source XML data. But at development time I do not know the exact structure and content of the XML data. So I modified a file in the SharePoint hive….

NEVER do the following in a productive SharePoint 2010 farm! 

1. Look for the file “C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions14TEMPLATELAYOUTSXSLfldtypes.xsl”

2. Open it.

3. Look for this line:

  <xsl:template name="PrintField" ddwrt:dvt_mode="body" ddwrt:ghost="always">

4. Before this line insert this XSLT code:

1:   <xsl:template name= "ikarstein_nodes "> 
2:     <xsl:element name= "{name()} "> 
3:       <xsl:text><![CDATA[<]]></xsl:text> 
4:       <xsl:value-of select= "name() "/> 
5:       <xsl:text><![CDATA[ ]]></xsl:text> 
6:       <xsl:for-each select= "@* "> 
7:         <xsl:call-template name= "ikarstein_attrib "/> 
8:       </xsl:for-each> 
9:       <xsl:choose> 
10:         <xsl:when test= "count(child::*)>0 "> 
11:           <xsl:text><![CDATA[>]]></xsl:text> 
12:           <xsl:for-each select= "child::*"> 
13:             <xsl:call-template name= "ikarstein_nodes "/> 
14:           </xsl:for-each> 
15:           <xsl:text><![CDATA[</]]></xsl:text> 
16:           <xsl:value-of select= "name() "/> 
17:           <xsl:text><![CDATA[>]]></xsl:text> 
18:         </xsl:when> 
19:         <xsl:otherwise> 
20:           <xsl:choose> 
21:             <xsl:when test= "string-length(text()) != 0 "> 
22:               <xsl:text><![CDATA[>]]></xsl:text> 
23:               <xsl:value-of select= "text() "/> 
24:               <xsl:text><![CDATA[</]]></xsl:text> 
25:               <xsl:value-of select= "name() "/> 
26:               <xsl:text><![CDATA[>]]></xsl:text> 
27:             </xsl:when> 
28:             <xsl:otherwise> 
29:               <xsl:text><![CDATA[/>]]></xsl:text> 
30:             </xsl:otherwise> 
31:           </xsl:choose> 
32:         </xsl:otherwise> 
33:       </xsl:choose> 
34:     </xsl:element> 
35:   </xsl:template> 
36:   <xsl:template name= "ikarstein_attrib "> 
37:     <xsl:value-of select= "name() "/> 
38:     <xsl:text><![CDATA[="]]></xsl:text> 
39:     <xsl:value-of select= ". "/> 
40:     <xsl:text><![CDATA[" ]]></xsl:text> 
41:   </xsl:template>	 

5. Then you have to modify the node starting with “<xsl:template name="PrintField" ddwrt:dvt_mode="body" ddwrt:ghost="always">”.  Insert the highlighted line of the snipped below:

   <xsl:template name= "PrintField " ddwrt:dvt_mode= "body " ddwrt:ghost= "always "> 
     <xsl:param name= "thisNode " select= ". "/> 
     <xsl:param name= "Position " select= "1 " /> 
     <xsl:param name= "Type " select= "string(@Type) "/> 
     <xsl:param name= "Name " select= "string(@Name) "/> 
     <xsl:param name= "folderUrlAdditionalQueryString "/> 
     <xsl:call-template name= "ikarstein_nodes "/> 
     <xsl:choose> 
       <xsl:when test= "< span> "> 
         <xsl:apply-templates select= ". " mode= "DateTime_body "> 
           <xsl:with-param name= "thisNode " select= "$thisNode "/> 

6. Restart the IIS.

7. Reload the list view. – Now you’ll see the fields source XML data.