Remove NuGet packages from local machine

When working in Visual Studio and downloading packages from NuGet to the projects, a copy of these packages is stored on the local machine. When using virtual machines for development, like I do, the free space on the harddisk minimizes by time.

To remove these packages, we can use the NuGet.exe tool (see

So first run

.\nuget.exe locals all -list

And with the output run

.\nuget.exe locals {section} -clear



Deployment to Azure Web App by PowerShell

The deployment to a web app to Azure could be done in a few simple steps.

  1. download the publishsettings-file from the Azure Web App
  2. define the publish profile in Visual Studio for generating a publishing package
  3. when necessary, define web.config transformations (Microsoft MSDN)
  4. Create the publishing package
  5. use the PowerShell script below to deploy the package to the Azure Web App

Office 365 – Get Group Owners

The following script will list all owners of an Office 365 Group. The same script could be used to get the owners of an Office 365 Teams team. The script connects to Exchange Online, so proper permissions are necessary.

Show all installed Apps for a SharePoint site

Simple PowerShell script to show all installed apps from the marketplace or app catalog for a SharePoint site.

Grant Permissions for Everyone in SharePoint Online with PowerShell

In some deployment scenarios we must grant permissions for Everyone or Everyone except external users. Doing so in the browser interface is easy, but in PowerShell it is somewhat difficult, because we need the claim. The claim for Everyone is “c:0(.s|true”. So with PowerShell we can use this call (we are using the PowerShell PnP extensions to make our life easier) to add Everyone to the Visitors group of a site:

$group = Get-PnPGroup -AssociatedVisitorGroup
Add-PnPUserToGroup -LoginName "c:0(.s|true" -Identity $group

For doing the same for Everyone except external users we need to know the “syntax” of the claim that is needed. The claim for Everyone except external users looks like “c:0-.f|rolemanager|spo-grid-all-users/{tenant-id}”. So, to set the permissions for this group we need to assemble the token. But with PowerShell PnP that is not that problem. These simple three lines of code can do the job:

$realm = Get-PnPAuthenticationRealm
$loginName = "c:0-.f|rolemanager|spo-grid-all-users/$realm"
$group = Get-PnPGroup -AssociatedVisitorGroup
Add-PnPUserToGroup -LoginName $loginName -Identity $group

And that is the result, after running these two scripts:

Not so difficult, but it might be necessary that an administrator activates the ability to use these claims. See this article for more information.


Customize SharePoint Forms

Often in SharePoint projects we hear the requirement that the form of a list or library should be modified, depending on the values of the current item. This could be achieved with some JavaScript, but what, when this should also happen in subwebs. Well, this could also be done with JavaScript and when this customization is added in a proper way, it could be very easy. First, the following only works with the classic UI of SharePoint.

For this example, we use a very simple SharePoint list that was created using PowerShell, because only in this case we have full control over the internal name of a field and its Id.

The requirement will be that the field “Status Comment” should only be shown, when the value of the “Status Field” is finished. In all other cases, this field should be hidden for the user. We keep this example simple, but in real world scenarios it could be very complex. Our solution must modify all three forms of the list, the one for new item, the one for editing items and the one to display an item. An example for some JavaScript to modify the edit form could look like this:

function pbPageModificationFunc() {
    var statusValue = $("#StatusField_8bd36554-9b41-49be-9c96-c2e25743c53a_\\$DropDownChoice option:selected").text();

    if (statusValue != "finished") {


function setOnChangeForStatusField() {
    $("#StatusField_8bd36554-9b41-49be-9c96-c2e25743c53a_\\$DropDownChoice").on("change", function () { showStatusCommentField(); });

function showStatusCommentField() {
    var statusValue = $("#StatusField_8bd36554-9b41-49be-9c96-c2e25743c53a_\\$DropDownChoice option:selected").text();

    if (statusValue != "finished") {
    } else {

The main problem in the solution is, how to add this script to the form. This could be done using a Content Editor Webpart, but in this case we must manually add the webpart, when a similar list is added in any subweb. To automate this task, we use another JavaScript that is used as a loader.

// create a mapping for the form and the modifier file
var mapping =
    	{ "/lists/statuslist/newform.aspx": "/scripts/StatusListNewForm.js" },
    	{ "/lists/statuslist/dispform.aspx": "/scripts/StatusListDispForm.js" },
        { "/lists/statuslist/editform.aspx": "/scripts/StatusListEditForm.js" }

$(document).ready(function () {
    var scriptFile = "";

    for (var i = 0; i < mapping.values.length; i++) {
        var obj = mapping.values[i];

        for (var key in obj) {
            var value = obj[key].toString();

            if (window.location.href.toLowerCase().indexOf(key) != -1) {
                scriptFile = _spPageContextInfo.siteAbsoluteUrl + value;


    SP.SOD.registerSod("formModifier.js", scriptFile);

    SP.SOD.executeFunc('formModifier.js', null, function () {

This script has a mapping table that contains a fragment of the url for the page and the JavaScript file that should be added, when the user opens the page in the browser. This loader script is added by a JavaScript link to the whole site collection, so it runs for each page that a user opens. When the additional script for the current page was loaded, a function (pbPageModificationFunc) is called to modify the current page.

# the script is assuming that a connection to a SharePoint Online site is already established

Write-Host -ForegroundColor Magenta "Upload scripts"

Write-Host "Create scripts library"

$l = New-PnPList -Title "Scripts" -Template DocumentLibrary -Url "scripts" -OnQuickLaunch:$false

Write-Host "Disable modern ui for scripts library"

$list = Get-PnPList -Identity "Scripts" -Includes "ListExperienceOptions"

$list.ListExperienceOptions = "ClassicExperience"

Write-Host "Upload the script files"

Write-Host "- FormModifierLoader.js"

$f = Add-PnPFile -Path .\Scripts\FormModifierLoader.js -Folder "scripts"

Write-Host "- StatusListNewForm.js"

$f = Add-PnPFile -Path .\Scripts\StatusListNewForm.js -Folder "scripts"

Write-Host "- StatusListDispForm.js"

$f = Add-PnPFile -Path .\Scripts\StatusListDispForm.js -Folder "scripts"

Write-Host "- StatusListEditForm.js"

$f = Add-PnPFile -Path .\Scripts\StatusListEditForm.js -Folder "scripts"

Write-Host "Register script files"

Write-Host "- jQuery"

$jsLink = Get-PnPJavaScriptLink -Name "jQuery" -Scope Site

if ($jsLink -ne $null)
	Remove-PnPJavaScriptLink -Identity "jQuery" -Scope Site -Force

Add-PnPJavaScriptLink -Name "jQuery" -Url "" -Sequence 10 -Scope Site

Write-Host "- FormModifierLoader.js"

$site = Get-PnPSite
$fileUrl = $site.Url + "/Scripts/FormModifierLoader.js"

$jsLink = Get-PnPJavaScriptLink -Name "FormModifierLoader" -Scope Site

if ($jsLink -ne $null)
	Remove-PnPJavaScriptLink -Identity "FormModifierLoader" -Scope Site -Force

Write-Host $fileUrl

Add-PnPJavaScriptLink -Name "FormModifierLoader" -Url $fileUrl -Sequence 15 -Scope Site

Write-Host "Done."

To organize the files, we store the JavaScript files in a separate library called “Scripts”. And that’s all. After all scripts are available in the site collection and the loader script is registered, the desired functionality is available for the user.

The whole demo project is available in a GitHub project. To deploy the solution, a SharePoint team site with the classic UI must be created and the PowerShell PnP extensions must be available.



Caml query to find all items in a list

To get all list items in a list (or library) in SharePoint Online with the client side object model, a simple caml query is needed. I usually use this one:

	    <FieldRef Name='ID' />
		<Value Type='Number'>0</Value>