Wednesday, November 1, 2017

Content Deployment Nightmares

We recently updated all 3 of our SharePoint farms, dev, prod, and our dmz servers with the August 2017 CU and then found out our content deployment jobs were failing to two of our forward facing SharePoint farms. The only thing that seemed to get the deployment jobs to stop running was to log on to each of my remote SharePoint servers and using powershell to stop the owstimer process. Once this was done the content deployment jobs would report back they had completed successfully but no content was actually deployed. We opened a ticket with Microsoft to get some assistance with the issue but we were still coming up short. Knowing that there was a process or timer job that wasn't firing like it was supposed to I ran this script and all of the sudden the content jobs started working properly.

$farm = Get-SPFarm

$disabledTimers = $farm.TimerService.Instances | where {$_.Status -ne "Online"}
if ($disabledTimers -ne $null)
{
foreach ($timer in $disabledTimers)
{
    $timer.Provision()
    $timer.Start()
    }
}

Wednesday, March 8, 2017

Powershell & SharePoint Exception has been thrown by the target of an invocation

The other day I was logged into my SharePoint server with my local admin user account and tried to run a powershell script against my farm and got an error that had me scratching my head. The error was "Exception has been thrown by the target of an invocation"

The error really made no sense since I had admin rights to the farm, but upon further investigation I found that my account didn't have the rights it needed to access some sites.

Solution was to go to central admin and select
 Application Management > Manage Web Applications >Select the web app you need access to >From the Ribbon select User Policy>Add Users

Here I added my account with Full Control and clicked save and then ran my powershell script again and it successfully executed.

Tuesday, January 6, 2015

Happy New Year 2015!

Greetings interwebs! hope your holiday was as amazing as possible, we stayed home this year and stayed up late watching movies and then watched the ball drop in Times Square on the web, hooray we don't need cable or satalite service to still enjoy a age old tradition.

Looking forward to getting some new content published as I have been working on a variety of things with Office365, SharePoint 2013, the SPServices library from our good friends at codeplex. Over the holiday I had some time to go through a box of ever collecting IT gear, routers, wifi switches, cables and all the mess, since one of my resolutions for the year was to get our spaces better organized and clean out the clutter. I found that I had a 3 Linksys WRT610N wifi routers that were still functional but for some reason or another I hadn't needed them.
 After a bit of searching I found that I could convert them to wifi repeaters with out any type of hardwired connection between them, SWEET MOTHER OF ALL THINGS AWESOME, I can now fully cover my home from front to back and top to bottom with wifi access, even our chicken coop could get setup for a webcam! HELL YEAH! I can watch youTube videos in the garage or access a how to series in order to build something or even for a bit of home security using web cams, obviously I have a few ideas of what to do with this new found freedom! So how to do it?

First I downloaded a wifi analyzer tool for my smart phone the Samsung Galaxy Note 3 and did a quick site survey where I walked around and noted the best spots to setup my access points in order to spread the signal out correctly.

You will then need to load up the dd-wrt firmware onto your router and then reconfigure a few things and you will be good to go. Excellent instructions are posted here on the dd-wrt wiki for the Linksys routers I have, but they are very similar for all models.

In our home we have 3 Google Chromecasts connected to TVs on each of the 3 levels of our home, each of our kids has their own Amazon Kindle Fire, plus I have 2 tablets and my wife has 1, we have 1 shared workstation for the kids to use, and then another Ubuntu Linux system for the littles to use, as well as a couple of laptops for work and projects, and lastly our cell phones use wifi at the house, so we have lots of devices consuming data on a regular basis, plus we have teen aged kids so I wanted to do my best to limit their time and usage of the internet during normal hours and I work from home doing consulting work.

This solution worked perfectly for me and I now have a greater control range over who gets access to what and when, the kids only connect to 1 of the access points, which has time limits, access restrictions, and filtering enabled, the rest of the network allows me to have the best signal possible wherever I am in the house or around the property.

A couple of pro tips:
--Make sure to do the 30-30-30 reset on your routers, this ensures you start with the best possible chance of getting these things to work properly.

--Once you have them configured go into the administration panel and backup the router, save it somewhere accessible as you will most likely be needing it.

Have fun with this one!

Saturday, April 6, 2013

Dynamically create html elements with jquery in a SharePoint Content Editor Web Part

One of the ways I like to create solutions with SharePoint is to utilize the Content Editor web part with some jquery to sort of commandeer the UI, because sometimes you just need to get some prototypes put together and the fastest way is to mock up and then create similar functionality.

In this example I have a document library that I have 9 pages in, I created the page names to coincide with the names of the dynamically generated buttons, divs, and iframes I am creating. My page names are
"Home", "Cost", "Schedule", "Performance", "Charts", "Reports", "Logistics", "Inventory"

Basically what I do is that I have2 empty divs on my page, and then as the page loads it creates all the buttons, divs, and iframes based off the list above that is used as an array.

What I really like about this solution is that I can reuse it over and over again since in order to get this script to work from a central location  I had to abstract out the order number to be used as a parameter which happens to be the site's title and is included in my url. Since all of our sub sites are created based off a template this works perfectly.



The script that my content editor points to looks like this




    

Now that we have that we can turn our attention to the javascript file that will loop through the array and create our buttons, divs, and iframes

// Define some initial variables
var buttonClicked = 'showHome';
var currentDiv = 'divHome';
var homeUrl="";
var siteName = "/dashboards/";
var siteLibrary = "/SitePages/";
var urlEnd = ".aspx?isdlg=1";
// This is an array of all the items names we want to use for our buttons
var pages = ["Home", "Cost", "Schedule", "Performance", "Charts", "Reports", "Logistics", "Inventory"];
// Since this script is centralized we need to look at the current Dashboard and get the task order number
var currentTaskOrderUrl = window.location.href;
var TaskOrderNumber = currentTaskOrderUrl.split('/')[4];
// onClick event for our dynamically created buttons
$(".switchIframe").live('click', function(e){
 // Lets make sure that nothing happens if the user clicks an already selected button
 if (e.target.id != buttonClicked)
 {
  
  // The user clicked a button for new content, we can target the div we want to show by 
  // doing a replace of the currently selected button's id, which has the same id name 
  // button id = showHome & div id = divHome
  targetDiv = (e.target.id).replace("show", "div");
  var $targetIframe = $($(this).data('target')), 
  src = $(this).data('src');
  
  if($targetIframe.attr('src') != src)
  {
   $targetIframe.attr('src', src);
  }

  hideDiv(currentDiv);
  showDiv(targetDiv);
  currentDiv = targetDiv;
  buttonClicked = e.target.id;
 }
    
});

function createLayout()
{
 var b;
 // Loop through the array of items we need to create
 for(b=0;b');
  // Source code to create all of our divs and iframes inside a div with an ID of contentdivs
  $("#contentdivs").append('
'+pages[b]+'
'); } } function showDiv(id) { var $sDiv = $('#' + id); $sDiv.show(800); } function hideDiv(id) { var $hDiv = $('#' + id); $hDiv.hide(200); } $(document).ready(function(){ // Build the UI elements, buttons, divs, iframes createLayout(); // Load up the source attribute of the home iframe $('#iframeHome').attr('src', homeUrl); // Show the div $('#divHome').show(600); });

Powershell add a document library to a set of sub sites recursively

So during one of my many experiments the other day I found I needed a document library on all of my orders sites that had a custom web part page in it. While there are several ways of doing this with Powershell I chose to loop through my sub sites and add the DashboardSitePages document library to each site from scratch. I also wanted to add a web part page to this library named Dashboard.aspx.

Hey for some reason my script pasting function is not rendering the xml line very well below so here is a link to the complete script file.

## DESCRIPTION
## ------------------------------------------------
## Script to loop through a set of Subsites and  
## adds a document library named SitePages  and a 
## web part page to the site named dashboard.aspx
 
## EXPLAINATION
## ------------------------------------------------
## This example illustrates how to loop through a  
## set of sub sites and add a document library and a 
## web part page named dashboard.aspx 

##
## BEGIN
## ------------------------------------------------
## Load up the snapin so Powershell can work with SharePoint
## if the snapin was already loaded don't alert the user
Add-PSSnapin microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
## Clear any errors or output to the screen
CLS
## Set variables
## This variable will be the site where I want to start
$parentSite = "http://sp2010/dashboards"
$webSites = Get-SPWeb $parentSite

$layoutTemplate = 2
$documentLibraryDescription = "A Document Library to store the Dashboard Pages"
$pageTitle = "Dashboard"
$targetLibrary = "DashboardSitePages"

function CreateSitePagesDocLib
{
 $listTemplate = [Microsoft.SharePoint.SPListTemplateType]::DocumentLibrary
 $webSite.Lists.Add($targetLibrary, $documentLibraryDescription, $listTemplate)
 $docLib = $webSite.Lists[$targetLibrary]
 $docLib.OnQuickLaunch = $true
 $docLib.EnableVersioning = $true
 $docLib.Update()
 CreateDashboardPage
}

function CreateDashboardPage
{
 $list = $webSite.GetList("http://sp2010/dashboards/$webSiteName/SitePages/")
 $xml = "" + $list.ID + "NewWebPageNewWebPartPage" + $layoutTemplate + "true" + $pageTitle + ""
 
 $result = $webSite.ProcessBatchData($xml) 
}

foreach($webSite in $webSites.Webs)
{
 $webSiteName = $webSite.Name
 $webSiteDescription = $webSite.Description
 $sitePagesLib = $webSite.Lists[$targetLibrary]
 if($sitePagesLib)
 {
  CreateDashboardPage
 }
 else
 {
  CreateSitePagesDocLib
 }
}

Sunday, March 31, 2013

Custom SharePoint Site Title Bar using jquery


One of the new items we wanted to add to our dashboard front pages was a site name and description bar across the top of the pages for our dashboards. Each of our dashboard sites was created using a Powershell export of a site we configured exactly the way we wanted, making it our template site, and then importing the site with a new name.

This gives us 100s of sites with the same configuration, page layout, and webparts named the same, but content is specific to each site such as financial data and other reports.

The approach to solving this issue was to use a bit of css, jquery, and a content editor web part. The content editor web parts will allow you to either enter free text and decorate it any way you like, or you can create your layout and copy the script and paste it into notepad and then save the file to a document library at the root of your site that has read access for any of your visitors. We also keep a copy of jquery 1.8.3 in this same document library called scripts. The newest version of jQuery breaks some of our functionality, so be sure to use the earlier version.

One requirement in building this was it had to be easy to update, so by keeping our code for the content editor web part in a single text file stored at the root of our site and then configuring each web part to point to this file we can now update hundreds of web parts with a single bit of code.

The end results were that I needed to have this yellow Title banner web part on each of my sites, the title banner is basically using jQuery to find some class tags on the page that contain the current site's title and description, two items already on the page, but not very easy to read.


You can see when we view the web part properties that the values have been set by our script, note the Content Link field, it points to my root document library where the web part reads the script that all the web parts will read, if we need to make a change to the web part this is where it will be done.


Each of these sites in the drop down need this dynamic web part added to it's Dashboard.aspx web part page.


Another example of the web part on a different site










Now that all that is working we need a way to automatically inject this web part onto all of our sub sites at once, this is where Powershell will prove its self once more. My previous post of Add/Update a web part with Powershell should be all you need to sort out the automation part.

Saturday, March 30, 2013

Powershell Delete a webpart from a SharePoint webpart page loop

Today I find that when I create new things, often times I create too many things during my testing of say dynamically adding a webpart to a SharePoint webpart page. So I need to have a way to quickly loop through my hundereds of sites and delete the webpart.


## CONTACT INFO
## ------------------------------------------------
## CREATED   : 2013.03.30
## MODIFIED  :
## AUTHOR    : Jason Lasby 
## EMAIL     : digitalslavery@gmail.com 
##
## DESCRIPTION
## ------------------------------------------------
## Script to loop through a set of Subsites and  
## Delete a web part from a page stored in the SitePages 
## Document Library named Dashboard.aspx
## 
## EXPLAINATION
## ------------------------------------------------
## This example illustrates how to delete a webpart 
## from a set of sites that use the same page layout
## and configured with the same web parts, think about 
## a company dashboard site where each department may 
## report standard data like who is in who is out, 
## work related accidents, finance data, shipping
## information, etc... We can loop through our sites
## and add or remove web parts for all sites at once.
##
## BEGIN
## ------------------------------------------------
## Load up the snapin so Powershell can work with SharePoint
## if the snapin was already loaded don't alert the user
Add-PSSnapin microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
## Clear any errors or output to the screen
CLS
## Set variables
## This variable will be the site where I want to start
$parentSite = "http://sp2010/dashboards"

function RemoveWebPart 
{
 foreach($wp in $wpm.WebParts | ?{$_.Title -like "* Banner *"})
 {
  if($wp)
  {
   $listOfWebParts = $wp.ID
   foreach($matchFound in $listOfWebParts)
   {
    $wpm.DeleteWebPart($wpm.WebParts[$matchFound])
    Write-Host "$matchFound was deleted for $webSite"
   }
  }
     
 }
}

Start-SPAssignment -Global
## Create a variable to hold the SharePoint site, invoke the connection
## to the site we defined in the $parentSite variable
$web = Get-SPWeb $parentSite
## Check to make sure that url exists
if($web)
{
 ## Loop through all the sub sites of the site url we got
 foreach($webSite in $web.Webs)
 {
  $webSiteName = $webSite.Name
  $pageUrl = "SitePages/dashboard.aspx"
  $page = $webSite.GetFile($pageUrl) 
  $wpm = $webSite.GetLimitedWebPartManager($page, [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
  if($wpm)
  {
   RemoveWebPart 
  }
  else
  {
   Write-Host "Web part not found"
  }
   
 }
}
 else
 {
  ## Gracefully let the user know that the site they requested
  ## was not available or was not found.
  Write-Host "$webSite not found, check the url and try again."
 }

Stop-SPAssignment -Global