Second Life of a Hungarian SharePoint Geek

April 23, 2014

Who Has Deployed This Solution?

Filed under: PowerShell, Reflection, SP 2010, Tips & Tricks — Tags: , , , — Peter Holpar @ 22:09

Recently we had a problem in one of our server farms that was caused by a sandboxed solution that was deployed by mistake as farm solution as well. I wanted to know who has deployed the farm solution, but in the Central Administration we can see only the time of the deployment, but there is no information regarding the person who performed the action:

image

If we submit the following SQL query in the configuration database of the farm (using the name of the solution as the filter)…

  1. SELECT [Id]
  2.       ,[ClassId]
  3.       ,[ParentId]
  4.       ,[Name]
  5.       ,[Status]
  6.       ,[Version]
  7.       ,[Properties]
  8.   FROM [SharePoint_Config].[dbo].[Objects]
  9.   WHERE [Name] = 'addispname.wsp'

… we should receive two records as result that include XML objects in the Properties fields like these ones:

  1. <object type="Microsoft.SharePoint.Administration.SPPersistedFile, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
  2.     <sFld type="Int64" name="m_FileSize">4748</sFld>
  3.     <fld type="System.Collections.Hashtable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="m_UpgradedPersistedFields" />
  4.     <fld name="m_Properties" type="null" />
  5.     <sFld type="String" name="m_LastUpdatedUser">CONTOSO\Administrator</sFld>
  6.     <sFld type="String" name="m_LastUpdatedProcess">vssphost4 (5876)</sFld>
  7.     <sFld type="String" name="m_LastUpdatedMachine">DEMO2010A</sFld>
  8.     <sFld type="DateTime" name="m_LastUpdatedTime">2013-08-22T00:01:04</sFld>
  9. </object>
  10. <object type="Microsoft.SharePoint.Administration.SPSolution, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
  11.     <sFld type="Guid" name="m_Id">31079555-a0db-4dce-8ca4-51e3e40cb6d1</sFld>
  12.     <sFld type="Boolean" name="m_WebPartPackage">False</sFld>
  13.     <sFld type="Guid" name="m_Wppid">00000000-0000-0000-0000-000000000000</sFld>
  14.     <fld type="Microsoft.SharePoint.Administration.SPServerRole, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" name="m_DeploymentServerType">WebFrontEnd</fld>
  15.     <sFld type="Boolean" name="m_HasWebAppResource">False</sFld>
  16.     <fld type="System.Collections.Hashtable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="m_UpgradedPersistedFields" />
  17.     <fld name="m_Properties" type="null" />
  18.     <sFld type="String" name="m_LastUpdatedUser">CONTOSO\Administrator</sFld>
  19.     <sFld type="String" name="m_LastUpdatedProcess">vssphost4 (5876)</sFld>
  20.     <sFld type="String" name="m_LastUpdatedMachine">DEMO2010A</sFld>
  21.     <sFld type="DateTime" name="m_LastUpdatedTime">2013-08-22T00:01:04</sFld>
  22. </object>

As you can see, one of the objects (SPSolution) describes the solution itself, the other one (SPPeristedFile) describes the persisted file that belongs to the solution. From the properties of the persisted file we can read the information we need, see m_LastUpdatedUser.

If you don’t like the idea to query the SharePoint content database directly, there is an other way to achieve the same information, for example using PowerShell and a bit of Reflection.

First we get a reference to our solution either by ID (as long it is known):

$solution = Get-SPSolution -Identity ‘31079555-a0db-4dce-8ca4-51e3e40cb6d1’

or by Name:

$solution = Get-SPSolution | ? { $_.Name -eq ‘addispname.wsp’ }

We can get the persisted file of the solution via the SolutionFile property, then using Reflection we can read its internal LastUpdateInfo property that contains the information regarding the user that deployed the solution:

$persistedFile = $solution.SolutionFile
$persistedFileType = $persistedFile.GetType()
$bindingFlags = [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance
$pi_LastUpdateInfo = $persistedFileType.GetProperty(‘LastUpdateInfo’, [System.Reflection.BindingFlags]($bindingFlags))
$lastUpdateInfo = $pi_LastUpdateInfo.GetValue($persistedFile, $null)
Write-Host $lastUpdateInfo

We should have an output similar to this one:

User: CONTOSO\Administrator
Process:vssphost4 (5876)
Machine:DEMO2010A
Time:August 22, 2013 12:01:04.0000

Beyond the user, one can find other potentially interesting information as well, including the host the solution was deployed from, and the process used to deploy the solution (executable + process ID a.k.a. PID). In the sample above the solution was deployed from Visual Studio, but in other cases the value can be for example powershell (4736) that means it was deployed using PowerShell.

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: