Friday, January 24, 2014

Backup SharePoint 2013

After building 4 farms, I deployed powershell to backup each farm (full farm backup), I quickly ran out of disk space for backups (250GB) as the backup-spfarm command-let will not overwrite a pre-existing farm backup (spbr0000 directory), therefore, I only had enough disk to retain one backup of each environment.

Enter SharePoint Backup Augmentation Cmdlets from CodePlex (http://sharepointbac.codeplex.com).

SharePointBAC makes it possible to groom backup sets, archive backups, and more. While the version on codeplex supports 2010, I was able to obtain the 2013 source files from Trevor Seward, MVP.

Once the solution is added and deployed, the following 5 new command-lets become available:

  1. Get-SPBackupCatalog: Retrieves an SPBackupCatalog object for a selected backup location and exposes properties of the catalog
  2. Export-SPBackupCatalog: Generates an export/archive of one or backup sets that is compressed as a zip file by default
  3. Remove-SPBackupCatalog: Performs grooming (i.e., cleaning out old backups) on a backup catalog and its associated backup sets
  4. Send-SPBackupStatus: E-mails a summary of the last backup operation to selected recipients using the farm's outbound e-mail configuration
  5. Set-SPBackupCatalog: Updates properties on an SPBackupCatalog object (more specifically, its underlying spbrtoc.xml catalog file)
        Here is a sample .ps1 script utilizing SharePointBAC solution which will backup farm and retain only the most recent backup:

        Add-PSSnapin Microsoft.SharePoint.PowerShell
        $cat = Get-SPBackupCatalog \\server\Share
        Backup-SPFarm -Directory \\server\Share -BackupMethod Full
        $cat.Refresh()
        $cat | Remove-SPBackupCatalog -RetainCount 1 -Confirm:$false
        $cat.Refresh()
        $cat | Send-SPBackupStatus -Recipients "admin@domain.com"

        Tuesday, January 14, 2014

        Open PDF's with Adobe instead of Office Web Apps

        SharePoint / PDF Default Application

        Adobe PDF files can be opened with either Office Web Apps (browser) or one of the Adobe pdf viewers. Powershell will assist.

        Change default PDF Application from Office Web Apps to Adobe Viewer

        To adjust the binding so that smartphones won’t try to view PDFs in Word Web App (but other devices will continue to), enter the following command and then press Enter:
        Get-SPWopiBinding -Action "MobileView" -Application "WordPDF" | Remove-SPWopiBinding -Confirm:$false
        To remove the binding altogether so that PDFs open in the default PDF viewer on all devices, use the following:
        Get-SPWOPIBinding –Application "WordPDF" | Remove-SPWOPIBinding -Confirm:$false

        Change Default PDF Application from Adobe to OWA  

        Get-SPWOPIBinding –Application "WordPDF" | Remove-SPWOPIBinding -Confirm:$false
        New-SPWOPIBinding –ServerName "<OWAServerName(ex: server.corp.Contoso.com)>" –Application "WordPDF" -AllowHTTP

        Source:


        Monday, January 13, 2014

        Clear SharePoint Cache Powershell

        Ever need to clear your farms' configuration cache? Kind of a pain huh? Having to hit each server, deleting all those xml files...resetting the config on all of them....well, powershell to the rescue! 

        While working an issue with Jeff Tindilier from MS premier support, he sent me the following powershell script which saves soooo much time!

        It will discover all servers in your farm, stop sptimer on each, delete the xml's, reset config file, start sptimer, on all servers!

        # Clear the SharePoint Timer Cache
        #
        # 2009 Mickey Kamp Parbst Jervin (mickeyjervin.wordpress.com)
        # 2011 Adapted by Nick Hobbs (nickhobbs.wordpress.com) to work with SharePoint 2010,
        # display more progress information, restart all timer services in the farm,
        # and make reusable functions.
        # 2012 Adapted by Dwayne Selsig (www.dwayneselsig.eu) to also work with SharePoint 2013.
        # Added loading of SharePoint Snapin for Powershell. Also this script only queries
        # the SharePoint servers.
        # Output program information
        Write-Host -foregroundcolor White ""
        Write-Host -foregroundcolor White "Clear SharePoint Timer Cache"
        #**************************************************************************************
        # Constants
        #**************************************************************************************
        Set-Variable timerServiceName -option Constant -value "SPTimerV4"
        Set-Variable timerServiceInstanceName -option Constant -value "Microsoft SharePoint Foundation Timer"
        #**************************************************************************************
        # Functions
        #**************************************************************************************
        #<summary>
        # Loads the SharePoint Powershell Snapin.
        #</summary>
        Function Load-SharePoint-Powershell
        {
        If ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
        {
            Write-Host -ForegroundColor White " - Loading SharePoint Powershell Snapin"
        Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction Stop
        }
        }
        #<summary>
        # Stops the SharePoint Timer Service on each server in the SharePoint Farm.
        #</summary>
        #<param name="$farm">The SharePoint farm object.</param>
        function StopSharePointTimerServicesInFarm($farm)
        {
        Write-Host ""
        # Iterate through each server in the farm, and each service in each server
        foreach($server in $farm)
        {
        foreach($instance in $server.ServiceInstances)
        {
        # If the server has the timer service then stop the service
        if($instance.TypeName -eq $timerServiceInstanceName)
        {
        [string]$serverName = $server.Name
        Write-Host -foregroundcolor DarkGray -NoNewline "Stop '$timerServiceName' service on server: "
        Write-Host -foregroundcolor Gray $serverName
        $service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$timerServiceName'"
        sc.exe \\$serverName stop $timerServiceName > $null
        # Wait until this service has actually stopped
        WaitForServiceState $serverName $timerServiceName "Stopped"
        break;
        }
        }
        }
        Write-Host ""
        }
        #<summary>
        # Waits for the service on the server to reach the required service state.
        # This can be used to wait for the "SharePoint 2010 Timer" service to stop or to start
        #</summary>
        #<param name="$serverName">The name of the server with the service to monitor.</param>
        #<param name="$serviceName">The name of the service to monitor.</param>
        #<param name="$serviceState">The service state to wait for, e.g. Stopped, or Running.</param>
        function WaitForServiceState([string]$serverName, [string]$serviceName, [string]$serviceState)
        {
        Write-Host -foregroundcolor DarkGray -NoNewLine "Waiting for service '$serviceName' to change state to $serviceState on server $serverName"
        do
        {
        Start-Sleep 1
        Write-Host -foregroundcolor DarkGray -NoNewLine "."
        $service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$serviceName'"
        }
        while ($service.State -ne $serviceState)
        Write-Host -foregroundcolor DarkGray -NoNewLine " Service is "
        Write-Host -foregroundcolor Gray $serviceState
        }
        #<summary>
        # Starts the SharePoint Timer Service on each server in the SharePoint Farm.
        #</summary>
        #<param name="$farm">The SharePoint farm object.</param>
        function StartSharePointTimerServicesInFarm($farm)
        {
        Write-Host ""
        # Iterate through each server in the farm, and each service in each server
        foreach($server in $farm)
        {
        foreach($instance in $server.ServiceInstances)
        {
        # If the server has the timer service then start the service
        if($instance.TypeName -eq $timerServiceInstanceName)
        {
        [string]$serverName = $server.Name
        Write-Host -foregroundcolor DarkGray -NoNewline "Start '$timerServiceName' service on server: "
        Write-Host -foregroundcolor Gray $serverName
        $service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$timerServiceName'"
        sc.exe \\$serverName start $timerServiceName > $null
        WaitForServiceState $serverName $timerServiceName "Running"
        break;
        }
        }
        }
        Write-Host ""
        }
        #<summary>
        # Removes all xml files recursive on an UNC path
        #</summary>
        #<param name="$farm">The SharePoint farm object.</param>
        function DeleteXmlFilesFromConfigCache($farm)
        {
        Write-Host ""
        Write-Host -foregroundcolor DarkGray "Delete xml files"
        [string] $path = ""
        # Iterate through each server in the farm, and each service in each server
        foreach($server in $farm)
        {
        foreach($instance in $server.ServiceInstances)
        {
        # If the server has the timer service delete the XML files from the config cache
        if($instance.TypeName -eq $timerServiceInstanceName)
        {
        [string]$serverName = $server.Name
        Write-Host -foregroundcolor DarkGray -NoNewline "Deleting xml files from config cache on server: "
        Write-Host -foregroundcolor Gray $serverName
        # Remove all xml files recursive on an UNC path
        $path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\*.xml"
        Remove-Item -path $path -Force
        break
        }
        }
        }
        Write-Host ""
        }
        #<summary>
        # Clears the SharePoint cache on an UNC path
        #</summary>
        #<param name="$farm">The SharePoint farm object.</param>
        function ClearTimerCache($farm)
        {
        Write-Host ""
        Write-Host -foregroundcolor DarkGray "Clear the cache"
        [string] $path = ""
        # Iterate through each server in the farm, and each service in each server
        foreach($server in $farm)
        {
        foreach($instance in $server.ServiceInstances)
        {
        # If the server has the timer service then force the cache settings to be refreshed
        if($instance.TypeName -eq $timerServiceInstanceName)
        {
        [string]$serverName = $server.Name
        Write-Host -foregroundcolor DarkGray -NoNewline "Clearing timer cache on server: "
        Write-Host -foregroundcolor Gray $serverName
        # Clear the cache on an UNC path
        # 1 = refresh all cache settings
        $path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\cache.ini"
        Set-Content -path $path -Value "1"
        break
        }
        }
        }
        Write-Host ""
        }
        #**************************************************************************************
        # Main script block
        #**************************************************************************************
        # Load SharePoint Powershell Snapin
        Load-SharePoint-Powershell
        # Get the local farm instance
        $farm = Get-SPServer | where {$_.Role -match "Application"}
        # Stop the SharePoint Timer Service on each server in the farm
        StopSharePointTimerServicesInFarm $farm
        # Delete all xml files from cache config folder on each server in the farm
        DeleteXmlFilesFromConfigCache $farm
        # Clear the timer cache on each server in the farm
        ClearTimerCache $farm
        # Start the SharePoint Timer Service on each server in the farm
        StartSharePointTimerServicesInFarm $farm

        Friday, January 3, 2014

        SharePoint 2013 Search Setup Powershell

        The following powershell will setup Search Application Topology via powershell...
        This is an example of a 4 server farm (2 wfe, 2 app):

        Specify the new servers you want to add search components to, start a search service instance (ssi) on these servers and create references to the search service instances

        $hostA = Get-SPEnterpriseSearchServiceInstance -Identity "<server>"
        $hostB = Get-SPEnterpriseSearchServiceInstance -Identity "<server>"
        $hostC = Get-SPEnterpriseSearchServiceInstance -Identity "<server>"
        $hostD = Get-SPEnterpriseSearchServiceInstance -Identity "<server>"

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

        Wait until all the search service instances are running. At the Windows PowerShell command prompt, type the following commands until the commands return the state "Online" for each of the search service instances

        Get-SPEnterpriseSearchServiceInstance -Identity $hostA
        Get-SPEnterpriseSearchServiceInstance -Identity $hostB
        Get-SPEnterpriseSearchServiceInstance -Identity $hostC
        Get-SPEnterpriseSearchServiceInstance -Identity $hostD

        Create a new search topology and a reference to the new search topology. At the Windows PowerShell command prompt, type the following command(s):

        $ssa = Get-SPEnterpriseSearchServiceApplication
        $newTopology = New-SPEnterpriseSearchTopology -SearchApplication $ssa

        Add all the search components to the new search topology. The following Windows PowerShell commands will create the search components of the new topology and assign them to the new servers. In this small enterprise search topology there is one index partition, index partition 0, to cater for a maximum of ten million items. This is indicated with the parameter -IndexPartition in the command New-SPEnterpriseSearchIndexComponent

        New-SPEnterpriseSearchAdminComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
        New-SPEnterpriseSearchAdminComponent -SearchTopology $newTopology -SearchServiceInstance $hostB

        New-SPEnterpriseSearchCrawlComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
        New-SPEnterpriseSearchCrawlComponent -SearchTopology $newTopology -SearchServiceInstance $hostB

        New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
        New-SPEnterpriseSearchContentProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostB

        New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostA
        New-SPEnterpriseSearchAnalyticsProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostB

        New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostC
        New-SPEnterpriseSearchQueryProcessingComponent -SearchTopology $newTopology -SearchServiceInstance $hostD

        New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostA -IndexPartition 0
        New-SPEnterpriseSearchIndexComponent -SearchTopology $newTopology -SearchServiceInstance $hostB -IndexPartition 0

        Activate the new search topology

        Set-SPEnterpriseSearchTopology -Identity $newTopology

        Verify that the new search topology is active

        Get-SPEnterpriseSearchTopology -SearchApplication $ssa

        Verify that all components of the new search topology are running correctly


        Get-SPEnterpriseSearchStatus -SearchApplication $ssa -Text







        Disable Loop-back Check Powershell

        Run the following from PowerShell as administrator on each server:

        $regKeyPath = "HKLM:\System\CurrentControlSet\Control\Lsa"
        $key = "DisableLoopbackCheck"
        New-ItemProperty -Path $regKeyPath -Name $key -Value "1" -PropertyType dword

        Thursday, January 2, 2014

        Managing SharePoint Security with Dynamic Active Directory Security Groups

        Have you ever needed to create security groups based upon Department, Physical Location (1st floor, 2nd floor, east/west, etc) or any other criteria whose values exist as an AD profile attribute? For example, let's say we have user A who works in Accounting but is now transferring to Marketing. This change in responsibilities probably means user A no longer requires access to shares/data/sites/etc. accountants utilize, however, user A will now require access to Marketing Resources.

        Active Directory Groups are as dynamic as their members: they need to change as users switch responsibilities, roles and locations. The problem is that distribution lists and security groups are often manually maintained by the Exchange or Active Directory administrator. This type of access update can be very tedious and time-consuming. Dynamic AD Groups to the rescue!

        Dynamically maintain groups based on rules that are applied to your directory data. When user information changes, GroupID Automate automatically updates the appropriate distribution lists and security groups. Your groups will never be out of date again.

        Groups are generally managed one of three ways: negligently, IT-centric, or user-centric. This means they either don’t manage groups, have a highly paid administrator manually manage groups, or have end users manage groups. All of these solutions have a cost that far outweighs creating dynamic groups through PowerShell.

        By automating these Active Directory groups, you can ensure they will always be accurate. Increase productivity by giving employees access to the right systems and information immediately upon hiring or promotion. Increase security by granting access to only the systems you want and denying access immediately upon any change in status. Use Active Directory’s group structure to your benefit with GroupID Automate.

        Luckily, there are a few people who have strung together the PS cmdlets needed to pull this off.
        Take a look at Baldwin D's post here:  http://baldwin-ps.blogspot.com/2013/05/dynamic-ad-security-groups.html