Category Archives: SharePoint 2007

User Profiles in a Silverlight PivotViewer

After seeing the PivotViewer used for Cricket World Cup and SharePoint sites, I thought it would be great way of viewing user profiles in SharePoint. As always, I had a great idea without the time or in depth technical knowledge of PivotViewer, in this case, to implement it until now.

My aim was to great a Pivot View that could be updated daily or weekly for users to see people information in a graphical form that can be used for both identifying groups of individuals with similar characteristics such as location and/or skills as well as being able to display in histograms the number of people that fitted in the selected filters i.e. how many people in each department.

Here’s the result with how I did it to follow:

Zooming in on an individual shows the picture in full and the profile properties I mapped.

The process involves creating the image collection and xml definitions that the Pivot Viewer uses to display the content and filtering, sorting and grouping controls.

For my first run, I’m keeping it simple and just including the person’s Name, description (About Me), department and link to My Site. This meant I could focus on the solution rather than working out how to get each property and format it.

To start with I need to get an export of the User Profile pictures (presuming this is the main source, you may have another), onto the file system. As I intend to automate the build of these files to support scheduling, I also needed to use the command line tools to generate the deep zoom images. I decided to use powershell, as it’s my new best friend and quick to prototype.

In my first run, I created one powershell file to export the images and CXML file but discovered that the CXML must reference the correct image ID created by the command line tool DZCollection.exe so I split the file in two. The process is now as follows:

  1. Use Powershell to export images – Get Enumerator over the UserProfileManager
  2. Export each profile image if exists to the file system
  3. Execute the command line tools to generate the deep zoom images and collections
  4. Use Power Shell to export properties – Enumerator again over the profiles looking up the image ID from the XML file created in step 3
  5. Create the CXML file using a template

Powershell script for exporting images:

$ver = $host | select version

if ($ver.Version.Major -gt 1) {$Host.Runspace.ThreadOptions = “ReuseThread”}

Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

Set-location $home

Start-SPAssignment -Global

$LocalPath = “C:\Development\UserProfilePivot\ProfilePictures”

$MySiteUrl = “http://intranet.contoso.com/my/”

$site = Get-SPSite $MySiteUrl

$siteWeb = Get-SPWeb –site $site

Write-Host “My Site retrieved:” + $site

$context = Get-SPServiceContext($site)

$pm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)

$AllProfiles = $pm.GetEnumerator()

foreach($profile in $AllProfiles)

{

$photourl = $profile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::PictureUrl].Value

if($photourl){

$personName = $profile.DisplayName

Write-Host “Exporting: ” $personName

#Download file

$photoFile = $siteWeb.GetFile($photourl)

$binary = $photoFile.OpenBinary()

$stream = New-Object System.IO.FileStream($LocalPath + “/” + $personName + “.jpg”), Create

$writer = New-Object System.IO.BinaryWriter($stream)

$writer.write($binary)

$writer.Close()

}

}

Stop-SPAssignment -Global

If you have a large collection of profile properties, I would use the paging function overload of the GetEnumerator to specify the start row and page size

Create the deep zoom images and collection

I create a command line file to this piece that calls the 2 tools available in the SDK:

cd “C:\Program Files (x86)\Microsoft Expression\Deep Zoom Composer\DZSamples”

DZConvert.exe C:\Development\UserProfilePivot\ProfilePictures\*.jpg C:\Development\UserProfilePivot\ProfilePictures\dzimages

DZCollection.exe C:\Development\UserProfilePivot\ProfilePictures\dzimages C:\Development\UserProfilePivot\UserPicturecollection.xml

Export the properties to create the CXML file

To keep it simple, I created the CXML file first by hand (You could use the Excel tool) and then just clone the XML nodes in the power shell (get this tip from here http://powershell.com/cs/blogs/tobias/archive/2009/02/02/xml-part-2-write-add-and-change-xml-data.aspx)

The template looked like this:

<?xml version=”1.0″ encoding=”utf-8″?>

<Collection Name=”User Profiles” SchemaVersion=”1.0″ xmlns=”http://schemas.microsoft.com/collection/metadata/2009&#8243; xmlns:p=”http://schemas.microsoft.com/livelabs/pivot/collection/2009&#8243; xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns:xsd=”http://www.w3.org/2001/XMLSchema”&gt;

<FacetCategories>

<FacetCategory Name=”Department” Type=”String” />

</FacetCategories>

<Items ImgBase=”ProfilePictures/UserPicturecollection.xml”>

<Item Img=”#51″ Id=”51″ Href=”http://intranet.contoso.com&#8221; Name=”Person Name”>

<Description>About Me</Description>

<Facets>

<Facet Name=”Department”>

<String Value=”Executive” />

</Facet>

</Facets>

</Item>

</Items>

</Collection>

Here’s the powershell script that creates that generates the updated file:

$ver = $host | select version

if ($ver.Version.Major -gt 1) {$Host.Runspace.ThreadOptions = “ReuseThread”}

Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

Set-location $home

Start-SPAssignment -Global

$LocalPath = “C:\Development\UserProfilePivot”

$MySiteUrl = “http://intranet.contoso.com/my/&#8221;

$XMLFileLoc= “C:\Development\UserProfilePivot\UserProfilePivot.xml”

$PicCollFileLoc= “C:\Development\UserProfilePivot\UserPicturecollection.xml”

Write-Host “Load existing XML file: ” $XMLFileLoc

$UserProfileXML = New-Object XML

$UserProfileXML.Load($XMLFileLoc)

Write-Host “XML file Loaded”

$cloneItem = @($UserProfileXML.Collection.Items.Item)[0]

Write-Host “Load collection XML file: ” $PicCollFileLoc

$PicCollXML = New-Object XML

$PicCollXML.Load($PicCollFileLoc)

Write-Host “XML file Loaded”

$site = Get-SPSite $MySiteUrl

$siteWeb = Get-SPWeb –site $site

Write-Host “My Site retrieved:” + $site

$context = Get-SPServiceContext($site)

$pm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)

$AllProfiles = $pm.GetEnumerator()

foreach($profile in $AllProfiles)

{

$photourl = $profile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::PictureUrl].Value

if($photourl){

$personName = $profile.DisplayName

$personDept = $profile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::Department].Value

$personAbout = $profile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::AboutMe].Value

$personURL = $profile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::PersonalSpace].Value

Write-Host “Exporting: ” $personName

#Find users image reference in collections file

$ImagePath = “ProfilePictures/dzimages/” + $personName.Replace(” “,”%20”) + “.xml”

$ImageID = $PicCollXML.Collection.Items.I | Where-Object { $_.Source -eq $ImagePath }

if($ImageID){

$ProfileCount = $ImageID.Id

$newperson = $cloneItem.Clone()

$newperson.Img = “#” + $ProfileCount

$newperson.Id = $ProfileCount

if($personURL){

$newperson.Href = “http://intranet.contoso.com&#8221; + $personURL

} else {

$newperson.Href = “http://intranet.contoso.com&#8221;

}

$newperson.Name = $personName

$newperson.Description = $personAbout

#Assume we know the order of the Facets

$FacetDept = @($newperson.Facets.Facet)[0]

$FacetDept.String.Value = $personDept

$UserProfileXML.Collection.Items.AppendChild($newperson) > $null

}

}

}

Write-Host “Save XML file back”

$UserProfileXML.Save($XMLFileLoc)

Stop-SPAssignment –Global

In brief, I open the template CXML file and create a clone of the Item element, I then loop through all the profiles and if they have a picture, find the element in the collection XML file using the Where-Object clause on the Items node. If we find a corresponding image, then get the user properties and start updating the clone node. The Department value was tricky to reference as you need to get the sub element first in this case Facets.Facet[0] rather than just reference through the XML tree. Last of all, remember to append your cloned node and when you’ve reached the last profile, write it all back to file.

Some improvements are needed as follows:

  • Only process users who’s profiles were updated since the routine last ran
  • Add some more facets such as skills, past projects etc
  • Re-use the same CXML file and lookup the users entry by Name and update
  • Enumerate in batches using the overload
  • Include users without an image and create a dummy profile picture instead
  • Bigger images to start with would work better.
  • Remove the Bing search result link as it’s probably irrelevant in a corporate environment
  • My script could always be improved I expect and it may be possible to use FIM to do the export somehow but this works for now

The final step is to upload all the files into a SharePoint document library and a the Silverlight Pivot Viewer control to the page and reference the CXML file. Unfortunately my VM gave me the “Your client does not support opening this list with Windows Explorer” and I gave up trying to fix it.

You can find out more about the Pivot Viewer here along with all the downloadable examples and tools:

http://www.silverlight.net/learn/data-networking/pivot-viewer/pivotviewer-control

As always, use the code as-is.

Leave a comment

Filed under PowerShell, SharePoint 2007, SharePoint 2010, Silverlight, User Profiles

What is really fast in returning results from a list based query ?

What is really fast in returning results from a list based query ?

Is it SPList, SPQuery, w index, w/o index, List Web service, Search or PortalSiteMapProvider ?

I found these really surprising results with test done on very large lists with 100K items: 

PortalSiteMapProvider performs well with indexing and even better without indexing:

 

And also well when using an ID field:

Search comes second as it uses the crawled index but overhead is that have to wait for the crawl interval which is usually 30minutes plus managed properties need to be configured.

Without these considerations:

To load a page with 100 item per page, it takes around 16 seconds.

Deleting just 1  item from a 100K list can take about 1 minute.

The total memory consumption for a list with 2 million items under root will be 4.5 GB.

Leave a comment

Filed under Admin / Config, Fixes / Solutions, SharePoint 2007

Search Administration – Could not connect to server

If you have the query server and index server roles on different servers in the farm and you get the following error showing in the ‘Server Status’ area of the Search Administration page….

Could not connect to server yourservernamehere for application ‘yourSSPnamehere’. This error might occur if the server is not responding to client requests, the firewall or proxy configuration is preventing the server from being contacted, or the search administration Web service is not running on the server.

….it could be because .Net 3.5 SP1 was installed prior to installing SharePoint 2007 SP2.

We encountered this a little while ago at a client site (SharePoint 2007 – including October 2009 cumulative updates – installed on servers running Windows Server 2003) and it turned out to be caused by corruption of the self-issued certificate used by the Office Server Web Services. .
 
Following the steps in this Microsoft support article to create a new self-issued certificate fixed it for us: http://support.microsoft.com/kb/962928
 
The symptoms we were experiencing weren’t exactly as mentioned in the support article however. We could get to the Search Settings page without any problem and while error event ID 6482 was being logged, it certainly wasn’t every minute. And the event description was more along the lines of ‘object not found’ rather than ‘application server administration job failed’. Search results were also being returned successfully. In fact, apart from the error msg on the Search Admin page there was no obvious indication that there was any problem at all.

If you prefer, before jumping in and creating a new certificate you can check to see if the self-issued SSL is working OK by opening a browser on the app/index server and type in the following addresses:
 
http://yourwfename:56737/yourSSPname/Search/SearchAdmin.asmx
https://yourwfename:56738/yourSSPname/Search/SearchAdmin.asmx
 
..substituting in your WFE server name(s) and SSP name as appropriate.
 
Then do the same on the WFE(s) substituting in the app/index server name.
 
If you get to the SearchApplicationWebService page in each case, the servers are talking to each other OK. Otherwise you may have a problem.
 
At the client mentioned above, browsing to both addresses from the app/index server to the WFE worked fine, but the https address didn’t work trying to get from the WFE to the app/index server.

Ian Docking – Senior Technical Consultant

Leave a comment

Filed under Admin / Config, Fixes / Solutions, SharePoint 2007

Replicating SPThemes.XML Changes to Multiple FrontEnds

After being asked to create a new custom SharePoint 2007 Theme on an environment with three front-end servers for an internal project, I soon noticed (post deployment) that the Add/Remove items changes in the SPThemes.xml file performed by the FeatureReciever were not replicated propertly to all of the web front-end servers.  After some investigation I found that within the FeatureReciever code I needed to execute the AddThemeItem/RemoveThemeItem function calls from inside the FeatureInstalled/FeatureUninstalling events rather than the FeatureActivated/FeatureDeactivating events.

This is because in a SharePoint farm with multiple servers, the FeatureActivated/FeatureDeactivating event only gets fired on a single server on the farm!

By putting the AddThemeItem/RemoveThemeItem function calls in the FeatureInstalled/FeatureUninstalling events instead, the code will get fired on every server in the farm.

Quick Example:

public class FeatureReceiver: SPFeatureReceiver {
public override void FeatureActivated(SPFeatureReceiverProperties properties) {
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {
}
public override void FeatureInstalled(SPFeatureReceiverProperties properties) {
AddThemeItem();
}
public override void FeatureUninstalling(SPFeatureReceiverProperties properties) {
RemoveThemeItem();
}
}

Vimal Naran – Senior Developer

1 Comment

Filed under Fixes / Solutions, SharePoint 2007, WSS 3.0

Windows Server 2008 firewall ports on a multi-server SharePoint farm

I ran into this problem a few weeks ago when installing & configuring a customer’s Sharepoint 2007 farm comprising an application/index server and a single web front-end on Windows Server 2008.

I was unable to view or configure the services (Office Sharepoint Search in my case) on the web front-end. Trying to do so via ‘Services on Server’ in Central Admin (Operations tab) resulted in the following error message:

An unhandled exception occurred in the user interface.Exception Information: Could not connect to server xxxxxxxx. This error might occur if the firewall or proxy configuration is preventing the server from being contacted.

A technet article on configuring Windows Firewall with Advanced Security mentioned that all ports used by web applications, including Central Admin, needed to be opened. After finding all of the port numbers as per the article (from the list of web apps in Central Admin) and making sure they were open on both server firewalls we still got the same error message.

We fixed the problem by opening ports 56737 and 56738. These ports are used by Office Server Web Services. You can see this site and its port numbers in IIS Manager but there’s no sign of it in the list of web apps in Central Admin of course.

A lot of posts about Windows firewall configuration mention opening the ports for ‘all of the web apps’ but don’t mention the Office Server Web Services.

Ian Docking – Senior Technical Consultant

Leave a comment

Filed under Admin / Config, Fixes / Solutions, SharePoint 2007