Skip to main content

Thinking out aloud - Dave Hunter's SharePoint Blog

Go Search
Home
Blog
About Me
  

Locations of visitors to this page


 Useful Links

  Microsoft UK events
  SharePoint 2007 on CodePlex
  SharePoint Community Portal
  SharePoint User Group
  SharePoint Community Portal
  SharePoint Pedia
  SharePoint MSDN Forums
  SharePoint University

 Other Blogs

  Andrew Connell
  Angus Logan
  Arpan Shah
  Bill English
  Charles Emes
  Chris Hines
  From the field
  Heather Solomon
  Joel Oleson
  Lawrence Liu
  Mark Harrison
  Martin Kearn
  Microsoft ECM
  Nick Mayhew
  Patrick Tisseghem
  Penny Coventry
  SharePoint Team
  Steffan Gossner
  Todd Bleeker
Home > Thinking out aloud - Dave Hunter's SharePoint Blog
My thoughts and findings on Microsoft Information worker technologies, including MCMS and SharePoint 2007 (MOSS).
Use InfoPath to author XML schemas (XSD)

From guowu

It is very easy to use InfoPath as an XML schema editor:

  1. Choose Design a form… from the File Menu in InfoPath.
  2. In the Design a new form task pane, select New Blank Form. Note, if you want to derive a schema from existing XML document or data connection, choose one of the New from… options and skip to step 4) below.
  3. On the Design Tasks pane, click on Data Source to show the Data Source Pane. Right click on the myFields element, you will see a shortcut menu. Starting there, you can create data source structure that models your need.
  4. Once you are done, go to File menu, Extract form files…, then quit InfoPath. Go to the folder you just saved extracted form files, you should find myschema.xsd is what you want. Note: if you are deriving a schema, the schema you want may not be defined directly inside myschema.xsd, but imported there.
  5. (Optional) Open myschema.xsd in your favorite XML or text editor, remove the my namespace auto-generated by InfoPath or replace it with your desired namespace URI.

An innovative use of InfoPath J

K2 BlackPearl - Update Design Templates

When you upgrade your K2 environment to the latest release (for example 803), you can update a process developed in a previous version by updating the design templates. You can do this by:

  • Please see the note below before continuing.
  • Right clicking on the design surface
  • Select "Update Design Templates" (pictured below).
  • You can then select the top node to update everything or specify particular activities etc to update and then click Finish

K2 BlackPearl - Update Design Templates

Note: What it doesn't tell you is that the process of updating the design templates will lose any server code in the process. Make sure you backup the process before you update the design templates. When the update is complete you will need to copy and paste the server code back in place.

I found this post on K2 Underground confirming this behaviour http://www.k2underground.com/forums/thread/20602.aspx.

Tip - SharePoint 2007 Escaped Column Names

Most developers who have experience of SharePoint will know that when naming columns using the user interface will result in the actual column name will be an escaped version of what the user entered as the column name. The most common replacement is a space is replaced with "_x0020_". For example: A user enters "Published Date". The display name will remain as "Published Date" but the underlying name of the column will be "Published_x0020_Date".

The table below lists some of the commonly replaced characters

Character

Hex Code

Escaped Version

[space]

20

_X0020_

|

7C

_X007C_

-

2D

_X002D_

\

5C

_X005C_

(

28

_X0028_

)

29

_X0029_

'

27

_X0027_

,

2C

_X002C_

!

21

_X0021_

%

25

_X0025_

&

26

_X0026_

?

3F

_X003F_

$

24

_X0024_

£

A3

_X00A3_

"

22

_X0022_

<

3C

_X003C_

>

3E

_X003E_

=

3D

_X003D_

#

23

_X0023_

 

However there is another way, .NET has a method called EncodeName, which is part of the System.Xml namespace. You can use this method to take in a string that needs to be escaped and returns the escaped string based on the input. For example:

 
using System.Xml; 


// encode the column name 
string escapedString = XmlConvert.EncodeName("Published Date"); 

 
// decode the escaped column name  
string normalString = XmlConvert.DecodeName(escapedString); 

For more information about EncodeName please see http://msdn.microsoft.com/en-us/library/system.xml.xmlconvert.encodename.aspx. Also note that there is a DecodeName method that does the reverse.

One way to get around the escaping is to name a column without spaces or special characters, save the changes and then go back into the column and rename with your desired name. The result is that the name specified first is used for the column name and the latter just changes the display name.

Hope this helps

Powershell SharePoint 2007 Backup Script
I’m still not bought on the whole Powershell and SharePoint idea but I’m getting there.  I found this example script that cleans up the old backup files and then performs a full farm backup of MOSS.

When performing backups of SharePoint using Central Administration or STSADM, backup files are created in a specified UNC path.  If you don’t keep an eye on this location and delete/archive old backups this can grow out of control.  Cleaning up backup files isn’t straightforward either, it involes manually editing the spbrtoc.xml file in the backup location and then deleting the backup folders that relate to the backups you removed from the XML file. 
 
This is where Powershell adds value.

# Clean-up (old) backup files created by WSS v3 (STSADM.EXE)
# Created by Marco
# Tested with PowerShell RTM v1.0

# Location of spbrtoc.xml
$spbrtoc = "\\server\backup\Sharepoint\spbrtoc.xml"

# Days of backup that will be remaining after backup cleanup.
$days = 14

# Import the Sharepoint backup report xml file
[xml]$sp = gc $spbrtoc

# Find the old backups in spbrtoc.xml
$old = $sp.SPBackupRestoreHistory.SPHistoryObject | ? { $_.SPStartTime -lt ((get-date).adddays(-$days)) }
if ($old -eq $Null) { write-host "No reports of backups older than $days days found in spbrtoc.xml.`nspbrtoc.xml isn't changed and no files are removed.`n" ; break}

# Delete the old backups from the Sharepoint backup report xml file
$old | % { $sp.SPBackupRestoreHistory.RemoveChild($_) }

# Delete the physical folders in which the old backups were located
$old | % { Remove-Item $_.SPBackupDirectory -Recurse }

# Save the new Sharepoint backup report xml file
$sp.Save($spbrtoc)
Write-host "Backup(s) entries older than $days days are removed from spbrtoc.xml and harddisk."

  • Create a batch file on the SharePoint 2007 server with the following commands:

STSADM –o backup –directory \\server\backup -backupmethod full -quiet
powershell.exe c:\scripts\SPFullFarmBackup.ps1

  • Save the file and add a scheduled job for the batch file.
This script:
  • Queries the spbrtoc.xml file and finds all the backups.
  • Deletes older backups (by the value of days specified in the script – in this case 14 days).
  • Deletes the associated backup files from the UNC path and save the updated spbrtoc.xml.

Thanks for Marco for the backup script http://blog.wauwwie.nl/Lists/Categories/Category.aspx?Name=MOSS%202007%20%2F%20WSS%20v.3

SharePoint 2007 Delving into Articles
You may have read some of my articles in the series of "Delving into".  These articles provide an indepth view on an area in SharePoint 2007.
 
Articles already in this series:

Articles Coming Soon

  • Delving into SharePoint 2007 Features
  • Delving into SharePoint 2007 Site Columns
  • Delving into SharePoint 2007 Content Types
Delving into SharePoint 2007 Personalisation

In SharePoint there are two types of modifications to sites; customisation and personalisation.  Customisation relates to changes for all users, this view of SharePoint is the "shared view".  The Shared View is a standard view of the page available to everyone.  Personalisation relates to a change made by an individual user on a per user basis, this view is the "personal view".

Enabling Personalised Views

Before you can start personalising pages you will need to enabling personalisation for users.  Personalisation features are enabled by granting rights for users in the Shared Services Provider.

  1. Navigate to the Shared Service Provider Administration website.
  2. Click on "Personalization services permissions".
  3. Add an individual user or group and grant rights for "Personal Features".

Personal Features allows users to personalise pages.  Personal Site allows users to have a MySite.

Please note: If you have NT Authority\Authenticated Users group listed with Personal Features you are allowing all domain users to personalise pages.

Now we have granted users the correct rights for personalisation, lets move onto personalising pages.

Personalising the page (personal views)

  1. Navigate to the desired page that you wish to personalise.
  2. Click on the "Welcome User Name" down arrow and select "Personalize this page". 
  3. The page can now be customised to your needs.
  4. After you have finished making changes, click on "exit personal view".

The screenshot below shows a personalised team site homepage with a new webpart for user's tasks.

When you personalise a page it will show up as the default view.  To show the "Shared View" again, click the "Show Shared View".

Resetting page content

  1. Navigate to the page that you wish to reset back to the "Shared View".
  2. Click on the "Welcome User Name" down arrow and select "Reset Page Content". 
  3. Click OK on the dialog.

When navigating back to this page the "Shared View" will be shown as the default (the "Personal View" no longer exists).

The screenshot below shows the shared view of the team site homepage.

Personalisation with WebParts

WebParts have configuration properties, typically these are set by the site collection owner or a user with the correct rights. These settings are applied to the "Shared View". When you create properties for webparts you can set the scope whether they are "Shared" or "User" personalisable properties. For example:

A Shared Property

[Personalizable(PersonalizationScope.Shared),
WebBrowsable(true),
WebDisplayName("RSS Feed Url"),
WebDescription("Location of RSS feed for control to display")]
public string RssFeedUrl
{
  get { return rssFeedUrl; }
  set { rssFeedUrl = value; }
}

A User Personalisable Property

[Personalizable(PersonalizationScope.User),
WebBrowsable(true),
WebDisplayName("Post Content"),
WebDescription("Show Titles or Full body of the post")]
public DisplayMode PostContent
{
  get { return postContent; }
  set { postContent = value; }
}

The enumeration PersonalizationScope controls whether the property is a shared customisation or a user customisation.

Considerations regarding enabling personalisation

Personalisation has a higher cost on performance than customisation.  For each user request SharePoint needs to decide which view to display to the user (whether the user has customised the page and needs to see the "personal view" or "shared view").  Because of this personalisation should be planned for and implemented with a good level of control / caution.

The content database stores shared and personalised versions of pages.  When a page is personalised the user personalised version is stored seperately in the content database to the shared version.  If 10 users personalise the homepage of a team site, the content database will hold 11 versions of the team site homepage (10 user personalised versions and 1 shared version).

MySites are a personalisable area for users.  They are designed for uses to modify and customise to help them carry out their daily jobs.  They have their personal view and shared view.  You should look into utilising MySites instead of enabling personal views, both have pros and cons.

Troubleshooting

  • The "Personalize this page" link may not appear if the page is checked out.
  • Whilst personalising the page if users can't move webparts between zones you may need to perform the following:
    • Verify the webparts have "Allow Close" and "Allow Hide".
    • Make sure the webpart zones allow personalization.  This is set using SharePoint Designer.
  • If user personalisation breaks the user's view and you can no longer see the page in order to reset the page content, pasting in the following command into the address bar of the web browser will call the same command.

javascript:MSOWebPartPage_RestorePageDefault();

Hope this helps

I've enabled comments
Just a quick note to let you know that I've enabled comments on my blog.  I'm looking forward to receiving your feedback.
 
If you are having issues please post on the UK SharePoint User Group http://suguk.org/forums/, of which I am an active member of a good community of users (including some MVPs).  Look out for dhunter on the user group.
Backup Script for K2 BlackPearl Databases
It's important to backup K2's databases before you deploy any new workflows.  At the moment there isn't a tool to remove K2 BlackPearl Workflow Process definitions deployed to a server.
 
If you have a backup of the databases then you can restore to that point in time.  K2 BlackPearl has 14 databases so it's easier to run a script to perform the backup rather than using Microsoft SQL Server Management Studio.
 
Here's my backup script ....
 
/* declare the variables */
declare @dbname as nvarchar(255)
declare @bckstmt as nvarchar(255)
declare @backupDir as nvarchar(255)
declare @dateSufix as nvarchar(10)

declare @year as varchar(4)
declare @month as varchar(2)
declare @day as varchar(2)

/*
Creates a backup for each of the K2 BlackPearl databases
in a specified folder set by the variable @backupDir
Adds a suffix to the database names to reflect the date
for example:
In folder C:\_DBBackups
Categories_2008-03-14.bak */
/* set the variables */ SET @backupDir = 'C:\_DBBackups' SET @year = CONVERT(varchar(4),DATEPART(yyyy, GetDate())) SET @month = CONVERT(varchar(2),DATEPART(mm, GetDate())) SET @day = CONVERT(varchar(2),DATEPART(dd, GetDate())) /* make sure the month and day variables contain 2 characters */ IF LEN(@month) = 1 SET @month = '0' + @month IF LEN(@day) = 1 SET @day = '0' + @day /* build the date suffix */ SET @dateSufix = @year + '-' + @month + '-' + @day /***************************************************************
backup the Categories database
****************************************************************/
set @dbname = 'Categories' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the Dependencies database
***************************************************************/
set @dbname = 'Dependencies' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the EnvironmentSettings database
***************************************************************/
set @dbname = 'EnvironmentSettings' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the EventBus database
***************************************************************/
set @dbname = 'EventBus' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the EventBusScheduler database
***************************************************************/
set @dbname = 'EventBusScheduler' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the HostServer database
***************************************************************/
set @dbname = 'HostServer' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the K2Server database
***************************************************************/
set @dbname = 'K2Server' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the K2ServerLog database
***************************************************************/
set @dbname = 'K2ServerLog' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the K2SQLUM database
***************************************************************/
set @dbname = 'K2SQLUM' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the SmartBox database
***************************************************************/
set @dbname = 'SmartBox' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the SmartBroker database
***************************************************************/
set @dbname = 'SmartBroker' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the SmartFunctions database
***************************************************************/
set @dbname = 'SmartFunctions' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the WebWorkflow database
***************************************************************/
set @dbname = 'WebWorkflow' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt) /***************************************************************
backup the Workspace database
***************************************************************/
set @dbname = 'Workspace' set @bckstmt = 'BACKUP DATABASE ' + @dbname + ' to ' + 'Disk = ' + char(39) + @backupDir + '\' + rtrim(ltrim(@dbname)) + '_' + @dateSufix + '.bak' + char(39) exec (@bckstmt)
 
Hope it helps.  Please test before using.
 
UPDATE: Corrected a syntax error.
Design Considerations for using the SharePoint UserProfileManager
I'm writing this post based on my experience with the UserProfileManager in SharePoint 2007.  I've seen many posts about people having issues using the UserProfileManager for normal users in SharePoint.
 
I will start with showing you how to access the user profiles using the UserProfileManager.  There are three ways to loop through the User Profiles, which are:
 
1.  For Each
// get the server context
Microsoft.Office.Server.ServerContext ctx = Microsoft.Office.Server.ServerContext.GetContext(HttpContext.Current);

// get the user profile manager
UserProfileManager userProfileManager = new UserProfileManager(ctx);

// get the count of the user profiles
int numberOfProfiles = userProfileManager.Count;

// loop through the user profiles
foreach(UserProfile profile in userProfileManager)
{
    // do some action on each currentProfile
}
2.  For Loop
// get the server context
Microsoft.Office.Server.ServerContext ctx = Microsoft.Office.Server.ServerContext.GetContext(HttpContext.Current);

// get the user profile manager
UserProfileManager userProfileManager = new UserProfileManager(ctx);

// get the count of the user profiles
int numberOfProfiles = userProfileManager.Count;

// loop through the user profiles
for (int i = 0; i < numberOfProfiles; i++)
{
    try
    {
        UserProfile profile = userProfileManager.GetUserProfile(i);

        // do some action on each currentProfile
    }
    catch (Exception ex)
    {
        // failed to get user profile
        // log the error
    }
}
3.  GetEnumerator
// get the server context
Microsoft.Office.Server.ServerContext ctx = Microsoft.Office.Server.ServerContext.GetContext(HttpContext.Current);

// get the user profile manager
UserProfileManager userProfileManager = new UserProfileManager(ctx);

UserProfile currentProfile;

// get the enumerator
System.Collections.IEnumerator enumProfs = userProfileManager.GetEnumerator();

bool continueEnum = true;

// loop through profiles
while (continueEnum)
{

    try
    {
        // move to next profile
        continueEnum = enumProfs.MoveNext();
    }
    catch (Exception ex)
    {
        // failed to get user profile
        // log the error
        // try to move to the next user profile

        continueEnum = enumProfs.MoveNext();
    }


    currentProfile = (UserProfile)enumProfs.Current;

    // do some action on each currentProfile

}
Using either of these methods with a user without rights for "Manage User Profiles" (set in the SSP Administration) returns a 403 Error in IIS.
 
If the user doesn't have rights you may think to use the SPSecurity.RunWithElevatedPrivileges for more information http://www.davehunter.co.uk/Blog/Lists/Posts/Post.aspx?ID=43.  RunWithElevatedPrivileges runs the code in the brackets under the SharePoint System Account.  This still fails.
 
If you debug the code you will receive the following error message:
 
 
After reviewing the MSDN Help, I found ...
 
 
<snip>
You must create the UserProfileManager object before accessing a UserProfile object. You can then retrieve the user profiles to which the user has access. Full access to everyone's user profile requires "Manage User Profiles" rights. Full access to your own profile requires "Use Personal Features" rights. Everyone has read access to all profiles.
</snip>
 
A workaround could be to iterate through a set number and trying to retrieve the profile relating to the current integer, for example:
// get the server context
Microsoft.Office.Server.ServerContext ctx = Microsoft.Office.Server.ServerContext.GetContext(HttpContext.Current);

// get the user profile manager
UserProfileManager userProfileManager = new UserProfileManager(ctx);

// set the number of profiles to iterate through
int numberOfProfiles = 400;

// loop through the user profiles
for (int i = 0; i < numberOfProfiles; i++)
{
    try
    {
        UserProfile profile = userProfileManager.GetUserProfile(i);

        // do some action on each currentProfile
    }
    catch (Exception ex)
    {
        // failed to get user profile
        // log the error
    }
}
 
I wouldn't recommend using this approach.  I feel the best approach would be to perform a search for people in SharePoint.  This can be created using a CAML query against the API or Web Service.  I will follow up this article with steps to achieve this.  A search would return public properties exposed to the search and wouldn't need administrative priviledges.
 
On summary ...
 
Iterating through the user profiles using UserProfileManager requires "Manage User Profiles" rights and therefore is an administrative function.
 
Only use the UserProfileManager if you are designing an administrative tool to modify the user profiles.  You should only use the UserProfileManager to retrieve a single user profile (either the current user or a known account by using the domain/username).
SharePoint and Silverlight
Some interesting articles and source code have been release recently regarding SharePoint and Silverlight.
 
Silverlight BluePrint for SharePoint
 
At the time of writing this post this site contains 6 samples for using Silverlight with SharePoint, these include:
  1. Hello Silverlight Web Parts and the SilverlightPart
  2. Silverlight Navigation Controls
  3. Silverlight Social Networking Web Part
  4. Visual How-To center with Silverlight
  5. Picture Viewer sample
  6. Silverlight Custom Field Types

All samples contain source code, video, setup instructions and code walkthrough.  http://www.ssblueprints.net/sharepoint/ 

Ian Morrish's Article about using the Silverlight and SharePoint using the DataView web part.  http://www.wssdemo.com/pages/silverlight.aspx.
 
 
Triplewood's SharePoint Silverlight Browser
 
From Triplewood ...
 
A SharePoint Silverlight Web Part which displays SharePoint Documents and Pictures in a rich Silverlight flow control.
 
 
 
For more information on Silverlight and to download please see http://silverlight.net/default.aspx.
1 - 10 Next
  Copyright
This work is licenced under a Creative Commons Attribution-Noncommercial-No Derivative Works 2.0 UK: England & Wales License
  Site Map

 Dave Hunter

I'm currently a Senior Consultant at CIBER UK. I specialise in Microsoft Information Worker technologies (especially MOSS, MCMS and .NET), with nearly 8 years of experience within this area of specialism. 

I have also gained two certifications for MOSS and WSS.

View Dave Hunter's profile on LinkedIn

Subscribe Subscribe

 Latest Posts

Use InfoPath to author XML schemas (XSD)12/06/2008 15:23
K2 BlackPearl - Update Design Templates06/06/2008 13:49
Tip - SharePoint 2007 Escaped Column Names 04/06/2008 13:27
Powershell SharePoint 2007 Backup Script30/05/2008 17:20
SharePoint 2007 Delving into Articles15/04/2008 13:17
Delving into SharePoint 2007 Personalisation08/04/2008 21:10
I've enabled comments02/04/2008 13:05
Backup Script for K2 BlackPearl Databases14/03/2008 16:00
Design Considerations for using the SharePoint UserProfileManager13/03/2008 22:10
SharePoint and Silverlight12/03/2008 12:15
1 - 10 Next
Posts that contain SharePoint per day for the last 30 days.
Technorati Chart