Friday, November 15, 2013

How To Export WSP SharePoint Solution from Solution Store with PowerShell

This is a simple script that can be usefull during migration of SharePoint from 2010 version to 2013 version if you are using ContentDB upgrade model.

This ps1 extract all wsp solution deployed to a SharePoint Farm to a specific folder on file system.

$destFolderName = "D:\Tmp\ExportedWSP"
foreach ($solution in Get-SPSolution)
{
    $id = $Solution.SolutionID
    $title = $Solution.Name
    $filename = $Solution.SolutionFile.Name

    try {
        $solution.SolutionFile.SaveAs("$destFolderName\$filename")
        Write-Host " – done" -foreground green
    }
    catch
    {
        Write-Host " – error : $_" -foreground red
    }
}

Run it on SharePoint Management Shell with Farm Admin permission.

Tuesday, November 5, 2013

Create Enterprise Search Service Application in SharePoint 2013 with Powershell

This note have the intent to give you a shortcut for a typical Enterprise Search Topology in SharePoint 2013 Small Farm.

This is basically a PowerShell script that help you to create from scrach an Enterprise Search Service Application (and its related Proxy) with following Topology:

Here's the script:

$PSSnapin = Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
#SET THIS PARAMETERS TO MEET YOUR Environement
$hostA = Get-SPEnterpriseSearchServiceInstance -Identity "applicationserver"
$hostB = Get-SPEnterpriseSearchServiceInstance -Identity "frontendserver1"
$hostC = Get-SPEnterpriseSearchServiceInstance -Identity "frontendserver2"

$serviceAppName = "Enterprise Search Service Application"
$dbServer = "SQLSERVERALIAS"
$searchServer = $serverName
$searchDBName = "SP2013_EnterpriseSearch"
$svcAppPoolName = "SharePoint Web Services System"
$indexLocation = "E:\SPSData\Index"
$searchCred = "DomainSearchServiceAccount"
$searchPwd = ConvertTo-SecureString -String 'DomainSearchServicePassword' -AsPlainText -Force

#END OF PARAMETER SECTION

Start-SPEnterpriseSearchServiceInstance -Identity $hostA
Start-SPEnterpriseSearchServiceInstance -Identity $hostB
Start-SPEnterpriseSearchServiceInstance -Identity $hostC


$hostA.DefaultIndexLocation = $indexLocation
$hostB.DefaultIndexLocation = $indexLocation
$hostC.DefaultIndexLocation = $indexLocation
 
#Wait for service OnLine on Every Host
$ss1 = Get-SPEnterpriseSearchServiceInstance -Identity $hostA
while ($ss1.Status -ne "Online")
{
    Start-Sleep 10
    $ss1 = Get-SPEnterpriseSearchServiceInstance -Identity $hostA
}
$ss1 = Get-SPEnterpriseSearchServiceInstance -Identity $hostB
while ($ss1.Status -ne "Online")
{
    Start-Sleep 10
    $ss1 = Get-SPEnterpriseSearchServiceInstance -Identity $hostB
}
$ss1 = Get-SPEnterpriseSearchServiceInstance -Identity $hostC
while ($ss1.Status -ne "Online")
{
    Start-Sleep 10
    $ss1 = Get-SPEnterpriseSearchServiceInstance -Identity $hostC
}


$cred = Get-Credential $searchCred
$searchSvcAccount = Get-SPManagedAccount $cred.UserName -ErrorAction SilentlyContinue

if ($searchSvcAccount -eq $null)
{
    $searchSvcAccount = New-SPManagedAccount $cred
}

$searchSvc = Get-SPEnterpriseSearchServiceInstance -Local
if ($searchSvc -eq $null)
{
    throw "Unable to retrieve search service"
}

#Set Search Service parameter
$searchSvc | Set-SPEnterpriseSearchServiceInstance

if ($searchSvc.Status -ne "Online")
{
$searchSvc | Start-SPServiceInstance
}

$svc = Get-SPEnterpriseSearchService
Set-SPEnterpriseSearchService `
      -Identity $svc `
      -ServiceAccount $searchSvcAccount.UserName `
      -ServicePassword $searchPwd `
      -ContactEmail "
contactemail@domain.com" `
      -ConnectionTimeout "60" `
      -AcknowledgementTimeout "60" `
      -ProxyType "Default" `
      -PerformanceLevel "PartlyReduced"
  
  
$searchApp = Get-SPEnterpriseSearchServiceApplication $serviceAppName -ErrorAction SilentlyContinue
if ($searchApp -eq $null)
{
    $saAppPool = Get-SPServiceApplicationPool | where { $_.Name -eq $svcAppPoolName }
    $searchApp = New-SPEnterpriseSearchServiceApplication -Name $serviceAppName -ApplicationPool $saAppPool -DatabaseServer $dbServer -DatabaseName $searchDBName
}

#Declare New Topology
$ssa = Get-SPEnterpriseSearchServiceApplication
$newTopology = New-SPEnterpriseSearchTopology -SearchApplication $ssa

#Define all required components
New-SPEnterpriseSearchAdminComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
New-SPEnterpriseSearchCrawlComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostB -IndexPartition 0
New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostC -IndexPartition 0
New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostB
New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostC

#Apply New Topology
Set-SPEnterpriseSearchTopology -Identity $newTopology

#Create Proyx for Service Application
$searchProxy = New-SPEnterpriseSearchServiceApplicationProxy -Name "$serviceAppName Proxy" -SearchApplication $searchApp


Or you can download the ps1 script here.

Update SharePoint 2013 to August 2013 CU

If you are planning to upgrade your SharePoint 2013 Farm to August 2013 Cumulative Update, consider following consideration:

1 - Go to this link to Request download for the CU
1.a - For SharePoint foundation the link is this one kb2817517.
1.b - For SharePoint Server the link is this one kb2817616.

2 - You already heve installed March 2013 SharePoint 2013 Public Update (PU)

3 - The update take a lot of time to complete. If you want to minimize this, read this interesting article "Why SharePoint 2013 Cumulative Update takes 5 hours to install?".

4 - After the update, you obviously need to run SharePoint Configuration Wizard. Using standard psconfigwiz.exe the update is performed in timer job. If you are experiencing issues using this approach, you can run psconfig.exe from command line with this parameters:

PSConfig.exe -cmd upgrade -inplace b2b -wait -force -cmd applicationcontent -install -cmd installfeatures

Note the -wait parameter that tell psconfig.exe to run the upgrade process not in the timerjob process, but in current process session.

The -force parameter tell psconfig.exe to ignore previous Upgrade Timer Job defined in configuration database.

In my case, running the upgrade in timerjob cause the upgrade process to be stucked on 10%.

Monday, November 4, 2013

Slow SharePoint Start Up - Disable CLR Check with PowerShell

If you are experiencing slow SharePoint Application Pool Start Up, probably what you need is to remove CLR Check for Assembly Signing.

I've found a very usefull PowerShell script from marvelous AutoSPInstaller (https://autospinstaller.codeplex.com/) that do it for you.

This function disable CLR Check from Windows Registry and from machine.config.

Here's the snippet:

Function DisableCRLCheck()
{
 Write-Host -ForegroundColor White " - Disabling Certificate Revocation List (CRL) check..."
 Write-Host -ForegroundColor White "  - Registry..."
 New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS -ErrorAction SilentlyContinue | Out-Null
 New-ItemProperty -Path "HKU:\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing" -Name State -PropertyType DWord -Value 146944 -Force | Out-Null
 New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing" -Name State -PropertyType DWord -Value 146944 -Force | Out-Null
 Write-Host -ForegroundColor White "  - Machine.config..."
 ForEach($bitsize in ("","64"))
 {
  # Added a check below for $xml because on Windows Server 2012 machines, the path to $xml doesn't exist until the .Net Framework is installed, so the steps below were failing
  $xml = [xml](Get-Content "$env:windir\Microsoft.NET\Framework$bitsize\v2.0.50727\CONFIG\Machine.config" -ErrorAction SilentlyContinue)
  if ($xml)
  {
   If (!$xml.DocumentElement.SelectSingleNode("runtime")) {
    $runtime = $xml.CreateElement("runtime")
    $xml.DocumentElement.AppendChild($runtime) | Out-Null
   }
   If (!$xml.DocumentElement.SelectSingleNode("runtime/generatePublisherEvidence")) {
    $gpe = $xml.CreateElement("generatePublisherEvidence")
    $xml.DocumentElement.SelectSingleNode("runtime").AppendChild($gpe) | Out-Null
   }
   $xml.DocumentElement.SelectSingleNode("runtime/generatePublisherEvidence").SetAttribute("enabled","false") | Out-Null
   $xml.Save("$env:windir\Microsoft.NET\Framework$bitsize\v2.0.50727\CONFIG\Machine.config")
  }
  else
  {
   if ($bitsize -eq "") {$bitsize = "32"}
   Write-Warning "$bitsize-bit machine.config not found - could not disable CRL check."
  }
 }
 Write-Host -ForegroundColor White " - Done."
}


Thanks again to autospinstaller for his wanderfull job.