Saturday, February 10, 2007

 

I'm at the European SharePoint Conference in Berlin which is on from Monday 12- Wednesday 14 Feb.

Hope to see some fellow SUGUK's and people I've only know though their blogs. Should be a good one.

If anyone is attending and wants to talk SharePoint and/or PowerShell ping me here.

Saturday, February 10, 2007 8:33:37 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

 

Following on from the work in my previous post where I set the users Picture property in their profile the next step is to add a Contact Web Part to our imported publishing pages. I’m using the default layout page to add the contact Web Part to, this page has the Web Part Zones underneath the content fields but you could use another layout that has a Web Part zones to the right of the content fields and of course you can use SharePoint Designer to create your own layout formats and embed the Contact control without using code.

This is how our publishing pages will look once we have added the Web Part to each page

An interesting feature of a Publishing page is that it has a contact property where you can assign user details to each page, you can either lookup the user from the picker in which case the page will pull the users details from the profile database or you can type in the details yourself.

 

The nice thing about the Contact Web Part is that once you have added it to a publishing page it will automatically pull the picture and the users description (if set in the Web Part) that has been assigned to the page from the profile database.

One bad thing about the part is you only get the choice to put the users name left or right not top or bottom.

So on to the code, I need a function that will take a site URL and then set the default Publishing Page’s contact property and then add the Web Part to the page.

 

 

# Function: Add-ContactWebPart # Description: Adds the Contact User Web Part to a publishing page # Parameters: SiteURL - Server relative URL of the Area # UserName - UserName to show as the contact in domain\user format # # Requirements: Needs to have the System.Web assembly loaded # function Add-ContactWebPart($SiteURL, $UserName) { $comment = "Contact WebPart Added" $site = new-object Microsoft.sharePoint.SPSite($SiteURL) $web=$site.OpenWeb() $user= $web.Users.get_item($UserName) $pubweb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web) $defaultpage=$pubweb.GetPublishingPages()[$pubweb.DefaultPage] $defaultpage.CheckOut() # Set Contact "Setting Contact on " + $pubweb.url + " to " + $user.Name $defaultpage.set_Contact($user) $defaultpage.Update() $webpartmanager=$web.GetLimitedWebPartManager($defaultpage.Url, [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared) $webpart=new-object Microsoft.SharePoint.Portal.WebControls.ContactFieldControl $webpart.ChromeType=[System.Web.UI.WebControls.WebParts.PartChromeType]::TitleOnly; $webpart.Title="Page Contact" $webpart.PicturePosition=[Microsoft.SharePoint.Portal.WebControls.PictureDirection]::Left $webpart.IsDisplayJobTitle=$true $webpart.IsDisplayPicture=$true $webpartmanager.AddWebPart($webpart, "LeftColumnZone", 0); " Checking in page" $defaultpage.CheckIn($comment) # Publish if($defaultpage.listItem.ParentList.EnableMinorVersions -eq $true -and $publishingPage.ListItem.File.MinorVersion -ne 0) { " Publishing" $defaultpage.listItem.File.Publish($comment) } # If moderation is being used handle the approval if ($defaultpage.listItem.ParentList.EnableModeration) { $modInformation = $defaultpage.listItem.ModerationInformation " Moderation on, Current Status: " + $modInformation.Status # Check for pending approval if($modInformation.Status -ne [Microsoft.SharePoint.SPModerationStatusType]::Approved) { " Approving" $defaultpage.ListItem.File.Approve($comment) } } # Clean up $pubweb.Close() $web.Close() $site.Close() }

 

In this code we find the SPUser object for the given username and set the Contact property of the PublishingPage to it. We then add the web Part using the new SPLimitedWebPartManager class. Most of the code is concerned with checking the page out and back in and assumes the page is not already checked out.

An interesting line is

$defaultpage=$pubweb.GetPublishingPages()[$pubweb.DefaultPage]

I'm indexing into the collection return by GetPublishingPages because Powershell doesn't support generics in the current version.

Saturday, February 10, 2007 8:17:59 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, February 07, 2007

The UK Met Office website goes down.

running Apache apparently, bless

Web
Wednesday, February 07, 2007 1:34:32 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

Don't forget the SharePoint user group meeting taking place tomorrow Feb 8th at Reading.

'Mr SharePoint community' Lawrence Lui is over from Redmond to take us through the Fab 40 Application Templates and lead a discussion on Office 14.

Sign ups and more detail here: http://suguk.org/forums/1/1901/ShowThread.aspx

Wednesday, February 07, 2007 1:08:50 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, January 28, 2007

Now we have the portal setup I want to add a Contact WebPart to each page but before I can do that I have to add a picture for each user I have imported, in order to keep this post a little shorter I’m only going to concentrate on using the UserProfile API’s to set our picture for each user.
(The Contact WebPart is MOSS WebPart that shows a users name and description and optionally their picture)
The field that we are going to set programmatically is accessed on the Users edit profile page as Picture:

Once set this will display the picture on the user profile like this


To do this I need to revisit our User.csv import file and add an extra field that gives the name of the JPG file that holds the users picture.
I’m going to assume that the previous blog post Upload a directory of files in 4 lines has already uploaded the users picture to the SiteCollectionImages picture library, in real life you’d probably use a separate picture library.


Ideally a profile import has occurred after we have added the users to Active Directory and populated the SharePoint profile database.

Now to set the Users Picture property we know to know the Property Name of the Picture Field.
To make this easy to find out here’s the first function for our toolbox Get-SPUserProfileConfigManager.
This function returns a UserProfileConfigManager (http://msdn2.microsoft.com/en-us/library/microsoft.office.server.userprofiles.userprofileconfigmanager.aspx), note this is the new class that resides in the Microsoft.Office.Server namespace not the v2 obsolete one that lives in Microsoft.sharePoint.Portal.UserProfiles.
Also ignore the sample currently given in the MSDN documentation above, it won’t work as it uses the old classes where you pass a PortalContext to the constructor whereas the new version of the classes take a ServerContext object.

 

# Function: Get-UserProfileConfigManager # Description: return a UserProfileConfigManager object which is used for management of MOSS User Profiles # Parameters: PortalURL URL for the Portal Site Collection # # function Get-UserProfileConfigManager([string]$PortalURL) { # Need to get a PortalContext object # as we do not have a HttpContext we need to source one the hard way $site=new-object Microsoft.SharePoint.SPSite($PortalURL) $servercontext=[Microsoft.Office.Server.ServerContext]::GetContext($site) $site.Dispose() # clean up # Return the UserProfileConfigManager new-object Microsoft.Office.Server.UserProfiles.UserProfileConfigmanager($servercontext) }

 

Once we get the UserProfileConfigManager we can call GetProperties and list the internal and display names for each profile property

$cm=get-userprofileconfigmanager "http://sps:2828" $cm.getproperties() | select name, displayname Name DisplayName ---- ----------- UserProfile_GUID Id SID SID ADGuid Active Directory Id AccountName Account name FirstName First name LastName Last name PreferredName Name WorkPhone Work phone Office Office Department Department Title Title Manager Manager AboutMe About me PersonalSpace Personal site PictureURL Picture UserName User name QuickLinks Quick links WebSite Web site PublicSiteRedirect Public site redirect SPS-Dotted-line Dotted-line Manager SPS-Peers Peers SPS-Responsibility Responsibilities SPS-Skills Skills SPS-PastProjects Past projects SPS-Interests Interests SPS-School Schools SPS-SipAddress SIP Address SPS-Birthday Birthday SPS-MySiteUpgrade My Site Upgrade SPS-DontSuggestList Don't Suggest List SPS-ProxyAddresses Proxy addresses SPS-HireDate Hire date SPS-LastColleagueAdded Last Colleague Added SPS-OWAUrl Outlook Web Access URL SPS-ResourceSID Resource Forest SID SPS-ResourceAccountName Resource Forest Account Name SPS-MasterAccountName Master Account Name Assistant Assistant WorkEmail Work e-mail CellPhone Mobile phone Fax Fax HomePhone Home phone

So from this list I see that I need to set the PictureURL property, to get a UserProfile we first need a UserProfileManager object:

# Function: Get-SPProfileManager # Description: Return a UserProfileManager object which is used for accessing MOSS User Profiles # Parameters: PortalURL URL for the Portal Site Collection # function Get-SPProfileManager([string]$PortalURL) { # Need to get a PortalContext object # as we do not have a HttpContext we need to source one the hard way $site=new-object Microsoft.SharePoint.SPSite($PortalURL) $servercontext=[Microsoft.Office.Server.ServerContext]::GetContext($site) $site.Dispose() # clean up # Return the UserProfileManager new-object Microsoft.Office.Server.UserProfiles.UserProfileManager($servercontext) }

And then a helper function Get-SPUserProfile to obtain the UserProfile object itself:

# Function: Get-SPUserProfile # Description: Return a UserProfile object, this will be created if it does not exist # Parameters: PortalURL URL for the Portal Site Collection # DomainUser UserName in Domain\user format function Get-SPUserProfile([string]$PortalURL, [string] $DomainUser) { $upm= Get-SPProfileManager([string]$PortalURL) if ($upm.UserExists($DomainUser) -eq $false) { $upm.CreateUserProfile($DomainUser) } $upm.GetUserProfile($DomainUser) }

Note that this function will create the UserProfile if it does not already exist.

Now we just need a function that makes it easy to set a single UserProfile property, if you have multiple properties to set it would be best to do them all at once and then call commit.

# Function: Set-UserProfileProperty # Description: Sets a property on a User Profile # Parameters: UserName [optional] UserName in Domain\user format # PropertyName Property to set # PropertyValue Property Value to set # $UserProfile UserProfile object, if using this in a loop this should be set # function Set-UserProfileProperty([string]$UserName, [string] $PropertyName, [string] $PropertyValue, [Microsoft.Office.Server.UserProfiles.UserProfile] $UserProfile) { # If we are not passed a UserProfile object then create it # if ($UserProfile -eq $null) { $UserProfile = Get-SPUserProfile($UserName) } $UserProfile[$PropertyName].Value= $PropertyValue $UserProfile.Commit() }

Note this function can either be called with a pre-created userProfile object or a UserName.

Heres the updated Users.CSV with the Picture Field added at the end  

LoginName, DisplayName, FirstName, LastName, Email, Picture brianb, Brian Ballack, Brian, Ballack, brianb@contoso.com, cowner10.jpg walterf, Walter French, Walter, French, walterf@contoso.com, cowner12.jpg

Now a function to tie this all together, it imports the CSV files, locates the user profile by login name and updates the user’s Picture URL:

function Set-UserPictures([string] $PortalURL, [string] $UserFile, [string] $Domain ) { Import-Csv $UserFile | foreach-object { $name=$Domain + "\" + $_.LoginName; $fullURL=$PortalURL + "/" + $_.Picture; Set-UserProfileProperty $PortalURL $name "PictureURL" $fullURL } }

 And you can make use of all of the above code by running this command:

Set-UserPictures "http://sps:2828" "users.csv" "contoso"

Ok now we're all set to add the Contact WebPart to each publishing page in the next post.

Sunday, January 28, 2007 6:24:37 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, January 25, 2007

Made the UK PowerShell User Group meeting last night in Wokingham, just, the weather and people having accidents on the M3 and M4 kept me late. Got to try out my new Acer GPS unit based on Windows Mobile 5, worked beautifully until setting the return journey when a fatal exception dialog popped up on route calculation, I had to reboot the unit, having seen that dialog many times developing on WM I just had to laugh.

Nice to meet other PowerShell enthusiasts, kudos to PowerGadgets for supplying the beer and pizza and Global Knowledge for hosting.

The meeting was hosted by all round good guy Thomas Lee along with Richard Siddaway. Thomas gave an interesting presentation on PowerShell installation a lot of which I didn't know.

One point to come out of the discussion was the number of profiles that PowerShell will load when it first starts up. Here are the locations and order the profiles get loaded in, note these files won't exist unless you or your admin has created them

  1. %windir%\system32\WindowsPowerShell\v1.0\profile.ps1  (all users, all shells)
  2. %windir%\system32\WindowsPowerShell\v1.0\ Microsoft.PowerShell_profile.ps1 ( all users, the Windows Powershell shell)
  3. %userprofile%\My Documents\WindowsPowerShell\profile.ps1  (per user, all PowerShell versions)
  4. %userprofile%\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 ( per user and the default Windows Powershell shell)

Now you can put code or functions in each of these files but the last loaded file wins if there are any conflicts.

This could be a problem with some companies that would like to define a corporate wide profile for every user and put it in system32\WindowsPowerShell\v1.0, as a user I can override any of the company function definitions with my own code in my own profile. You could lock down the PowerShell %userprofile% files but that might cause other problems.

Someone pointed out at the meeting what was needed is a readonly profile that can be loaded globally and last for every user but hey presto there's a PowerShell team blog out today on making functions read-only http://blogs.msdn.com/powershell/archive/2007/01/25/controlling-powershell-function-re-definition.aspx , now that's what I call service.

 

As the meeting closed Thomas also gave out a USB Pen drive to everyone who turned up loaded with PowerShell related goodies, woo hoo free stuff, and oh yeah I'll be speaking at the next meeting about controlling SharePoint with PowerShell, should happen sometime in March.

 

 

Thursday, January 25, 2007 9:36:19 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, January 11, 2007

I just finished finalising the flights and hotels to attend the SharePoint 2007 European Conference in Berlin today when I realised I knew zip about the German language, yes I know the usual German words picked up from films, schnell, bitte etc. but I'd never spoken one single german phrase for real.

Whatever country I go to I try to speak a little of the local language, if nothing else it gives the waiters a laugh, so I needed a quick and easy starters course in German, a little Googling and I found this gem German Podcasts by Stephan Wiesner

This is fantastic, its a series of podcasts where Stephan takes you through a story teaching you German as he goes about a Hans a German progammer who flies into an airport, goes through customs and talks about a conference he's been at!

The story is nicely pitched at the complete beginner and Stephan has produced mp3's, pdfs to accompany and even a video.

The content is also posted at http://www.archive.org which lets you listen on the webpage itself via a Flash plugin.

I wonder can he do a podcast that teaches me how to say: 'What?? you're NOT using PowerShell to script SharePoint?'

 

 

 

Thursday, January 11, 2007 6:12:07 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [2]  | 
 Sunday, December 17, 2006

You might have heard about the Million Dollar Homepage where a Alex Tew sold pixels on a 1000x1000 grid on his website thus making him over a millon dollars, an idea which falls both into the 'Why didn't I think of that' and 'there's one born every minute' categories, however there is a site out there that loosely takes the idea and turns it towards a much better cause.

From the Darfur Wall website itself:

The numbers 1 to 400,000 cover the 40 panels of The Darfur Wall. Each number represents a person killed in Darfur. By donating $1 or more you can light a number, turning it from dark gray to brilliant white. As we light the wall, we acknowledge the importance of each life lost, we cast light upon a tragedy too many have ignored, and we overcome one barrier to peace.

 

 

Its sobering to think that each number represents a human life lost, please promote this site where and when you can, it would be nice to see that wall brightly lit.

Strangely although I came to the site via Digg there is a SharePoint connection to this, the site has been setup by Jonah Burke ex of the MOSS BDC Team who I happened to see speak at TechED in Boston.    

And what number did I pick? In true geek fashion 443 of course.

 

 

Sunday, December 17, 2006 8:40:54 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 

 

As a follow on from my previous post we can do some neat calculations on the amount of data stored in MOSS personal sites using Powershell.

Using the measure-object CmdLet against the StorageUsedMB property we can calculate the number of personal sites (+1 one as it includes the root site), average size of of each site, smallest, largest and total storage size of all sites.

Again assuming http://sps:20488 is where your personal sites are hosted

PoSH C:\demo> $output=stsadm -o enumsites -url "http://sps:20488"
PoSH C:\demo> $xml=[XML]$output
PoSH C:\demo> $xml.sites.site | measure-object storageusedmb -min -max -sum -average | format-table

Count Average Sum Maximum Minimum Property
----- ------- --- ------- ------- --------
5      0.62   3.1 0.7     0.4     StorageUs...

To get a list of the sites in question with the largest at the top use -descending on the sort CmdLet:

PoSH C:\demo> $xml.sites.site | sort storageusedmb -descending | select url, owner, storageusedMB | format-table

Url                         Owner                    StorageUsedMB
---                         -----                    -------------
http://sps:20488/person... CONTOSO\mike               0.7
http://sps:20488/person... CONTOSO\jeff               0.7
http://sps:20488/person... CONTOSO\administrator      0.7
http://sps:20488           CONTOSO\administrator      0.6
http://sps:20488/person... CONTOSO\brianb             0.4

And if you just want the top 2 offenders us the -first option on the select-object CmdLet

PoSH C:\demo> $xml.sites.site | sort storageusedmb -descending | select url, owner, storageusedMB -first 2 | format-table

Url Owner StorageUsedMB
--- ----- -------------
http://sps:20488/person... CONTOSO\mike 0.7
http://sps:20488/person... CONTOSO\jeff 0.7

 

Obviously in real life those figures would be a lot larger!

Sunday, December 17, 2006 4:58:38 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 

A point came up at the UK SharePoint User Group Chrismas drink, about Personal sites and whether they were top level sites i.e they exist as records in the Sites table and are the top level container for all its subwebs, I hadn’t checked this in v3 so a quick check with PowerShell and stsadm confirms that this is still the case as in V2

Assuming http://sps:20488 is where your personal sites are hosted calling stsadm -o enumsites and processing the returned XML in PowerShell gives us

PoSH C:\demo> $output=stsadm -o enumsites -url "http://sps:20488"
PoSH C:\demo> $xml=[XML]$output
PoSH C:\demo> $xml.sites.site

Url : http://sps:20488
Owner : CONTOSO\administrator
ContentDatabase : WSS_Content_11fba01f-f0c4-4a05-a3c3-868499fd31ce
StorageUsedMB : 0.6
StorageWarningMB : 0
StorageMaxMB : 0

Url : http://sps:20488/personal/administrator
Owner : CONTOSO\administrator
ContentDatabase : WSS_Content_11fba01f-f0c4-4a05-a3c3-868499fd31ce
StorageUsedMB : 0.7
StorageWarningMB : 80
StorageMaxMB : 100
Etc…

Tiding up the output a little

PoSH C:\demo> $xml.sites.site | select url, owner

Url Owner
--- -----
http://sps:20488                           CONTOSO\administrator
http://sps:20488/personal/administrator    CONTOSO\administrator
http://sps:20488/personal/brianb           CONTOSO\brianb
http://sps:20488/personal/jeff             CONTOSO\jeff
http://sps:20488/personal/mike             CONTOSO\mike
….

 

 


Sunday, December 17, 2006 4:40:58 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, December 03, 2006

Now that I have added some content to our portal I want to approve and publish all pages in each publishing web.

To do this I've created a function that takes an MOSS PublishingPage object and a comment that will be added when we check-in, approve and publish.

 

# Function: Approve-PublishingPage
# Description: Approve a single page in a Publishing Web
# Parameters: publishingPage PublishingPage object
# comment Comment to accompany the check-in/approve/publish
#
function Approve-PublishingPage ([Microsoft.SharePoint.Publishing.PublishingPage]$publishingPage, [string]$comment)
{
" Publishing Page: " + $publishingPage.Name

$listitemfile = $publishingPage.ListItem.File

# Check item if checked out
if ($listitemfile.Level -eq [Microsoft.SharePoint.SPFileLevel]::Checkout)
{
   " Checking in page"
   $listitemfile.CheckIn($comment,[Microsoft.SharePoint.SPCheckInType]::MajorCheckin )
}


# If moderation is being used then handle the approval and publishing
if ($publishingPage.ListItem.ParentList.EnableModeration)
{
   $modInformation = $publishingPage.ListItem.ModerationInformation

   " Moderation Enabled"

   # Check for pending approval
   if($modInformation.Status -eq [Microsoft.SharePoint.SPModerationStatusType]::Pending)
   {
      " Approving"

      $listitemfile.Approve($comment)
   }

   # Publish
   if($modInformation.Status -eq [Microsoft.SharePoint.SPModerationStatusType]::Draft)
   {
   " Publishing"
   $listitemfile.Publish($comment)
   }
}
}

this function will be called from Approve-AllPagesInSPWeb

# Function: Approve-AllPagesInSPWeb
# Description: Loop through all the pages in a Publishing Web and checkin and approve them
# Parameters: web SPWeb object
# comment Comment to accompany the checkin/approve/publish
#
function Approve-AllPagesInSPWeb([Microsoft.SharePoint.SPWeb]$web, [string]$comment)
{

# Check this is a publishing web
if ([Microsoft.SharePoint.Publishing.PublishingWeb]::IsPublishingWeb($web) -eq $true)
{

$pubweb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web);

"Checking $($pubweb.URL)" 

   $pubcollection=$pubweb.GetPublishingPages() 

   for($i=0; $i -lt $pubcollection.count; $i++)
   {
      Approve-PublishingPage $pubcollection[$i] $comment
   }

}

}

Now I'd like to use a foreach look around the GetPublishingPages collection but that's not possible due to lack of Generic support in PowerShell at the moment, so an index loop does the job.

To approve all pages in all webs we can pipe the SPWebs to a foreach loop and pass the SPWeb object to Approve-AllPagesInSPweb

$site = spsite "http://yourmossserver"
$site.allwebs | foreach-object {Approve-AllPagesInSPweb $_ "System Approval"}

Added as a function approveall it produces this output

 

In the next step I'll add a Contact WebPart to every page.

 

 

Sunday, December 03, 2006 9:01:15 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [6]  | 
 Sunday, November 19, 2006

Yes...Fitz is blogging again. At last Mike Fitzmaurice one of the primary links between the SharePoint team and the outside world is blogging again.

No...Maurice Prather one of the few hardcore SharePoint bloggers around has posted that he is leaving the SharePoint team. That's a real loss, overall compared to say the PowerShell team the state of blogging from the SharePoint team has been really poor over the last year, but as blogs come second best to shipping a product out the door perhaps that's understandable, hopefully things will improve once the RTM celebrations have finished. 

 

Sunday, November 19, 2006 3:34:24 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

In a previous post I've added content to the publishing pages in the legal and finance divisions and its useful to know what fields are in a list when working with the SharePoint API or say the Query By Content WebPart . Yes you can do using the UI but its a pain.

First get the SPWeb object for our site

$site=spweb "http://sps:2828/divisions/finance"
$web=$site.Openweb()

now show the lists on the site

$web.lists | select title,contenttypes

Title                                   ContentTypes                          
-----                                   ------------                          
Documents                               {Document, Folder}                    
Images                                  {Document, Folder}                    
Master Page Gallery                     {Master Page, Folder}                 
Pages                                   {Page, Article Page, Welcome Page, F...
Workflow History                        {Workflow History}                    
Workflow Tasks                          {Task, Folder}
                        


The Pages list holds the publising pages so let's list its fields


$web.lists["Pages"].Fields | select title, internalname, typedisplayname | sort title

Title                      InternalName               TypeDisplayName         
-----                      ------------               ---------------         
Approval                   Approval                   Workflow Status         
Approval Status            _ModerationStatus          Moderation Status       
Approver Comments          _ModerationComments        Multiple lines of text  
Article Date               ArticleStartDate           Date and Time           
Byline                     ArticleByLine              Single line of text     
Check In Comment           _CheckinComment            Lookup                  
Checked Out To             CheckedOutTitle            Lookup                  
Checked Out To             CheckoutUser               Person or Group         
Checked Out To             LinkCheckedOutTitle        Computed                
Client Limit               Client_x0020_Limit         Number                  
Collect Feedback           CollectF                   Workflow Status         
Collect Signatures         CollectS                   Workflow Status         
Contact                    PublishingContact          Person or Group         
Contact E-Mail Address     PublishingContactEmail     Single line of text     
Contact Name               PublishingContactName      Single line of text     
Contact Picture            PublishingContactPicture   Hyperlink or Picture    
Content Type               ContentType                Choice                  
Content Type ID            ContentTypeId              Content Type Id
       

etc...

There are a lot of fields, to get the count use $web.lists["Pages"].Fields | measure-object
That gives 92 fields for the Pages library.

To see the content publishing pages themselves use

$web.lists["Pages"].Items | select name, file, level

Name                       File                                           Level
----                       ----                                           -----
default.aspx               Pages/default.aspx                             Draft
Client1.aspx               Pages/Client1.aspx                             Published


and finally two functions for our toolbox to make calling these easier

function get-SPListFields([string]$URL, [string]$ListName)
{
$site=get-spweb $URL
$web=$site.OpenWeb()
$list=$web.Lists[$ListName]
$list.Fields
}

function get-SPListItems([string]$URL, [string]$ListName)
{
$site=get-spweb $URL
$web=$site.OpenWeb()
$list=$web.Lists[$ListName]
$list.Items
}

These functions will come in useful later when we approve pages in a site with PowerShell.

 

 

Sunday, November 19, 2006 3:09:58 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

One of the things that the PowerShell team has always pointed out is the importance of naming conventions in functions.
Most of the bult-in PowerShell functions have a verb-noun format i.e. get-process, get-service etc..
Keeping things consistent across the different types of providers helps with the learning process as you can almost guess what a cmdlet would be called once you know the noun.

Up to now I thought this was just a syntax sugar but this blog entry from the main PowerShell guy Jeffrey Snover points out an important benefit if you name your functions correctly.
When you type a function name, and PowerShell tries to match the correct code to call, it will automagically add a get- to the function name and try to match on that if it fails to find a function of the exact name.

Heres an example take the simple get-SPSite function

function get-SPSite([string]$url)
{
   new-object Microsoft.SharePoint.SPSite($url)
}

I've been using this as $a=get-spsite "http://server" but I could have used $a=spsite "http://server". Its a small thing but if you're typing on the command those extra four characters add up plus it almost looks like C# code not having to use a lengthy namespace prefix.

Likewise for get-SPWeb

function get-SPWeb([string]$url)
{
   $site=new-object Microsoft.SharePoint.SPSite($url)

   $site.OpenWeb()
}

 


 

Sunday, November 19, 2006 3:04:49 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  |