Tuesday, July 23, 2013

Checking and granting ShellAdmin rights

You can check which users has enough permissions by running:

Get-SPShellAdmin

If your current user doesn't have enough permissions you can grant ShellAdmin rights by running:

Add-SPShellAdmin -UserName <domain>\<username> -database <DB Name>

See these pages for more information:

Number of users in the User Profile service application

You can obtain the number of users in the user profile service application by opening the settings page for the service application inside of central administration.

To navigate to this page, open:
  • Central Administration
  • Next click "Application Management"
  • Then "Manage service applications"
  • Now, click on the name for the user profile service application
On the page that opens there is a total count of users in the upper right corner. 

Number of users in the user profile service application
Alternatively, you can also obtain this same count by using PowerShell. First obtain a UserProfileManager object:

$mySite_url = <Url to your My Site site collection>;
$context = Get-SPServiceContext $mySite_url;
$upm= New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context);
Write-Host($upm.Count);

Note: the script above must be run by as a user that has ShellAdmin rights. 

See this post on how to check if your current user has enough rights, and if needed how to grants the user ShellAdmin rights.

In SharePoint 2010 there might exist a bug in the count method for the UserProfileManager object. Under some circumstances count method will return a different number of profiles than what can be iterated over in a loop.

For example, to count all available profiles by iterating, run the following additional lines of PowerShell code:

$profiles = $upm.GetEnumerator();
$profiles.Reset();
$count = 0;
foreach($profile in $profiles) {$count++;}
Write-Host($count);

Sometimes $count will have a lesser value than what $upm.Count returns.

See this and this for additional information to what causes this issue.

Thursday, July 11, 2013

Ghosting the unghosted master page

Sometimes master page files in SharePoint libraries can become unghosted, meaning they are no longer linked to a physical file in the file system. This can happen when someone, for example, edits a master page using SharePoint Designer.

A file inside a library have have one out of three different states when looking at its state using PowerShell and the SPFile.CustomizedPageStatus property:
  • customized
  • un-customized
  • none
Customized (unghosted) means the file is no longer linked to a physical file, un-customized (ghsoted) means the file is linked to a local file (and if needed can by updated via a solutions package) and none means the file never had a file linked to it.

If you are updating through a wsp package a master page and notice the currently installed master page is in the "none" state, proceed with first renaming the current master page. Note: this will not break the pages that are currently using it. Pages use a reference to master pages, changing their names will not change the reference. Next install/update the package that contains the update master page. If you now check the library you should see the new, and updated, file.

You can check the ghosted/unghosted status of files by running:

$masterPageGallery = "Master Page Gallery"
$url = "http://www.example.com"

$site = Get-SPSite $url
$list = $site.RootWeb.Lists[$masterPageGallery]

foreach($item in $list.Items)
{      Write-Host $item.Name "-" $item.File.CustomizedPageStatus

If you find that the file you are trying to update is unghosted you got a few different options. You can add little bit of logic to the snippet above to check the status of the files and programmatically revert them to their ghosted state. I.e. instead of just printing them to the prompt, run $item.File.RevertContentStream(); to re-ghost the files you found to be unghosted.

Another option is to use some some external tool, like http://spghostfilesmanager.codeplex.com/,  to re-ghost the files you need ghosted.

For more information on SPFile, CustomizedPageStatus and RevertContentStream(), read http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spfile.aspx.

Also check out http://jamestsai.net/Blog/post/SPFileCustomizedPageStatus-amp3b-SPFileRevertContentStream-The-way-to-check-SPFile-GhostUn-Ghost-status-and-Revert-to-site-definition-via-code.aspx for more information on what makes a file unghosted and how you can programmatically re-ghost it.

Site collection backup

A site collection can easily be backed up in PowerShell using the following script:

$root_dir="path to backups";Backup-SPSite –Identity 
http://domain.tld/sites/test -Path $root_dri+"\test.bak"

or written on one line as

$root_dir="path to backups"; Backup-SPSite –Identity http://domain.tld/sites/test -Path $root_dri+"\test.bak"

Just copy and paste the code above and enter a real value for $root_dir before running it.

This script can be modified a little and extended to backup all site collections in the farm as well:

$root_dir = "path to backups"
Get-SPSite | ForEach-Object
    $FilePath = $root_dir + $_.Url.Replace("http://","").Replace(https://,"").Replace("-","--").Replace("/","-").Replace(";","-") + ".bak"; 
    Backup-SPSite –Identity $_.Url -Path $FilePath;
}

in the same way it can also be written as a one-liner:
$root_dir="path to backups"; Get-SPSite | ForEach-Object{$FilePath = $root_dir + $_.Url.Replace("http://","").Replace(https://,"").Replace("-","--").Replace("/","-").Replace(";","-") + ".bak"; Backup-SPSite –Identity $_.Url -Path $FilePath}

For reference read http://technet.microsoft.com/en-us/library/ff607901.aspx to learn what other parameters there are available for Backup-SPSite.

Wednesday, July 10, 2013

How to update SharePoint solutions?

Here is a PowerShell script for updating and deploying already installed wsp solution in a SharePoint farm.

Normally when you run Update-SPSolution SharePoint adds the solution to be updated to a queue and a installation/deployment job will take care of the actual installation. Before the timerjob runs there might be a few seconds delay, as for while the timerjob is running and performing the actual deployment of the newly updated solution.

I came up with the following script to check if the deployment is finished or still running. It doesn't return the prompt before it is done installing all solution located inside of a user specified directory, $packages_folder.

$packages_folder = "packages"

$local_path = $(get-location)
$packages = [IO.Directory]::GetFiles("$local_path\$packages_folder"); 

write-host "Installing:"
foreach ($package in $packages) {
 $package_withoutPath = $package.split('\')[-1];
 $wspID = Get-SPSolution -Identity $package_withoutPath;
 
 #wait here until the previously deployed package is finished with deployment
 write-host " $package_withoutPath" -nonewline;
 while($wspID.JobExists -eq $true) {
  write-host '.' -nonewline;
  sleep -Seconds:1;
 }
 write-host '';
 Update-SPSolution -Identity $package_withoutPath -LiteralPath $package -GACDeployment;
 
}

write-host "Finishing:"
foreach ($package in $packages) {
 $package_withoutPath = $package.split('\')[-1]
 write-host " $package_withoutPath" -nonewline;
 $wspID = Get-SPSolution -Identity $package_withoutPath;
 while($wspID.JobExists -eq $true) {
  write-host '.' -nonewline;
  sleep -Seconds:1;
 }
 write-host '';
}

The script loops over all packages found from a certain directory and updates them using the Update-SPSolution cmdlet.

Once all packages are added to the update queue, it waits for all deployment jobs to finish before returning the prompt.