Sunday, January 27, 2013

.Clone() or –Clone, that is the question…

When you are working with Search in SharePoint 2013 you no longer have the luxury of using the GUI to modify search topology. Now we have to directly modify a topology using a clone in PowerShell.

At a high level we have the:
  • Search Service Application
  • Search Topology
  • Search Instance on each Server in the search topology
We also have the following components:
  • Admin
  • Crawler
  • Content Processing
  • Analytics Processing
  • Query Processing
  • Index
When we want to change the topology of a search service application such as:
  • Change the index location on the index component
  • Add a index replica on another server in the farm
  • Add additional components to other servers in the farm
  • Remove components
We have to first clone the active topology, make our changes to the clone and then activate the clone. However, there is a difference between using the Clone() method on the SSA and using the New-SPEnterpriseSearchToplogy –Clone switch. One gives your newly cloned components ID’s where the other does not.
When we create a clone by doing the following:
$ssa = get-spenterprisesearchserviceapplication
$clone = $ssa.ActiveTopology.Clone()

We get this when we look at the topology:
image

And we get this when we look at the components in the cloned topology: (Get-SPEnterpriseSearchComponent  -SearchTopology $clone)
image

As you can see above, all of our components have blank IDs. If we wanted to remove a component from the topology how would we identify which component to remove? The Remove-SPEnterpriseSearchComponent –Identity switch wants an ID of the component to remove so we need to get a valid ID in order for this work.
Using the above method we can easily add additional components to the topology but we cannot remove.
Solution
After you capture your SSA run the following command:
$active = Get-SPEnterpriseSearchTopology -Active -SearchApplication $ssa
$Clone = New-SPEnterpriseSearchTopology -SearchApplication $ssa -Clone -SearchTopology $active
Now we get this: Smile
image

Now we have an ID field that we can use to easily remove a component from the topology.

{Kam}

Friday, January 18, 2013

Enhanced Self Service Site Creation

SO, self service site creation in SharePoint. Always a hot topic with the "Power User" in Company A and scares others in Company B. After all, we put a lot of work into building a SharePoint architecture that will help prevent and prohibit site sprawl. That, along with a recent deliverable, got me thinking.... Why not develop an easier way to automate this process and integrate an approval?

Problem:
We need to empower our business users/owners to create their own site collections. Or we may need to simply automate the creation of webs or site collections. We rely on the user to enter the correct URL to adhere to naming conventions, correct templates, security, etc.

Solution:
The solution is two-fold, and you guessed it.....it involves PowerShell.
  1. Create a new list (or site with a list) called Auto/Self Service Site Creation
  2. Have that list contain a few integral pieces of information such as:
    • Title (Single Line Text)
    • Owner (People Picker)
    • Second Owner (People Picker)
    • Abbreviation (Used for Site URL)
    • Status (For workflow)
    • Email
  3. Now attach a workflow to this list that captures approval for each submitted site request.
  4. Nightly run a PoSH script that will check that list for items with the status of Approved and automatically create the site using the SPFarm account or other privileged user. It can also send an email to the user notifying them that their site is ready!

This allows our users to submit site requests but ensures they are approved and reviewed. Hence, limiting site sprawl and maintaining our SharePoint IA where needed.

Tuesday, January 1, 2013

Creating groups and users in PowerShell

I recently had a SharePoint migration where they were using users directly in the SharePoint default Visitors, Members, Owners groups. Because this gets hard to manage we opted to get AD groups setup and added to SharePoint groups for easier management. Because this was a lot of groups we used powershell to create all of the groups and add the necessary members.

 

#Script

function Write-ToLog($msg)
{
    $logDate = Get-Date -UFormat "%m%d%Y"
    $path = "AD_NewGroup_Log-" + $logDate + ".log"

    $msg | Out-File $path -append
}

function Write-ToScreen($msg)
{
    #$newLine = "`n"

    $currentTime = Get-Date -UFormat "%H:%M:%S"
    $msg = $currentTime + " :: INF :: " + $msg + $newLine

    Write-ToLog($msg)
    Write-Host -ForegroundColor Yellow $msg
}

function Write-ActionToScreen($msg)
{
    #$newLine = "`n"

    $currentTime = Get-Date -UFormat "%H:%M:%S"
    $msg = $currentTime + " :: ACT :: " + $msg + $newLine

    Write-ToLog($msg)
    Write-Host -ForegroundColor Green $msg
}


# Import AD module
Write-ActionToScreen "Importing Active Directory module"
Import-Module ActiveDirectory

# Retrieve list of groups to be created from CSV file
Write-ActionToScreen "Importing CSV file"
$groups = Import-Csv .\Groups_Members.csv

# Designate which OU these groups will be created in
Write-ActionToScreen "Settting OU location"
$ou = "OU=SharePoint,DC=Lab,DC=Local"

# Check to see if OU exists and create groups, add members
Write-ActionToScreen "Testing OU path and starting group creation"
if ((Test-Path AD:\$ou) -eq $true)
{
    Write-ToScreen "Verified that OU DOES exist"
    foreach ($group in $groups)
    {
        Write-ActionToScreen "Creating new group $($group.GroupName)"
        New-ADGroup -Name $group.GroupName -SamAccountName ($group.GroupName).trim() -DisplayName $group.GroupName -Description $group.Description -GroupCategory Security -GroupScope Global -Path $ou
        Write-ToScreen "Finished creating group $($group.GroupName)"
        Write-ActionToScreen "Getting group members"
        $users = @(($group.Members).split(";"))
        foreach ($u in $users)
        {
            Write-ActionToScreen "Adding $u to $($group.GroupName)"
            Add-ADGroupMember -Identity $group.GroupName -Members $u
            Write-ToScreen "Finished adding $u to group $($group.GroupName)"
        }
    }
}
else
{
    Write-ToScreen "OU does not exist in AD tree. Please make sure your OU variable is pointing a to a valid OU"
}

 

 

#CSV

Here is a sample import file that was used. Users are separated by ‘;’ .

 

GroupName,Description,Members
SP_SiteName_Owners,SharePoint Security Group,tuser1;tuser2
SP_SiteName_Contrib,SharePoint Security Group,tuser1;tuser2

Happy New Year!

Welcome 2013! I hope everyone had a great 2012 and have set your goals for 2013Smile My first goal of 2013 was to get a SharePoint Search Service Application configured. No matter what I did I could not get it provision correctly through PowerShell or the GUI. I blew away the SA many times and tried again. I tried cloning the topology and activating it but it all was giving errors that the admin component could not connect to the server. After some digging in the registry I found a key that pointed to an old admin database. After I updated the keys it worked again.

The following location is where I found the stale/orphaned records.

 

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\15.0\Search\Applications\GUID\ResourceManager

Site logos

Have you ever been working across 10,20,30,100+ sites and needed to to update the logo location for all of them? Below you will find a script that can be used to update every logo for every site collection and web(sub-site).

Similarly, you can use another script to update other object properties. The best way to do this would be to deploy a custom solution and have the solution do it for you. But in lieu of that, here you go.

# Script

$SiteCollections = get-spsite -limit all

foreach ($site in $SiteCollections)
{
    $MainWeb = Get-SPWeb -Identity $Site.Url
    $MainWeb.SiteLogoUrl = “/SiteAssets/logo.png"
    $MainWeb.SiteLogoDescription = “Company Logo"
    $MainWeb.Update()
    Write-Host "Settings image for $mainWeb"
    $MainWeb.Dispose()
        foreach ($web in $site.AllWebs)
        {
            $Web.SiteLogoUrl = “/SiteAssets/logo.png"
            $Web.SiteLogoDescription = “Company Logo"
            $Web.Update()
            Write-Host "Setting image for $web"
        }
}

 

{Kam}