Posts

Set up Enterprise App to use App-Only Sites.Selected permissions and wite to SharePoint with PnP Powershell

I wanted to run unattended scripts against SharePoint for various governance and content cleanup jobs and found the guidance for this to be a little confusing.   I think it's a good idea to limit the access of any script, so I prefer to set up an App per script and use the Sites.Selected permission to limit the sites to which my app has access.   Here's the process I used to get it to work: You can register an app in the Azure portal UI, but there's a few steps that must be performed with PowerShell, so I figured just doing it all in Powershell made it consistent.   Step 0:  Get the right version of PnP.Powershell I also had to use the PnP.PowerShell 2.2.81 nightly build because there was a bug introduced in 2.2.0.  If you need to get a specific version you can run Install-Module, but I prefer to use Save-Module with specific version  so I can keep different version of PnP.PowerShell around to avoid having my old scripts affected by new modul...

Quick SPFx Dev Environment Setup Guide

This is just a quick post to document my current setup steps Install NVM for windows Install the proper version(s) of node using nvm install VersionNum (see https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-development-environment for currently supported versions) Address any critical vulnerabilities Install yeoman and spfx genereator npm i -g yo npm i -g @microsoft/generator-sharepoint Install additional utils Install gulp npm i -g gulp Install Git Install VS COde Test yo @microsoft/sharepoint

Show Document LIbrary from another site collection on a Modern SharePoint Page

Here's a pretty good workaround for the lack of a cross-Site Collection Document library and not having to go to a fancy search interface or develop or buy an SPFx component.   Keep in mind that the user who's visiting the site where you're surfacing the library will need at least read access to the library. Go to the document library you'd like to surface, then go to the folder, etc. with the information you'd like to share. Copy the URL from the address bar. On the Modern Page/site where you'd like to show that document library/folder, add an Embed Web Part Add the following to your embed web part: <iframe src="URLYOUCOPIEDINSTEP1" width="100%" height="600"></iframe> This experience allows people to navigate the library/folders without leaving the site they are on, but the docs open in their own tab.

Power Automate: Using the SharePoint Update Item action

Power Automate's Update Item action for SharePoint has an issue with choice fields in that when you add that action, all fields are blank EXCEPT Choice fields.  Choice fields will instead default to the top item in the choice list.   This is really bad because if you don't clear them the flow will overwrite any existing values with the top items. Currently, the only way I can see to avoid this issue is to manually clear each field, so here are the steps: Choose the dropdown item on the choice field. Choose "Enter Custom Value" Immediate go back to the field and click the 'X' in the field and it will be cleared Repeat for each choice field that you don't want to change. I think the above is just a hack/workaround to a problem with how this action is configured by default so I put this into the uservoice/suggestion box for PowerAutomate.    Upvote this if you think it's worth it: https://powerusers.microsoft.com/t5/Power-Automate-Ideas/SharePoint-Update-...

Restoring a lot of files from the Recycle Bin

I had a customer who accidentally synched a (very large) SP Online library and then decided they didn't want the files on their PC anymore...so they deleted them and were shocked to learn that they'd been deleted from SharePoint too! Thanks to PnP Powershell you can use the following to restore a batch of files quickly (and filter). First, you'll want to make sure you only select the files you want to restore.  I used a combination of filtering by the person who deleted the files and the date they were deleted, e.g. Connect-PnPOnline https://yourtenanturl $restoreSet = Get-PnPRecycleBinItem | Where-Object { $_.DeletedByEmail -eq "imsorry@company.com" -and $_.DeletedDate -gt "1/1/2019" } Make sure you have a fairly updated version of the PnP Powershell module as the objects that come back have more properties populated than in older versions so you can do more powerful filtering Next you can restore the files like this: $restoreSet | Rest...

Scoped Bootstrap for SharePoint

I've got a project for a client that involves refactoring a lot of bad choices related to SharePoint branding in Classic mode sites.   (While I'm enthusiastic about the Modern Sites and new techniques using SPFx extensions, most of our customers are slow on the uptake). I've had to do this a few times and this blog explains it perfectly, but due to some formatting issues over there and a desire for just the steps as I need to update/repeat this, I've summarized here: Open up a node capable command prompt (I use cmd) Create a directory for your solution (e.g. C:\Repos\ScopedBootstrap) Run npm install bootstrap@3.3.7 (or whatever version you need to work with) Go into the node_modules\bootstrap\less directory  Open bootstrap.less in VS Code. Place  .YourUniqueClassName{  before all the @import statements and close the curly brace at the end of the file. Go back to the ..\bootstrap directory (in node_modules) Run npm install to install the dependenci...

Switching between on-prem and SharePoint Online versions of PnP Powershell Commands

I've updated my original post to just link to these instructions. This is a better way of doing it as you're explicitly loading the specific commands each time you need to run them, that way you're clear on which version you're using: https://www.erwinmcm.com/running-the-various-versions-of-pnp-powershell-side-by-side/   I use the PnP Powershell commands very frequently, but mostly only for SP Online.   Lately I've been working on a SP2013 customization and wanted to use the PnP PowerShell commands for SP2013. If you have multiple version of the commands installed then you'll need to select which one you want to use. This thread explains that you need to clear your PSMODULEPATH environment variables but then you'll need to an import-module when you need to work with a particular version.  Follow this guidance first:  https://github.com/SharePoint/PnP-PowerShell/issues/1356 Doing that is fine if you don't mind retyping your module path in the...

Client Side Override the Site Logo's link in an SharePoint Site

In SharePoint sites that have any kind of hierarchy of subwebs, it is frequently desirable to override the logo's link behavior to link back to the root of the site collection.   There's a bunch of guidance on how to do this by overriding the master page, but not much on how to do this client-side, to avoid MasterPage manipulation.   Here's a script that helps to do this: //update site icon link, SP overrides any direct reassignment so you have to change the existing ID //and then create a dummy element with the existing ID to avoid future JS errors. //read old link id var prevId = $("#DeltaSiteLogo > a").attr('id'); //change the id $("#" + prevId).attr({       'id':'CustomSiteLogo',       'title': 'Employee Portal Home',       'href':window.location.protocol + "//" + window.location.host }); $("#DeltaSiteLogo > a").after("<a id='" + prevId + "...

Connect-PnPOnline : For security reasons DTD is prohibited in this XML document. error

Until today I had never received this error when trying to connect to SPO.    If you get this error there's a good chance it's related to missing records on the DNS server your machine is relying upon.  If not set, there's a good chance you're using your ISP's DNS servers, whose records may not be as up to date as others.  The quick fix (at least for me) was to alter my DNS settings to point to more reliably up-to-date DNS.   Here's a how to fix this issu (on Windows 10, if you aren't using windows 10, follow your OS instructions on updating DNS settings and then just jump to step 4 below) along with a few options for DNS settings that I tested: Click Start and type "View Network Connections. Right-Click your adapter that connects to the internet and choose properties Choose TCP/IP v4 and then click the "Properties" button At the bottom of the IP v4 properties window, select the radio button that says "Use the following DNS Server ...

Reordering the default content type for document sets

Had a particularly annoying time with this as the document sets were already in use and was attempting to do this in SharePoint Online.    My scenario was that I was using document sets and only wanted document sets in the root folder.  So I set the other ctypes as not visible, but then the customer asked to default to one of the content types that wasn't previously set up at the top of the list, and I couldn't reorder in the "Document Set Setting" option of the document set content type because there's a multi-select box with no up/down functionality for these.   As a last ditch effort I went back to the List Settings and just made all content types visible on the new button, which enabled the documents that were supposed to created in the document set to be created at the root level (temporarily).  Then I reordered the content types, then set the non-docset content types back to not being visible.  VOILA! to my surprise that solved the problem....

Setting up an SP2013 VM on Azure, with a GUID-less DB

Image
Critical Path Training produces a number of excellent training courses, books, and free resources.   If you haven't checked out their  Inside SharePoint 2013  book, you definitely should.  It's a pretty comprehensive guide to what Developers need to know (initially) to do SP2013 Development. I typically build their VM when I first start using the next version of SharePoint and often make it my baseline for general development.   This year however I've decided to spice it up a bit and go for an install without the Configuration Wizard and a GUID-less database instance, per  Todd Klindt/Shane Young's book  because their guide is more close to an enterprise level configuration.  I also wanted install and configure it in Azure, so I can get to it wherever I am (and free up some  SSD  space on my PC). The Critical Path VM guide can be downloaded  here .  You'll need a (free) account to download the guide.  I sug...

SharePoint Solution Downloader

Special thanks to Djamel Chagour and his response to my MSDN thread (which linked to this blog post ) to solve my issue of grabbing solutions from the Solution store so I could drop them on another server. His post is more complex and deals with generating the stsadm commands for a batch deployment. Mine is the dumbed down version that just pulls the files so I can readd them as I need them. Here's the code: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; using System.Xml; using System.Web; namespace Mirant.SharePoint.Administration.WSPDownloader { class Program { static void Main( string [] args) { bool hasErrors = false ; if (args.Length != 1) { Console.WriteLine( "Usage: Company.SharePoint.Administration.WSPDownloader directory...

Movin on Up: Converting a VDI to a VHD to move from VirtualBox to Azure

Months (years?) behind the rest of the world, I've finally decided it's time to get my VMs up to Azure (no more SSD swapping between PC and laptop despite having a easily mountable caddy in my work laptop and this sweet caddy in my PC . As a loyal VirtualBox user I opted for VDI rather than VHD, but now I must convert.  So here's what I did: Uninstall VBox Guest Additions from the VM Shut the VM down (don't save the state). Remove the VDI from the Virtual Media Manager in Virtual box before running the command below Run the following command using Run As Administrator by right-clicking on the command prompt (from the VBox Install directory unless you've set the PATH variable):  VBoxManage clonehd e:\SP2013DEV.vdi  c:\SP2013DEVaz.vhd --format VHD In the above command the first file is the source VDI the second is the destination VHD. Wait for the magic to happen it should take a while since VMs with SP on them are pretty big.  Going from one drive to another...

Deleted Site Collection continues to show up in Central Admin

In working through my last post  I managed to leave a remnant in Central Admin of a removed Host Named Site Collection that was stored in the default HNSC Content database.   After many attempts to repair in a more acceptable way, (DB Repairs, removing/adding content db, etc) I finally realized that the issue wasn't in my HNSC content db, but rather a leftover reference in the SharePoint_Config DB .  Taking a page from the book-of-things-you-should-never-do-in-SharePoint, I found the reference in the SiteMap table and had to manually delete that row.   I backed up the database first in anticipation of impending doom , but it seems to have done the trick. I'm going to poke around the internet a little more, hoping there's a better way to clean this up or even some timer job or other process that takes care of this in the future, but if you know of the better way, please post it.

Getting Started With Host Named Site Collections - PowerShell Script

Well, it's been a while, but I'm finally getting around to really digging deep into SP2013.  As I go through this I figured I'd start putting together a few helper PowerShell Scripts: Once you've got a SP2013 developer machine created you may want to stand up additional Host Named Site Collections (If you haven't created one yet, use the Critical Path Training guide at http://www.criticalpathtraining.com in the Members section).  I've also included the ability to stand up a new ContentDB for your site collection. Here's a relatively simple Powershell script to help you with this: $snapin = Get-PSSnapin | Where-Object { $_.Name -eq "Microsoft.SharePoint.Powershell" } if($snapin -eq $null) {     Write-Host "...loading Microsoft.SharePoint.PowerShell snapin" -ForegroundColor Gray     Add-PSSnapin Microsoft.SharePoint.PowerShell } function CreateHNSC($name, $url, $template, $contentdatabasename) {     $defaultWebApp = Get-SP...

Using JQuery to Tweak Editform.aspx

For smaller changes to your Editform.aspx you may want to avoid doing a solution deployment that contains a custom content type feature with a custom EditForm.aspx.  This is a quick workaround.  It's pretty much the same as we used to to in MOSS with only minor changes to the way you get to the form. I did this in IE, but it's probably similar in other browsers: Place an html document containing some JavaScript/Jquery into a document library on your list's site.  (Try just putting this for initial testing: <script type="text/javascript">alert('hello world');</script>) Navigate to the list whose editform.aspx you want to change Right click on any item's link to it's display form and choose 'open in new tab' Go to the newly opened tab and click the 'Edit Item' button  to open the item in the editform.aspx append &ToolPageView=2 to the url Add a Content Editor Web Part and point it to your document from step 1...

Opening an Infopath form library template from Infopath in a link

I've found a lot of bad info on how to do this and it's not well documented so hopefully this helps someone: first create a JavaScript function so that your links aren't super long: <script type="text/javascript">             function OpenForm(absSiteUrl, siteRelFormUrl, siteRelSaveUrl)             {                         var formUrl = absSiteUrl + siteRelFormUrl;                         var saveUrl = absSiteUrl + siteRelSaveUrl;                         var formSvcUrl = absSiteUrl + "_layouts/FormServer.aspx?XsnLocation=" + formUrl;    ...

People Search from MySite returns 404

If you have MySites and a Search Center running in your farm, you may have overlooked a not-so-obvious configuration setting. When setting up MySites for a User Profile service application, your Search Center URL must point to the "Pages" folder where the Search Center publishing pages are located instead of the Search Center web URL. Otherwise, a People Search from a MySite will forward the request to to http://[searchcenter]/PeopleResults.aspx?k=searchquery (which doesn't exist) instead of http://[searchcenter]/PeopleResults.aspx?k=searchquery which is where the PeopleResults.aspx page is actually located. TLDR: Use http://[searchcenter] /Pages/ for your Search Center url in UPA MySite Settings.

Including a JS file for a custom ribbon control CommandUIHandler without using a ScriptLink CustomAction or Custom Page Components

I've been struggling lately with the proposed solutions for including the javascript for CommandUIHandler's CommandAction and EnabledScript attributes.  Thus far I have only seen the following examples: JavaScript directly into the attributes (messy), Including a ScriptLink command action (bad because then the script file is included in every page where the feature is activated causing bloated pages) Creating a page component (overcomplicated) Instead of all this, I created a pattern which loads the js file on the fly with javascript and keeps your ribbon development more compact (note I have JQuery loaded in the master page, if you don't have this then you'll have to either load jquery dynamically or reference the elements without JQuery): <commanduihandler    CommandAction="javascript:                              ...

Quickly determine which PID corresponds to which App Pool's w3wp.exe

This is a command that will quickly let you know which w3wp.exe you should be debugging on Server 2008 (IIS7, since the App Pool isn't listed in Visual Studio's 'attach to process' dialog). go to \Windows\System32\inetsrv and run "appcmd list wp" and you'll get a list that associates App Pool and PID