• Automating Managed Password Change Using PowerShell

    Wanted to share a script I wrote a couple months ago for another PFE to create random passwords, log them to a text file and change a SharePoint managed account. 

    #Identify the account to change
    $Account = "contoso\svcSPExcel"
    $ManagedAccount = Get-SPManagedAccount $Account

    #Generate the Random Password
    $rand = New-Object System.Random
    #Generate a new 20 character password
    $pwd = ""
    1..20 | ForEach { $pwd = $pwd + [char]$rand.next(33,127) }

    #Set the Password as a secure string
    $securePassword = ConvertTo-SecureString -String $pwd -AsPlainText -Force

    #Log the Change prior to the change
    $Text = "SharePoint Managed Account Password Changed for: " + $Account + " to " + $pwd
    Add-Content c:\temp\PasswordChanges.log $Text
    #Reset the Password
    Set-SPManagedAccount -Identity $ManagedAccount –Password $securePassword -Confirm:$false
    #Repeat lines 1-18 for each managed account you want to change.

  • SharePoint 2013 Search Error: Event ID 2548 - Content plugin can not be initialized - list of CSS addresses

    While working with a customer and provisioning Search they were getting a strange error that was causing the topology not to activate.  It just stayed in a hanging state and in the Windows Application log there were errors: Event ID 2548 - "Content plugin can not be initialized - list of CSS addresses."  After a little research and testing I figured out the problem was really easy to fix.  We granted the WSS_WPG and WSS_Admin_WPG groups Full Control permissions to the path where the Search Index would live.  After we made the change the topology activation finished without issues.  We did a quick reboot and the server came back up without errors. 

    As for the script used to provision search, see this post.

  • SharePoint Site Redirection Using PowerShell

    Working with a customer this week there was a desire to create a script to redirect users from one site to another (mostly because we had several sites to do this to).  While there are many ways to accomplish this such as IIS or using the Content Editor Web Part with a traditional redirect script, SharePoint also provides a redirect page content type that provides this functionality.  Below is an example script we created to achieve the creation of the old site URL, create a redirect page with the property that redirects to the new site and sets the redirect page as the home page of the site.

    Add-PSSnapin Microsoft.SharePoint.PowerShell

    #Setup Site String Variables

    $Site = "http://intranet.contoso.com/sites/Proj/"

    $SiteName = "Project1"

    $site1 = $site + $SiteName

    #Specify the site to redirect to

    $Site1Redirect = "http://intranet.contoso.com/PM/Projects/Project1"

    #create the old site in the new environment to redirect from

    new-spweb -url $site1 -Template "CMSPublishing#0" -Name $SiteName

    #Create Redirect Page

    $s1 = get-spweb $site1

    #Finds the appropriate page layout

    $pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($s1)

    $pl = $pubWeb.GetAvailablePageLayouts() | Where { $_.Name -eq “redirectpagelayout.aspx”}

    #Create New Page

    $newPage = $pubWeb.AddPublishingPage("Redirect.aspx", $pl) #filename need end with .aspx extension

    $newPage.Update()

     

    #Get the docs from the Pages library and store in variable

    $list = $s1.lists["Pages"]

    $items = $list.items

    #Go through all items and update the redirect page to point to the proper

    foreach($item in $items)

    {

    #If the "Name" column value equals "Redirect.aspx"

    if($item["Name"] -eq "Redirect.aspx")

    {

    #Change the value of the "Redirect URL" column

    $item["Redirect URL"] = $Site1Redirect

    #Update the item

    $item.Update()

    }

    }

    #Check the file in and publish it

    $newPage.CheckIn(“Created by PowerShell”);

    $newPage.ListItem.File.Publish("")

     

    #Configure Redirect Page as Home Page for each site

    $HomeDL = $s1.RootFolder

    $HomeDL.WelcomePage = "Pages/Redirect.aspx"

    $HomeDL.update()

  • SharePoint 2013 Search Configuration PowerShell Script

    So last month I promised some customers I would post my
    search script for 2013 and as life would have it, August came before I got to
    it so here it is…. Better late than never. 
    While this script is pretty basic as far as provisioning Search for
    SharePoint 2013 goes it does address two things I always try to do when I provision
    search that I don’t often see.  First, it
    is designed to use two different service accounts, one for the administration
    application pool and the other for the query application pool.  Second, at the end of the script I put in a
    piece that sets the content access account to another account which follows
    best practice. 

    This particular code is designed for a standard 3 tier farm
    that has an Application, Web and Database server.  The idea of the code is to put most of the
    Search roles on the Application server. 
    The roles going on the Web server are related to the Query Role and
    Index. 

    Script:

    #Setup Variables - Assume 2 Servers (App & Web)

    #Assume 3 Accounts (Content Access, Admin, Query)

    #### Note - You should setup the Index Location prior to
    running these commands and ensure it is an empty folder

    #### Note - If you setup diag logging prior to running
    script, ensure you give dbo permissions to the account you run this under

    write-host 0. Setting up some initial variables.

    $AppSvr = "SPApp2013"

    $WebSvr = "SPWeb2013"

    $CAAcct = "campbushnell\svcSPSearchCA"

    $password = "ZAQ!2wsx"

    $CAAcctPW = ConvertTo-SecureString -String $password
    -AsPlainText -Force

    $AdminAcct = "campbushnell\svcSPSearchA"

    $QueryAcct = "campbushnell\svcSPSearchQ"

    $SSAName = "EnterpriseSearch"

    $SSIAppSvr = get-SPServiceInstance -server $AppSvr |
    ?{$_.TypeName -eq "SharePoint Server Search"}

    $SSIWebSvr = get-SPServiceInstance -server $WebSvr |
    ?{$_.TypeName -eq "SharePoint Server Search"}

    $IndexLocation = "C:\SPIndexLocation"

    $err = $null

     

     

    #Start Services for SSI

    write-host 1. Start Services search services for Each Server

    Start-SPEnterpriseSearchServiceInstance -Identity $SSIAppSvr

    Start-SPEnterpriseSearchServiceInstance -Identity $SSIWebSvr

     

     

    #Create Application Pools

    write-host 2. Create a Application Pools

    $AdminAppPool = new-SPServiceApplicationPool -name
    $SSAName"-AdminAppPool" -account $AdminAcct 

    $QueryAppPool = new-SPServiceApplicationPool -name
    $SSAName"-QueryAppPool" -account $QueryAcct

     

     

    #Create Search Service Application

    write-host 3. Create the SearchApplication and set it to a
    variable

    $SearchApp = New-SPEnterpriseSearchServiceApplication -Name
    $SSAName -applicationpool $AdminAppPool -databasename
    $SSAName"_AdminDB"

     

     

    #Create Search Service Application Proxy

    write-host 4. Create search service application proxy

    $SSAProxy = new-spenterprisesearchserviceapplicationproxy
    -name $SSAName"ApplicationProxy" -SearchApplication $SearchApp

     

     

    #Clone Search Topology (this is empty by default)

    write-host 5. Clone Search Topology

    $SearchTopology = $SearchApp.ActiveTopology.Clone()

     

     

    #Provision Search Administration Component

    write-host 6. Provision Search Admin Component.

    New-SPEnterpriseSearchAdminComponent -SearchServiceInstance
    $SSIAppSvr -SearchTopology $SearchTopology

     

     

    #Provision New Search Content Processing Component

    write-host 7. Create New Search Content Processing Component

    New-SPEnterpriseSearchContentProcessingComponent
    -SearchServiceInstance $SSIAppSvr -SearchTopology $SearchTopology

     

     

    #Provision New Search Analytics Processing Component

    write-host 8. Create New Search Analytics Processing
    Component

    New-SPEnterpriseSearchAnalyticsProcessingComponent
    -SearchServiceInstance $SSIAppSvr -SearchTopology $SearchTopology

     

     

    #Provision New Search Crawl Component

    write-host 9. Create New Search Crawl Component

    New-SPEnterpriseSearchCrawlComponent -SearchServiceInstance
    $SSIAppSvr -SearchTopology $SearchTopology

     

     

    #Provision New Search Index Component

    write-host 10. Create New Search Index Component

    New-SPEnterpriseSearchIndexComponent -SearchServiceInstance
    $SSIWebSvr -SearchTopology $SearchTopology -RootDirectory $IndexLocation

     

     

    #Provison New Query Processing Component

    write-host 11. Create New Query Processing Component

    New-SPEnterpriseSearchQueryProcessingComponent
    -SearchServiceInstance $SSIWebSvr -SearchTopology $SearchTopology

     

     

    #Activate Topology Changes

    write-host 12. Activate Topology

    $SearchTopology.Activate()

     

     

    #Setup default Content Access Account

    write-host 13. Set the default content access account

    Set-SPEnterpriseSearchServiceApplication –Identity
    $SearchApp -ApplicationPool $QueryAppPool -DefaultContentAccessAccountName
    $CAAcct -DefaultContentAccessAccountPassword $CAAcctPW

     

    Write-host "Your search application $SSAName is now
    ready"

     

    One last note with this script, it is designed for smaller
    farms and if a large search farm is being created more configuration will be
    required to ensure you get the performance you are looking for.

  • 404 & 401 Errors with the App Management Service

    I recently was testing out the configuration of the App Management Service in SharePoint 2013.  For the most part I followed the TechNet article on the steps but because I like to create scripts I can share with customers I did the configuration in PowerShell.  Below is the script which not only creates the App Management Service but also the Subscription Service which is required by the App Management Service.  (If you use this script make sure you setup your service accounts as managed accounts first)  I also like to get my DNS Forward Lookup Zone and wildcard CNAME alias created before running the script in case the AD/DNS guys have any changes they want to suggest.

    To setup the DNS forward lookup zone and wildcard CNAME alias I followed the TechNet article I already referenced but in case you are following this post instead of that I’ll quickly rehash it.  First, open DNS then right click Forward Lookup Zone and click New Zone.  When going through the wizard click Next to start it then select Primary Zone and click Next.  Then choose if it is at the Forest or the Domain, in my case it doesn’t matter so I chose Domain and then click Next.  Next you will provide a name for your zone (CampBushnellApps.lcl – This will become the $AppDomain variable in the script below).  Once that’s done I use the defaults through the rest of the wizard and click Finish to create. 

     

    Now I can create the wildcard CNAME alias.  To do so I select the newly created forward lookup zone and right click and select new Alias (CNAME).  In the New Resource Record window I type * for the Alias Name and the WFE FQDN for the FQDN field (in this case SPWeb2013.campbushnell.lcl).  If I wanted to use a load balanced URL (DNS A Record) instead I could do that instead of pointing directly at the WFE.  This can work great for abstracting the server name or in the case that I have multiple WFEs.   

     

    Now that the DNS side of the house is configured, I run my script…  (The first section of the scripts I write I always setup my variables for use in the script which is great for multiple farms)

    #Create Variables

    write-host 0. Setup Variables

    $AMAcct = Get-SPManagedAccount "campbushnell\svcSPApps" #App Management Service Account

    $SSAcct = Get-SPManagedAccount "campbushnell\svcSPSubscript" #Subscription Settings Service Account

    $SubServiceName = "Subscription Settings Service"

    $AppServiceName = "App Management Service"

    $SubDBName = "SubscriptionSettingsServiceDB"

    $AppDBName = "AppServiceDB"

    $AppSvr = "SPApp2013"

    $AppDomain = "CampBushnellApps.lcl"

    $AppPrefix = "apps"

     

    #Start the Subscription Settings Service and App Management Service

    write-host 1. Subscription Settings Service and App Management Service

    $SubServiceInstance = get-SPServiceInstance -server $AppSvr | ?{$_.TypeName -eq "Microsoft SharePoint Foundation Subscription Settings Service"}

    Start-SPServiceInstance -Identity $SubServiceInstance

    $AppServiceInstance = get-SPServiceInstance -server $AppSvr | ?{$_.TypeName -eq "App Management Service"}

    Start-SPServiceInstance -Identity $AppServiceInstance

     

    #Create Subscription Settings Service App Pool

    write-host 2. Configure Subscription Settings Service App Pool

    $appPoolSubSvc = New-SPServiceApplicationPool -Name $SubServiceName-"AppPool" -Account $SSAcct

     

    #Create Subscription Settings Service App

    write-host 3. Configure Subscription Settings Service App

    $appSubSvc = New-SPSubscriptionSettingsServiceApplication –ApplicationPool $appPoolSubSvc –Name $SubServiceName –DatabaseName $SubDBName

     

    #Create Subscription Settings Service App Proxy

    write-host 4. Configure Subscription Settings Service App Proxy

    $proxySubSvc = New-SPSubscriptionSettingsServiceApplicationProxy –ServiceApplication $appSubSvc

     

    #Create App Management Service App Pool

    write-host 5. Configure App Management Service App Pool

    $appPoolAppSvc = New-SPServiceApplicationPool -Name $AppServiceName-"AppPool" -Account $AMAcct

     

    #Create App Management Service App

    write-host 6. Configure App Management Service App

    $appAppSvc = New-SPAppManagementServiceApplication -ApplicationPool $appPoolAppSvc -Name $AppServiceName -DatabaseName $AppDBName

     

    #Create App Management Service App Proxy

    write-host 7. Configure App Management Service App Proxy

    $proxyAppSvc = New-SPAppManagementServiceApplicationProxy -ServiceApplication $appAppSvc

     

    #Configure App URLs

    write-host 8. Configure App URLs

    Set-SPAppDomain $AppDomain

    Set-SPAppSiteSubscriptionName -Name $AppPrefix -Confirm:$false

     

    On occasion I have had step 8 of my script fail because SharePoint is still provisioning the service application and cannot setup the URLs.  In those cases I simply manually setup the required variables and rerun the two lines of code for step 8.  Once that is created I should be able to open Central Admin and access the Apps section.  In this area I am going to verify my App Domain and App Prefix are set to my variables by selecting Configure App URLs. 

     

    After I have verified that I go configure my App Catalog for the web application by selecting Manage App Catalog.  Because it is new I have to create one for the web application.  The process is much like creating a new site collection. 

    After that there is one more step to take to allow my web application to access apps from the SharePoint store, I need to activate the Apps that require accessible internet facing endpoints feature.  To do so I browse to Application Management à Manage Web Applications à select my web application and select Manage Features in the ribbon.  Then I activate the feature.

     

    At this point I am able to add apps from the SharePoint store to a SharePoint page!!!  But when I go and test the app on the page it bombs with “page cannot be displayed” error messages in the web part!  What gives!?!  Well after some Fiddler traces I found 404 errors.

     

    As it turns out the default website is picking up the app and trying to respond for it rather than redirecting to a SharePoint web application.  First I attempted to fix this by disabling the default web site in IIS on my WFE.  Not the fix so I re-enabled it (not because it is doing anything but because I like to keep things as close to out of the box as I can, especially for testing purposes).  So instead I change the binding on my web application to pick up anything on port 80 (which is what my site is using).  When I test again I get prompted for credentials so I put them in and continue to get prompted.  

    What is with the prompting for credentials?  I quickly test again and this time my Fiddler trace shows me 401 errors.  First I wonder if it is a loopback issue so I disabled loopback and after my first prompt it accepts my credentials and my app works! 

    To disable loopback if you aren’t familiar, open the registry and go to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA and create a new DWORD (32-bit) Value with a name of DisableLoopbackCheck and set the value to 1.  Restart the server after the change to ensure it takes effect.  Reference article KB 896861

    But I know that prompting credentials on page load isn’t going to fly in the real world so how can I fix it?  Well, to be honest it so simple I almost didn’t try it… all I did was add the App Domain (*.CampBushnell.lcl) to my trusted sites and configured trusted sites to pass credentials.  (I would recommend that be part of a group policy rather than setup on individual computers)  I did take the Loopback out again and found that it still kept prompting for credentials so it definitely is part of the fix here.

      

    As an aside in case you are using Kerberos with your web application… I spent several hours working through issues with this while using a Kerberos web application and found consistent prompting that neither of the above solutions resolved.  In fact, the only way I have found around it so far for a web application using Kerberos is to setup a separate web application that is NTLM and setup the IIS binding to it rather than the Kerberos based web application.  I still needed to trust the domain and forward credentials but after I did that the prompting issue stopped.