Thursday, April 27, 2017

SharePoint 2013 - Sign in as a different user

I keep forgetting this, so noting it down here:


Wednesday, April 19, 2017

Calling constructor of an internal class

I keep running into code that tries to "hide" from being used such as making classes internal or private. It is a royal pain in the ass when debugging.

Fortunately, reflection is very easy with powershell so we can do something like this:

$parameters = @(some-array-of-parameters)
$typeName = 'full-name-of-the-type'
Add-Type -AssemblyName $assemblyName
$assembly = [Reflection.Assembly]::Load($assemblyName)
$bindingFlags = [Reflection.BindingFlags]"Default,NonPublic" # also include Static if needed
$t = $assembly.GetType($typeName)
$m = $t.GetConstructors() | Where-Object {$_.GetParameters().Count -gt 0} # in my case, I happen to be looking for a non-default constructor
$myclassinstance = $m.Invoke($parameters)

Tuesday, April 4, 2017

SocialDataManager.SocialDataManager Proxy has no ServiceContext available

Just ran into this issue when trying to instantiate Microsoft.Office.Server.SocialData.SocialTagManager in powershell:

$siteUrl = 'some-site-url'
$site = Get-SPSite $siteUrl
$serviceContext = Get-SPServiceContext($site)
$msstm = New-Object Microsoft.Office.Server.SocialData.SocialTagManager($serviceContext)

New-Object : Exception calling ".ctor" with "1" argument(s): "UserProfileApplicationNotAvailableException_Logging :: SocialDataManager.SocialDataManager Proxy has no ServiceContext available."
At line:1 char:10
+ $msstm = New-Object Microsoft.Office.Server.SocialData.SocialTagManager($service ...
+          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodInvocationException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

Not much out there, but the UserProfileApplicationNotAvailableException provided a clue. I did not track down the specific cause, but it looks like I was not running powershell with an account that admin permissions in the UPA or MMS. I did not have time to dig further, but instead simply opened up my powershell as the farm account and did not run into the same problem.

Wednesday, March 22, 2017

Finding Alias for SharePoint Email Enabled Lists

As usual, there are several ways to do this that can be readily found via a search

Powershell: Loop through each Web Application, Site Collection (SPSite), Subweb (SPWeb), List. Then look in the EmailAlias property for what you are searching. In large environments, I suspect that this would be very slow and resource intensive. Here is a Foreach-Object pipeline that would do the trick:

Get-SPWebApplication | ForEach-Object {$_.Sites} | ForEach-Object {$_.AllWebs} | ForEach-Object {$_.Lists} | Where-Object {$_.CanReceiveEmail -and $_.EmailAlias} | Format-Table EmailAlias, Title, ParentWebUrl -AutoSize

SQL: One way is to essentially do the above but via the content databases, but this one also seems resource intensive:

USE [Some_Content_DB]
SELECT tp_Title, tp_EmailAlias, FullUrl
  FROM [dbo].[AllLists] lists
  LEFT JOIN [dbo].[AllWebs] webs ON lists.tp_WebId = webs.Id
  WHERE tp_EmailAlias IS NOT NULL

SQL: I decided to see what the Microsoft SharePoint Foundation Incoming E-Mail timer job does (job-email-delivery) since the timer job should be quite fast. Looking at the code, I can see that it calls the proc_getEmailEnabledListByAlias stored procedure. Diving into that, I see that this may be a better query:

SELECT * FROM [SharePoint_Config].[dbo].[EmailEnabledLists] 

However, I did also run across a post mentioning that it is possible the Config database and the Content database can be out of sync. So, it may still be necessary to choose the correct method depending on the problem one is trying to tackle.

Wednesday, December 28, 2016

Faking Microsoft.SharePoint.ServiceContext.Current with Powershell

While debugging some server side code, I tried to mimic it in Powershell. The challenge was that the backend code relied on Microsoft.SharePoint.SPServiceContext.Current. Fortunately, there are many posts on how to do this including:

Frustratingly, none of this was working when I tried. I was running as the Farm Account.

Then, I came across this:

I normally use just the Windows Powershell while on my servers and call Add-PSSnapin Microsoft.SharePoint.Powershell. However, I forgot that the SPServiceContext::Current is being lost when a new thread is being used.

I added the following and all is good again:
$Host.RunSpace.ThreadOptions = 'ReuseThread' 

Outlook add-in logging

I recently inherited support of an Outlook plugin (add-in) and needed to output a few more debugging statements. I put those lines into the code, but not events were logged into the Event Viewer Application Log as expected. Fumbling around I saw this: and added an environment variable VSTO_SUPPRESSDISPLAYALERTS = 0.

Wednesday, November 23, 2016

SPList.GetItems(SPQuery) appears to miss items if paging info not precise

We have some code that uses SPList.GetItems(SPQuery) with paging info.

The list items we were running against had the following values:

ID   Created
--   -------
51   8/30/2016 8:02:40 AM
49   8/12/2016 2:42:26 PM
48   6/27/2016 3:39:05 AM
46   6/21/2016 4:04:28 PM
45   6/21/2016 3:10:18 PM
44   6/21/2016 2:32:13 PM
43   6/21/2016 3:56:01 AM
42   6/20/2016 6:32:34 AM
41   6/20/2016 4:55:47 AM
39   6/14/2016 1:30:05 PM <-- The last item on page 1
38   6/14/2016 11:34:51 AM <-- Should be the first item on page 2
37   6/14/2016 10:21:22 AM <-- With our bad code, this one is first on page 2
36   6/14/2016 8:48:43 AM
35   6/9/2016 12:56:16 AM
32   5/25/2016 11:38:44 PM
29   5/9/2016 9:43:31 AM
28   5/9/2016 9:35:38 AM
26   4/28/2016 8:19:59 AM

Due to a bug in our code (timezone conversion!), we were providing an SPListItemCollectionPosition containing an incorrect value for the Created property. As a result, SPList.GetItems gets the first row that matches both criteria. This leads to the appearance that the paginated data is missing rows.

For example:

$webUrl = 'some-web-url';
$rowLimit = 10;
$goodPage = 'Paged=TRUE&p_ID=39&p_Created=20160614%2013%3A30%3A05';
$badPage  = 'Paged=TRUE&p_ID=39&p_Created=20160614%2011%3A30%3A05';

$web = Get-SPWeb $webUrl;
$list = $web.Lists['some-list'];
$spquery = New-Object Microsoft.SharePoint.SPQuery;
$spquery.Query = "<OrderBy><FieldRef Name='Created' Ascending='False' /></OrderBy>";
$spquery.RowLimit = $rowLimit;
$spquery.ListItemCollectionPosition = New-Object Microsoft.SharePoint.SPListItemCollectionPosition($goodPage);
$list.GetItems($spquery) | Format-Table ID, Name, @{l='Created'; e={$_['Created']}} -AutoSize;
$spquery.ListItemCollectionPosition = New-Object Microsoft.SharePoint.SPListItemCollectionPosition($badPage);
$list.GetItems($spquery) | Format-Table ID, Name, @{l='Created'; e={$_['Created']}} -AutoSize;
$list.GetItems("Id", "Created", "Name") | Format-Table ID, Name, @{l='Created'; e={$_['Created']}} -AutoSize;

Using the above powershell, the results from $goodPage works as expected. However, with $badPage, the time is off by 2 hours (we provided 11:30:05 instead of 13:30:05). Since we are sorting descending by Created, the wrong page info value causes the entry at 11:34:51 to be skipped as well. Oops!