mandag den 7. oktober 2013

SPBG High availability with SharePoint 2013

I hold a speech at the SPBG network seminar's, the topic was (High availability with SharePoint 2013) and yes, still using the Microsoft "metro" style.

A great seminar with with a lot of good questions. 
SPBG, is known for it's high end SharePoint users and technicians, with a broad knowledge in alll topics.
Please wisit http://www.spbg.dk

 The slides from the seminar is shown here and your all welcome to leave some comment.

Slides

torsdag den 6. juni 2013

jBoye seminar in London

Yesterday I hold a speech at the one of jBoye network seminar's in London, the topic (High availability with SharePoint 2013) and yes, still using the Microsoft metro style.

A great seminar with with a great view over London city. I wish my office hade this view.
Big thanks to Lau, who facilitated the meeting and to jBoye for arranging the seminar. Please visit http://www.jboye.com

 The slides from the seminar is shown here and your all welcome to leave some comment.
(Please mind that all Saxo Bank specific slides have been removed)

Slides

onsdag den 10. april 2013

Disable all Health analyzer rules in SharePoint 2013


As in SharePoint 2010 we also in SharePoint 2013 have a lot of jobs running and analyzing the overall health of our server.  
All those rules are really nice, but in some cases you don’t need them. 
Example: 
  • If you know that you are running with databases over the limit and you are okay with that. 
  • You are running with only one service account, and is okay with that.
  • Your running whit a smaller page file than your physical RAM  (Quit a big file if you have 48Gb)

They all have in common that you as an admin made choices, and as we all know admins never make bad decisions. So instead of mannerly disable rules one at the time, you can just disable all and enable the ones you need.

To disable all rules just run the script below, this will disable all rules. To include the SharePoint SnapIn read this post  

If you like, this can be combined with a xml file so you can disable rules based on this as well. See this post to get inspiration. I would recommend using this if your maintaining a large organisation with a lot of environments.

PowerShell Script:
------------------------------
function main
{
$healthList = [Microsoft.SharePoint.Administration.Health.SPHealthRulesList]::Local.Items
 foreach ($Listitem in $healthList)
 {
  Write-Host -ForegroundColor Green $listitem.Id ": " -NoNewline
  if ($Listitem["HealthRuleCheckEnabled"] -ne $false)
  {
   Write-Host -ForegroundColor Magenta "Disable job"
   $Listitem["HealthRuleCheckEnabled"] = $false
   $Listitem.Update()
  }
  else
  {
   Write-Host -ForegroundColor White Done -BackgroundColor Black
  }
 }
}

Have fun with PowerShell 


tirsdag den 12. marts 2013

Sharepoint Document cheked out to

I wass asked to make a blog on an topic that was related to the checked out to <none> problem.
When SharePoint gets a deadlock in relation to Check-In/Check-Out situation it is due to the state of the CheckOutUserID field in the AllDocs table.

This field is set to -1, which by SharePoint is interpreted as <none>

To fix the page and thus be able to check-in or -out the page the CheckOutUserID must be replaced by an existing UserID from that particular Site Collection/Web Application.

The below SQL script does that, however it is important, that one item exist in the list in addition to the broken one, as the ID used in the script below, will be taken from the first item having an ID different from -1.
Alternative Microsoft advice to use the ID "58"

Generic script below, only the Database name is needed prior to running this.

USE [Portal_XXX_content]
GO
BEGIN TRY
BEGIN TRANSACTION
-- Check if any documents checked out with an invalid status
IF (SELECT COUNT(*)
FROM AllDocs (NOLOCK)
WHERE CheckoutUserId = -1) <= 0
BEGIN
PRINT 'INFO: No document checked out with invalid user id (-1)'
END
ELSE
BEGIN
-- Check if any checked out documents available
IF (SELECT COUNT(*)
FROM AllDocs(NOLOCK)
WHERE CheckoutUserId IS NOT NULL
AND CheckoutUserId > -1) <= 0
BEGIN
PRINT 'ERROR: Nothing checked out so can''t find a valid user ID'
END
ELSE
BEGIN
-- Show documents that has invalid user id
SELECT *
  FROM AllDocs(NOLOCK)
  WHERE CheckoutUserId = -1
  --Updating sharepoint field [checkoutUserId] to a value different from -1
  UPDATE [AllDocs]
  SET CheckoutUserId = (SELECT TOPCheckoutUserId
                        FROM [AllDocs] (NOLOCK)
                        WHERE CheckoutUserId > -1)
WHERE CheckoutUserId = -1


SELECT *
  FROM AllUserData (NOLOCK)
  WHERE tp_CheckoutUserId = -1
  --Updating sharepoint field [tp_CheckoutUserId] to a value different from -1
  UPDATE [AllUserData]
  SET tp_CheckoutUserId = (SELECT TOP 1 CheckoutUserId
                           FROM [AllDocs] (NOLOCK)
                           WHERE CheckoutUserId > -1)
  WHERE tp_CheckoutUserId = -1
END
END
--Finish SharePoint update
PRINT 'The operation completed successfully.'
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
BEGIN
ROLLBACK TRANSACTION
END
DECLARE @ErrorInfo NVARCHAR(4000)
SELECT @ErrorInfo = ERROR_MESSAGE()
RAISERROR(@ErrorInfo, 16, 1)
END CATCH

This Solution is supported by Microsoft!

mandag den 4. marts 2013

SharePoint 2013 on Azure



So this blog post is about Windows new Azure platform. And will not have any technical contend. But take it as a fun story on me trying to figure out the price for a server on Windows Azure.
   
I as a Microsoft Bizspark Partner was looking for an easy way to set up a new SharePoint 2013 installation on Azure. Just to start a POC on hosting SharePoint 2013 server. So i went to the portal administration panel to create my first windows machine, so I could get started.

My first concern was with the size, I should at least start with the minimums requirements for SharePoint 2013, since I need to present this solution to some customers and need to show that my solution is running fast and problem free. And also not get in to a discussion about my solution is running on at testing environment and it of course would be much faster for the customer. So to find out how big my installation needed to be I went to Microsoft to find the minimums requirements, just to discover that its good sense and fully lives up to my expatiation. So for the smallest installation I need 4 CPU and 8GB RAM, this should be no problem. (I would strongly recommend a larger server)
http://technet.microsoft.com/en-us/library/cc262485.aspx

As a Bizspark Partner I have some benefit regarding Azure as I can use some servers for free so I can get up and running before I have to pay for the services I need. And trust me I have no problem with paying for a service. So I went and signed up for Azure to get started. I thought to myself this is no problem, Microsoft have this under control so it is just for me to start. And my expectation was correct, under offers I found a link and with no problem I was up and running. This process got me smiling. 

So to set up A virtual machine on Azure just go to the administration portal click the big and easy to find plus sign and pick Virtual machines (This of course demand that you sign up for the review program first). So I thought to myself. Microsoft wants all to use SharePoint so they will make this easy for me. I will just have to pick an image and off I go right.

But I was soon to get a lot wiser. First up to choose the Image, just to find that I can choose a SQL image, a windows image even a Linux image, but not a SharePoint image? So I figured out that they properly haven made this one jet, so I will just need to create this myself. So I picked a clean windows 2012 server. And then I needed to choose my Virtual machine size. And then I got a little confused. I could choose from the following sizes.


Okay not the biggest machines in the world. I  can as a bizspark partner choose extra small or small. So to have the minimums demand in the back of my head, I found that I needed the extra large server to install a single instance of SharePoint 2013. (BTW why can have a server with 768MB of RAM, that's not even enough to run a decent IIS).
So looking at the largest instance I can start using being the small server having 1 CPU and 1.75BG RAM it would be a little hard to get something installed. So okay I thought, to get something up and running I need to pay for my service.

So to make a simple calculation on what I need to pay, for my minimum installation. I went to the calculation site to look at some numbers. For a single SharePoint installation with everything on the same box I need an Extra Large server, since the Large server with 4 CPU’s only have 7GB RAM. Remembering that the minimum RAM I need is 8GB.

After finding out that I needed an Extra Large server, I wanted to figure out what my monthly bill would be. I navigated to the calculator and found out that I had to pay. $460,80 per month for a single virtual server to run SharePoint 2013. (I know that I should use Office 365 for Office installation, and with good sense.) But I wanted to have full control over my installation and did not want to invest in hardware.

Azure is a good and fast system especial if you are using the "websites, databases or any other service", but in my sense it's not really mature for a windows installation. Except if you want to pay some really heavy prices. For my startup installation, I would need at least two severs one for SharePoint and one for SQL. So the price would be $921 on a monthly base. That’s a really heavy price to have as a startup.

So what is the key learning’s.

Azure is a really good alternative to buying servers yourself, and get them hosted. But I think the price is a little high for the machines you need. In my case I would have to spend almost $11.000 per year for two servers. Can I do this better? Well this depend on how good price I can get in a hosting company like Rackspace. I can get a decent server for less than $2.500 that matches the demands for running SharePoint and SQ. So I just need to find a place in the country to store my servers for about $5.000 a year. Well maybe it’s okay to pay a little more be-course my servers will hopeful work for more than one year.

So what will I do. Am not sure, I might call up Microsoft and ask if they can raise the number of RAM in there large server, this way it will support most of the applications for a little less on monthly base.
Else I will go and figure out on how to use O365 and SharePoint 2013.

torsdag den 28. februar 2013

Error on UserProfileManager and a funny SiteSubscriptionId


So I was struggling a little bit with an old PowerShell script to import pictures to the user profiles on our Intranet. The script was not working and I need to figure out what went wrong.
So the script is well documented on various forums, so that should be no big deal in getting this to work. So I went head first, and in to the pool I went.

So the script looks like this.
$site = Get-SPSite $mySiteUrl
$context = Get-SPServiceContext $site
$profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)

So the first part was easy, just getting the “mysite” URL, Next part to get the mysite service context. Now again quit easy. But then I had to get the profile manager. Then some problems came up.
So when trying to get the profile manager I got this error when running the commands manual.

New-Object : Exception calling ".ctor" with "1" argument(s): "Object reference not set to an instance of an object.” At line:1 char:29
+ $profileManager = New-Object <<<< Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
    + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodInvocationException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

So this had to be the problem to my script.
After some quick test I found my context hade a funny SiteSubscriptionId

SiteSubscriptionId
------------------
00000000-0000-0000-0000-000000000000

So I found that the SiteSubscriptionId will always be a blank Guid unless you have multi-tenancy enabled in the environment, so the problem should be found elsewhere.
I my case I found out that the user running the script was net in the administrators group of the service provider, so adding the user running the script to the group fixed the problem.

Go to Central Administration => Application Management => Manage Service Applications 
Highlight the row “User Profile Service Application”

Click the administrators in the ribbon and add the correct user.
Click the Permissions in the ribbon and add the correct user


onsdag den 27. februar 2013

Speech at jBoye

Today I hold a speech at the one of jBoye network seminar's, on the topic (High availability with SharePoint 2013). A fun presentation as this was my first try on using the Microsoft metro style.

For the ones that know Danish will be able to read the slides. but your all welcome to leave a comment.
(Please mind that all Saxo Bank specific slides have been removed)

Slides

onsdag den 20. februar 2013

Adding SharePoint PowerShell snapins


Over time I have seen a lot of ways to add the SharePoint snapins. So I decided that I would share my point of view on this.

So a lot of post on the internet is showing various ways to do this, by as the structure fascist I am, I like to keep things organized. So I always put my code in functions.

Why?

Well first it gives you a nice overview of the code, Always put your main code in a main function. This way it’s always on the top of your script. Second. By adding all your code in functions you can call the reuse then over and over again in your script.

It’s also a good idea to let your script tell you where in the process it is. This gives you a nice overview over watt you script is doing

So how do I add the snapin.

function snapin
{
  $spSnapin = Get-PSSnapin | where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}        
  if($spSnapin -eq $null)
  {
    Add-PSSnapin Microsoft.SharePoint.PowerShell
    Write-Host -ForegroundColor "Green" -Object "SharePoint PowerShell Snapin loaded"
  }
  else        
  {  
     Write-Host -ForegroundColor "Gray" -Object "SharePoint PowerShell Snapin already loaded"
  }
}
  
So after adding this function I call this function just before I call the main function. My structure will always look like this.

function
main
function snapin

snapin
main
# end of script

onsdag den 13. februar 2013

Adding December 2012 CU to the Codeplex AutoSPInstaller


After struggling with the slipstreaming problem that Microsoft has introduced after June 2012 CU. I decided to embed this update function to the script itself. This also gives the flexibility to add future updates to the script without using the slipstream functionality.

The function is quit strait forward, just add the unattended install line to a function and call this function after the language pack install. You need to make a folder called "Hotfixes" inside the SharePoint bits folder, and place the update there.

For more information on the AutoSPInstaller from codeplex follow this link.
http://autospinstaller.codeplex.com/   

Here is the function to add

#region Install CU updates
# ===================================================================================
# Func: Install SharePoint CU's
# Desc: Installs the SharePoint collumutive update in unattended mode
# ===================================================================================
function InstallCu()
{
  if(!(test-path -path $SPbits\Hotfixes)){Write-Host "You do not have an hotfix folder"; return}
  $Media = Get-ChildItem $SPbits\Hotfixes | where {$_.Extension -eq ".exe"} | sort-object $_.Name
      
  if($Media -eq $null){write-host "There is now (Cu).exe files in the Hotfix folder"; return }
    foreach($InstallationFile in $Media)
       Write-Host "Installing:" $InstallationFile.Name
       $InstallStart = Get-Date
       try
       {
         . $SPbits\Hotfixes\$InstallationFile /passive /log:$CurrentPath\Logs\$InstallationFile.Name.txt | out-null
       }
       catch
       {
         Throw "- Installation of CU failed"
       }
  }
  Write-host " The installation of CU completed"
}
#endregion

Notes:
More info on using the slipstreaming read this post made by Todd.

fredag den 8. februar 2013

#ESPC2013


I went to the conference for some inspiration and to hear a lot of great community MVP’s talk about all the new stuff in SharePoint 2013.

I will post some more comments and lessons learned later.

tirsdag den 15. januar 2013

How to create a emergincy website for mulible DNS's using Powershell

Okay, There is a lot of ways to ad a IIS site using Powershell so this is defently not the ultimate guide to set it up.
I will in this guide not use the IIS powershell snapin. This is becource this snapin dos not come out of the box when you nstall IIS7 (windows 2008 or 2008R2).
So how to create a script, that create a website.

Well the first thing we need to do is to make a folder to hold our website. This would nomaly be in the Inetpub folder, but it can also be placed in a more decired path.

The powershell command for creating a folder in powershell where $FPath is the folder path.
New-Item -Path $FPath -type Directory

To find out if the parth allready exists use this line, The command return $true or $false.
$FolderPath = Exists-Dir $FPath

Togetter it could look like this
$FolderPath = Exists-Dir $FPath
if ($FolderPath -ne $true){ New-Item -Path $FPath -type Directory}

So now that we have created a folder, we can move on to create a application pool in IIS7. To create this web application we need to import the webapplication modules to modify IIS objects. If you have the IIS snapin installed the server don't import this sanpin. To import the module add this to the first line in the script.
import-module WebAdministration

This will add some new methods to your powershell console. for more information on these please visit:

After we have these methods awalieble we can start manipulating the IIS. To create a weapplication we will use this command where $AppPoolName is the name for the application pool.
New-WebAppPool -Name $AppPoolName

To check if this application pool allready exists, we can use the check status. this will retur a nice ugly error if its not there :o) (Okay I know its a cruel way) but by adding the erroraction silentcontinue we dont have to see it.
Get-WebAppPoolState -Name $AppPoolName
                    
-ErrorAction SilentlyContinue

So to put this together we get this.
$webapp = Get-WebAppPoolState -Name $AppPoolName
                             
-ErrorAction SilentlyContinue
if (-not $webapp)
{
     New-WebAppPool -Name $AppPoolName
}

So now we are ready to make the website. This can be made by using this command.
New-Website -ApplicationPool $AppPoolName
           
-Name $SiteName
            -HostHeader $SiteName
            -PhysicalPath
$FPath
            -Port
80

And to check if the site exists use this command
Get-Website | Where {$_.Name -eq $SiteName};

Bringing this together and creating a site could look like this.
$website = Get-Website | Where {$_.Name -eq $SiteName};
if (-not $website)
{
   New-Website -ApplicationPool $AppPoolName
              
-Name $SiteName
              
-HostHeader $SiteName
              
-PhysicalPath $FPath
               -Port 80
}

So now that we have created the site, its time to add bindings. For multible bindings I have created a xml file, holding all the bindings. Please note that the simple module give no method to check for a binding. This is why this script delete all bindings and adds them again.
Note: You need to ad the primary binding (ex. www.yoursite.com) in the bottom of the xml file.

Here is the compleate function to add bindings.

function AddBindings
{
   $BindingsXMLFile = $dp0 + "\Bindings.xml"
   [xml]$BindingsConfig = [xml](Get-Content $BindingsXMLFile)
   if (-not $BindingsConfig)
   {
      Write-Host "- Bindings configuration file does not exist."
      break 1
   }
   else
  {
      $SiteBindings = Get-WebBinding -Name $SiteName
      if ($SiteBindings)
      {
        foreach ($bind in $SiteBindings)
        {
         Remove-WebBinding -Name $SiteName
                          
-BindingInformation $bind.BindingInformation
        }
   }
     
   $BindingsEnabled = $BindingsConfig.SelectNodes("DeploymentConfig/Bindings/Binding") | where {$_.Enable  -ieq "True"}
   if ($BindingsEnabled)
   {
    foreach ($binding in $BindingsEnabled)
    {
     $BindingHostName = $binding.Hostname
     $BindingPort = $binding.Port
     New-WebBinding -Name $SiteName
                   
-HostHeader $BindingHostName
                    
-Port $BindingPort
                    -ErrorAction
SilentlyContinue
   }
  }
 }
}

Here is an example of the structure in the xml file:
<?xml version="1.0" encoding="utf-8"?>
<DeploymentConfig>
  <Bindings Name="Bindings">
         <Binding Enable="true" Hostname="www.yoursite.com" Port="80"></Binding>
  </Bindings>
</DeploymentConfig>