Microsoft Teams channel with multiple linked SharePoint folders

Today a customer came to me with the following problem. They had managed to create two folders in SharePoint linked to the same Microsoft Teams channel. When they tried to delete the second folder they got the error message “To delete this folder, go to the channel in Microsoft Teams”

The steps below describe how I was able to reproduce this issue and how I managed to successfully delete the duplicate folder.

REPLICATING THE PROBLEM

Select the folder linked to the Teams channel and click the “Copy to” button

Copy the folder to the same document library and you will end up with two folders in the document library called General and General1 (the copy)

Select the newly copied General1 folder and you will see the “Go to channel” button, this is because both General and General1 folders are now linked to the General channel in Teams

Try deleting the General1 folder and you will get the error message “To delete this folder, go to the channel in Microsoft Teams”

Problem is that there is no channel General1 in Teams, because General1 is actually linked to the General channel, which can’t be deleted

I tried everything I could think of to delete the second folder, including CSOM, PowerShell and even SharePoint Designer but I always got the same error message

SOLUTION FOR DELETING THE FOLDER

Finally I stumbled on the following solution for deleting the folder. Select the folder and move it to your OneDrive

Presumably the SharePoint development team didn’t think anybody would be dumb enough to do this, so they didn’t throw the “To delete this folder, go to the channel in Microsoft Teams” error message spike strip in my path.

Once in my OneDrive I was able to delete the folder without puncturing any tires 🙂

Disable Firefox insecure password warning when testing with Selenium

If you use Selenium and Firefox version 52 or higher for testing your UI and your development site does not use SSL, then you will get the following warning when entering passwords on your login page “This connection is not secure. Logins entered here could be compromised”

Firefox will also open the URL https://support.mozilla.org/en-US/kb/insecure-password-warning-firefox?as=u&utm_source=inproduct in a new tab which takes the focus away from the page you are testing.

This is a great feature and will hopefully stop some users from giving away their passwords over insecure connections. However if you are a developer/tester this is a very annoying feature and breaks your Selenium/Firefox tests during the development phase.

You can stop this warning and the new tab opening by changing the Firefox preference security.insecure_field_warning.contextual.enabled to false

I am using C# to run my tests so my code for setting up the Firefox driver looks something like this:


// Firefox driver setup
FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference("security.insecure_field_warning.contextual.enabled", false); // disable insecure password warning
IWebDriver driver = new FirefoxDriver(profile);

// more test code

Where is the Visual Studio 2017 MSBuild.exe?

If you have installed Visual Studio 2017 and need to use the latest MSBuild.exe CLI you may have discovered that it is no longer installed in %programfiles(x86)%\MSBuild\15.0\Bin\msbuild.exe

MSBuild.exe can now be found in %programfiles(x86)%\Microsoft Visual Studio\2017\<version_name>\MSBuild\15.0\Bin\msbuild.exe

Note that the <version_name> [Community|Professional|Enterprise] is now part of the path above.

Visual Studio 2015 Error Opening .cshtml File

PROBLEM

You double-click a .cshtml file in Visual Studio 2015 and you get an error “Object reference not set to an instance of an object”.

SOLUTION

  1. Close Visual Studio
  2. Delete all files in the folder %LocalAppData%\Microsoft\VisualStudio\14.0\ComponentModelCache
  3. Re-open Visual Studio
  4. You should now be able to open your .cshtml file

SharePoint Designer 2013 Workflow Suspended with HTTP 400 exception

I have a SharePoint Designer 2013 workflow which sometimes ends up in a Suspended state with the following cryptic HTTP 400 error:

RequestorId: af5849b3-e5e4-5875-0000-000000000000. Details: RequestorId: af5849b3-e5e4-5875-0000-000000000000. Details: An unhandled exception occurred during the execution of the workflow instance. Exception details: System.ApplicationException: HTTP 400 {“Transfer-Encoding”:[“chunked”],”X-SharePointHealthScore”:[“0″],”SPClientServiceRequestDuration”:[“44″],”SPRequestGuid”:[“af5849b3-e5e4-5875-bc88-32fb13dd46f3″],”request-id”:[“af5849b3-e5e4-5875-bc88-32fb13dd46f3″],”X-FRAME-OPTIONS”:[“SAMEORIGIN”],”MicrosoftSharePointTeamServices”:[“15.0.0.4481″],”X-Content-Type-Options”:[“nosniff”],”X-MS-InvokeApp”:[“1; RequireReadOnly”],”Cache-Control”:[“max-age=0, private”],”Date”:[“Tue, 29 Apr 2014 22:21:08 GMT”],”Server”:[“Microsoft-IIS\/7.5″],”X-AspNet-Version”:[“4.0.30319″],”X-Powered-By”:[“ASP.NET”]} at Microsoft.Activities.Hosting.Runtime.Subroutine.SubroutineChild.Execute(CodeActivityContext context) at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager) at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

workflowemailerror01

I knew this was happening on a “Send an email” action in the workflow, but was having some trouble tracking down the issue and couldn’t find anything obviously wrong with the way things were setup.

After increasing the diagnostic logging levels I finally came across the following error in the ULS log:

Exception occured in scope Microsoft.SharePoint.Utilities.SPUtility.SendEmail. Exception=System.ArgumentException: The specified string is not in the form required for a subject.
at System.Net.Mail.Message.set_Subject(String value)
at Microsoft.SharePoint.Utilities.SPUtility.SendEmail_Client(EmailProperties properties)
at Microsoft.SharePoint.ServerStub.Utilities.SPUtilityServerStub.InvokeStaticMethod(String methodName, ClientValueCollection xmlargs, ProxyContext proxyContext, Boolean& isVoid)
at Microsoft.SharePoint.Client.ServerStub.InvokeStaticMethodWithMonitoredScope(String methodName, ClientValueCollection args, ProxyContext proxyContext, Boolean& isVoid)

The email being sent out used the customer name in the subject line.

workflowemailerror03

In this particular instance the customer name was coming from an InfoPath form and when I looked in the form I found a carriage return and line feed at the end of the customer name which was causing the error.

workflowemailerror02

I fixed the source data which was causing the problem, but I still had forms which included the bad data. I thought if I could strip out the carriage return and line feed in the workflow before sending the email that would solve my problem.

Unfortunately there is no built-in workflow actions to do this kind of string replacement with special characters. So I even went to the trouble of trying to create my own custom SharePoint 2103 workflow action to do this, thinking that it would be reusable.

workflowemailerror04

Setting ResultString to SourceString.Replace(“\r\n”, “”)

The custom action stubbornly refuses to work with escaped characters. I tried every variation of this I could imagine even using characters escaped for Regex expressions, as under the hood the workflow engine is using Regex to do the replacement. The custom action works beautifully if you use a regular string replacement like SourceString.Replace(“abc”, “”), but special characters it does not like. I finally gave up with this approach and fixed the bad data in the form before the workflow got fired.

List all alerts in a SharePoint farm

The PowerShell below allows you to list out in CSV format all the Alerts users have set on all lists in all sites, in all site collections, in all the web applications in a SharePoint Farm.

This script is a modification of the script at http://www.deliveron.com/blog/post/Find-all-Alerts-in-a-Site-Collection-in-SharePoint-2010.aspx by Jess Collicott which listed a site collection’s alerts.

####################################################################################################
#
#  Author.......: Khalid Ansari
#  Date.........: 07 Apr 2014
#  Description..: Output alerts set on all sites in all site collections in all web apps in the farm
#				  to a CSV file
#
####################################################################################################
Add-PSSnapin microsoft.sharepoint.powershell

$spAssignment = Start-SPAssignment

$webApps = Get-SPWebApplication -IncludeCentralAdministration
$alertResults = @()
foreach($webApp in $webApps)
{
    $webApp.url
	foreach ($site in $webApp.Sites) {
		$site.url
		foreach ($web in $site.AllWebs) {
			$web.url
			foreach ($alert in $web.Alerts){
				$alertResult = New-Object PSObject
				$alertResult | Add-Member -type NoteProperty -name "List URL" -value ($web.URL + "/" + $alert.ListUrl)
				$alertResult | Add-Member -type NoteProperty -name "Alert Title" -value $alert.Title
				$alertResult | Add-Member -type NoteProperty -name "Alert Type" -value $alert.AlertType
				$alertResult | Add-Member -type NoteProperty -name "Subscribed User" -value $alert.User
				$alertResults += $alertResult
			}
		}
	}
}
$alertResults

$alertResults | Export-CSV "FarmAlerts.csv"

Write-Host
Write-Host "Script Completed"
Stop-SPAssignment $spAssignment

The script will create a file called FarmAlerts.csv with a list of all the alerts.

Change SharePoint Management Shell default folder

I often pin the SharePoint Management Shell to the taskbar on SharePoint servers I am working on as shown below

spmgmtshellshortcut01

When I click on it I want it to open in a folder of my choice instead of the default, which is the users root folder.

Easy enough, but unfortunately you can’t just change the “Start in:” folder on the shortcut. You must change the “Target:” value instead. Every time I go to change the shortcut I mess it up because of the somewhat complicated target string.

I will show you how to change this target string to do what we want. First right-click on your taskbar shortcut, then right-click on the “SharePoint 2013 Management Shell” menu item, then click on propertiesspmgmtshellshortcut02

You will get the following dialog box:spmgmtshellshortcut03

Your “Target:” value should look like:

C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe -NoExit  ” & ‘ C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\CONFIG\POWERSHELL\Registration\\sharepoint.ps1′”

Edit this value and add the folder you want to open in as shown below

C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe -NoExit  ” & ‘ C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\CONFIG\POWERSHELL\Registration\\sharepoint.ps1’; cd D:\SharePoint\Scripts

Note that the new command goes between the last single and double quote of the original string.

Since all we are doing here is adding a PowerShell command, you could technically add any other commands you wanted or even run a script if you want.

Your shortcut will now open in the default folder of your choice

spmgmtshellshortcut04

Login prompt accessing list on SharePoint site with anonymous access enabled

PROBLEM

You have a SharePoint Publishing site with anonymous access enabled. Users are able to get to most of the pages and document libraries that you have exposed via anonymous access, but you have one or more lists which stubbornly prompt the user to login.

This problem also commonly occurs on anonymous access Blog sites living under a Publishing site where users are prompted to login to post comments. That is because comments are stored in a SharePoint list and this problem is related to SharePoint lists exposed to anonymous users.

SOLUTION

Many solutions to this problem suggest disabling the Site Collection feature ViewFormPagesLockdown as this is enabled by default on Publishing sites. This is a bad idea as it exposes various pages such as /layouts/viewlsts.aspx, more commonly known as Site Contents, that you do not want to give anonymous users access to. ViewFormPagesLockdown on an anonymous site is a good thing, but it does cause us grief with lists we want to expose anonymously.

I have created a PowerShell script below that enables anonymous access on a list living under a publishing site without having to resort to disabling the ViewFormPagesLockdown feature.

####################################################################################################
#
#  Author.......: Khalid Ansari
#  Date.........: 17 Jan 2014
#  Description..: Allow anonymous access to a list in a publishing site
#                 For details of the problem this script solves go to http://wp.me/p3Cf9P-aL
#  Parameters...: [Required] SiteUrl = Url of site (not site collection, unless they are the same)
#                 [Required] ListDisplayName = Display name of list
#
####################################################################################################
param(
    [parameter(Mandatory=$true)] [string] $SiteUrl
    , [parameter(Mandatory=$true)] [string] $ListDisplayName
)

$spAssignment = Start-SPAssignment

$web = Get-SPWeb $SiteUrl -ErrorAction Stop
Write-Host -f Green "Found site $($web.Title)"
$list = $web.Lists[$ListDisplayName]
if ($list) {
	Write-Host -f Green "Found list $($list.Title)"

	$list.BreakRoleInheritance($true, $false)
	$list.AllowEveryoneViewItems = $true
	Write-Host -f Yellow "Existing permissions: $($list.AnonymousPermMask64)"
	$list.AnonymousPermMask64 = "ViewPages, OpenItems, ViewVersions, Open, UseClientIntegration, ViewFormPages, ViewListItems";
	$list.Update();
	Write-Host -f Yellow "Updated permissions.: $($list.AnonymousPermMask64)"
	Write-Host -f Green "Anonymous access enabled on list"
}
else {
	Write-Host -f Red "List $($ListDisplayName) not found"
}

$web.Dispose()
Write-Host
Write-Host "Script Completed"
Stop-SPAssignment $spAssignment

Running the script above results in output similar to that shown below:

listanonaccess01

Note that in order to enable these permissions it is necessary for the script to break permission inheritance on the list. After running the above script your list should be accessible anonymously and you didn’t have to disable the ViewFormPagesLockdown feature.

Quick, cheap and easy documentation using video capture

Have you ever had to do project documentation? Do you want to do this quickly, cheaply and without poking yourself in the eye with a sharp stick? If so read on.

I often have to educate users, administrators and developers on how to work with the solution I have built for them. This usually involves some kind of knowledge transfer session at the end of which I have brain dumped a lot of new and overwhelming information on the customer, which they promptly forget!

I go into each project with the intention of walking away from the project knowing that the customer has enough knowledge to work with and take over the project after I have left, either using an internal team and/or or have an external consultant come in and continue maintaining and enhancing the project.

Typically documenting for the above purposes involves creating Word documents with screenshots. I have done a lot of these and they are time consuming and painful and typically end up on a SharePoint site or worse on a file share somewhere. They get out of date before the file dries on the disk and people forget about them instantly. Also you never want to read one of these documents with a sharp object lying nearby.

I hate this kind of documentation! It is dumb! It doesn’t work! It is costly! It is pointless! I refuse to do it anymore!

There is a better way to do documentation in a fraction of the time it takes to do dumb documentation. And it is easier to digest, it is easier to update, it conveys a thousand times more information in a much shorter period of time then it would take to read a dumb document. Oh and it is fun to do!

Video capture is the way to do this. I now make short YouTube style documentation videos for my customers. Typically 1-5 minutes long, although for some more complicated things I have made longer videos up to 15 minutes. I recommend keeping the videos short and under 5 minutes. This is much more digestible length and is easier to make and redo if you mess it up the first time. You can usually break longer videos down into shorter more digestible chunks.

Here is a sample video to show you what I am taking about.

I have done a little video below documenting how to do video captures using SnagIt which is my preferred tool for capturing these videos.

After making these videos I typically put them up in an Asset Library in a SharePoint site dedicated to documentation. I also use the site to put up the few and far between Word documents that I now produce as part of documenting solutions.

On a recent two month long project I was able to document everything future administrators and developers need to know to maintain and enhance the solution in 2.5 hours of video. Somebody brand new to the project could be up and running in under half a day! On some projects it has taken me up to a week of reading Word documents, poking around and talking to people to glean less information then I was able to convey in those 2.5 hours of video.

I now actually enjoy documenting solutions and would never go back to the old way of doing it. It just doesn’t make sense.

Visual Studio 2012 SharePoint .csproj Unsupported

I have run into this a few times now and I keep forgetting how to fix it, so it is time to document the solution.

PROBLEM

I install Visual Studio 2012 on a machine, connect to TFS and get latest on some SharePoint projects. I open the SharePoint project and get the following error message:

“These projects are either not supported or need project behavior impacting modifications to open in this version of Visual Studio. Projects not displayed either require no changes or will automatically be modified such that behavior is not impacted.

Unsupported
This version of Visual Studio does not have the following project types installed or does not support them. You can still open these projects in the version of Visual Studio in which they were originally created. For details, see More information.”

unsupportedproject01

And my first reaction is What do you mean you don’t support .csproj files. Those files were invented for you. If you don’t recognize them who will?

So then I the scour the Interweb come up with a bunch of useless suggestions about how I should run Devenv.exe /ResetSkipPkgs or better still uninstall Visual Studio, turn off the computer, wait 30 seconds, turn it on again, install Visual Studio, etc.

The solution shown below is simpler and doesn’t harm any humans in the process.

SOLUTION

The solution to this madness is to install the Office Developer Tools for Visual Studio 2012.

Open up the Web Platform Installer and if you don’t have it installed download and install it. Search for Office Developer Tools and install it.

unsupportedproject02

For some reason I never remember to do this, now if I can just remember that I wrote this article I won’t waste another hour of my life.