Sunday, December 12, 2010

Install/Uninstall User Solution Application Wide

Build on this blog post on how to get sandboxed on the farm, I also need to be able to install/uninstall sandboxed solution farm wide. There for I made they have two functions to wrap the install and Uninstall-SPUserSolution SPUserSolution.

The core code is when a call (a version 2) of the Get-UserSolution filter to get the deactiveated solutions and then call the build-in cmdlet Install-SPUserSolution

  1. $gc = Start-SPAssignment
  2. Get-UserSolution -SiteCollection $SiteCollection -Filter $Filter -Verboses:$Verboses | `
  3. Where-Object -FilterScript { $_.Status -eq "Deactivated" } | `
  4. Install-SPUserSolution -Site $SiteCollection -AssignmentCollection $gc
  5. Stop-SPAssignment $gc


The code:

Get sandboxed solution on the farm

How to get all sandboxed (user solution) installed on the SharePoint farm.

  1. $gc = Start-SPAssignment
  2. $gc | Get-SPSite | Get-SPUserSolution
  3. Stop-SPAssignment $gc


The output:



Name                                SolutionId                                                      Status

----                                     ----------                                                         ------


Contacts.wsp                   3089ef04-527e-4b35-a0a2-af5f4df8a71b     Activated


Sandboxed1.wsp              a9240922-c794-433c-acf7-0ce7863b46d0 Deactivated


Sandboxed1.1.wsp           a9240922-c794-433c-acf7-0ce7863b46d0 Activated


Sandboxed1.1.wsp           a9240922-c794-433c-acf7-0ce7863b46d0 Activated


Sandboxed1.2.wsp           a9240922-c794-433c-acf7-0ce7863b46d0 Deactivated


Sandboxed1.wsp              a9240922-c794-433c-acf7-0ce7863b46d0 Activated



It is really simple to get a full list of sandboxed solutions, but the output is not useful, because we can see which site collection the sandboxed solution is store in.



This small PowerShell script will display the site collection url



  1. function Get-UserSolution
  2. {
  3. param(
  4. [Parameter(
  5. Position=0,
  6. Mandatory=$true,
  7. ValueFromPipeline=$true,
  8. ValueFromPipelineByPropertyName=$true)
  9. ]
  10. $SiteCollection
  11. )
  12. process
  13. {
  14. Write-host "Site Collection:" $SiteCollection.Url
  15. $gc = Start-SPAssignment
  16. $SiteCollection | Get-SPUserSolution -AssignmentCollection $gc
  17. Stop-SPAssignment $gc
  18. }
  19. }
  20. Get-SPSite | Get-UserSolution


The output:



Site Collection: http://win-ugka6ujlm21



Name                               SolutionId                                                       Status               
----                                    ----------                                                          ------               
Contacts.wsp                   3089ef04-527e-4b35-a0a2-af5f4df8a71b     Activated            
Sandboxed1.wsp              a9240922-c794-433c-acf7-0ce7863b46d0 Deactivated          
Sandboxed1.1.wsp           a9240922-c794-433c-acf7-0ce7863b46d0 Activated            
Sandboxed1.1.wsp           a9240922-c794-433c-acf7-0ce7863b46d0 Activated            
Sandboxed1.2.wsp           a9240922-c794-433c-acf7-0ce7863b46d0 Deactivated          
Site Collection: http://win-ugka6ujlm21/my


Site Collection: http://win-ugka6ujlm21/sites/sandbox


Sandboxed1.wsp              a9240922-c794-433c-acf7-0ce7863b46d0 Activated  



The code:

Saturday, November 6, 2010

Windows 7 Favorites and SharePoint

One of the many cool features in Windows 7 is the Favorites

This is a list of “shortcut” that is display in the Windows Explore and in the “save as” dialog in programs like Word.

clip_image001

clip_image003

The Windows 7 Favorites works by creating a shortcut to folder and this goes for WebDav folders to.

To setup the a shortcut to a SharePoint site

To setup the shortcut and you only need to do this one time. Open Word and to go “save as” (the shortcut for this is F12), enter the url for the SharePoint site in the file name (Only the url!) and click enter or click on the save button. Then right click on the clip_image004 and select “Add current location to Farvorites” and wola your SharePoint is add and it is easy to browse next time when you want to save a document. clip_image006

Monday, November 1, 2010

IE 9, site pinning, overlay icons and SharePoint

One of the new thing in IE 9 is the site pinning. A cool new feature that allows a users to add a tab in IE9 to the taskbar. After the tab is added to the taskbar we can, from IE 9, interact with it, like overlay icons and ther is it where SharePoint comes in, as the data provider. I create an announcements list and read the current count from it and set the overlay icons to match the count all through JavaScript.

The results of adding two list items to announcements list image

My code

This is the code in the PlaceHolderAdditionalPageHead content placeholder

  1. <script src="http://ajax.Microsoft.com/ajax/jQuery/jquery-1.4.2.min.js" type="text/javascript"></script>




This is the code in the PlaceHolderMain content placeholder



  1. <span id="statusInfomation">Loading...</span>
  2. <script type="text/javascript">
  3. var loadingIcon = "/_layouts/images/jumplist/search.ico"
  4.  
  5. var getData = function()
  6. {
  7. $.getJSON("/ie9test/_vti_bin/listdata.svc/Ie9TestAnno()/$count", function (data)
  8. {
  9. if(data != 0 && data < 6)
  10. {
  11. var icon = "/_layouts/images/jumplist/num_" + data + ".ico";
  12. setOverlayIcon(icon, "Now got " + data);
  13. }
  14. else if(data == 0)
  15. {
  16. setOverlayIcon("", "Now got " + data);
  17. }
  18. });
  19. }
  20.  
  21. function setOverlayIcon(url, text)
  22. {
  23. $("#statusInfomation").html(text);
  24. if(url != "")
  25. {
  26. window.external.msSiteModeSetIconOverlay(url, text);
  27. }
  28. else
  29. {
  30. window.external.msSiteModeClearIconOverlay();
  31. }
  32. }
  33.  
  34. $(document).ready(function()
  35. {
  36. setOverlayIcon(loadingIcon, "Loading...");
  37. setInterval(getData, 5000);
  38. });
  39. </script>




In function in line 21, is where I interact with the overlay icons, pure magic :D



- Happy IE 9 coding

Saturday, October 30, 2010

List the controls added to a SPDelegate on a Website

I need to inspect a delegate control, to discover which control there is add to it. So I create this PowerShell code to create a HttpContext, set the right Current.Items to be a real SharePoint context. Create a SharePoint Delegate Control, set the properties and then invoke CreateChildControls on it and out put the result on the screen.

image

  1. [System.Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null
  2. [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") | Out-Null
  3.  
  4. #parm
  5. $delegateControlId = "SmallSearchInputBox"
  6. $weburl = "/cwd"
  7. $hosturl = "http://win-ugka6ujlm21"
  8. $absoluteUrl = $hosturl+$weburl
  9.  
  10. #creating a fake httpcontext
  11. $request = New-Object "System.Web.HttpRequest" "", $absoluteUrl, ""
  12. $stringWriter = New-Object "System.IO.StringWriter"
  13. $httpResponse = New-Object "System.Web.HttpResponse" $stringWriter
  14. [System.Web.HttpContext]::Current = New-Object "System.Web.HttpContext" $request, $httpResponse
  15.  
  16. #HACK - Need a 'Microsoft.SharePoint.SPWeb' not a 'System.Management.Automation.PSObject'
  17. [System.Web.HttpContext]::Current.Items["HttpHandlerSPWeb"] = (Get-SPSite -Identity $hosturl).OpenWeb($weburl, $false)
  18.  
  19. #create and set properties for the delegate control
  20. $dc = New-Object "Microsoft.SharePoint.WebControls.DelegateControl"
  21. $dc.AllowMultipleControls = $true
  22. $dc.ControlId = $delegateControlId
  23.  
  24. #create a method object and invole the method
  25. $bindingFlags = [Reflection.BindingFlags] "NonPublic,Instance"
  26. $method = $dc.GetType().GetMethod("CreateChildControls", $bindingFlags)
  27. $method.Invoke($dc, @());
  28.  
  29. #list the child controls
  30. $dc.Controls | %{
  31. $_.GetType().BaseType
  32. }
  33.  
  34. #dispose
  35. $StringWriter.Dispose | Out-Null
  36. $httpResponse.Close() | Out-Null


The code:

Tuesday, September 21, 2010

Health Analyzer Demo

What is health analyzer? This is the copy/pasta from msdns Overview of SharePoint Health Analyzer “SharePoint Health Analyzer is a feature in Microsoft SharePoint Foundation 2010 that enables administrators to schedule regular, automatic checks for potential configuration, performance, and usage problems in the server farm.”

So what we need to create a health analyzer rule?

  1. Create a subclass of the SPHealthAnalysisRule or SPRepairableHealthAnalysisRule
  2. Register the rule
  3. Test/execute the rule

1) Create a subclass

In this demo I create a subclass of the SPRepairableHealthAnalysisRule and besides for implement the abstract properties from SPRepairableHealthAnalysisRule, I also override Check and Repair method.

The Check method is used to identify a single potential problem in the SharePoint environment. In this demo we are a test if a very important file exists on the c: drive.

  1. public override SPHealthCheckStatus Check()
  2. {
  3. FileInfo info = new FileInfo(@"c:\importantfile.txt");
  4. return info.Exists ? SPHealthCheckStatus.Passed : SPHealthCheckStatus.Failed;
  5. }




Repair method is used to repair the problem that if the Check method return SPHealthCheckStatus.Failed. In the demo we just create the very important file on the c drive.



  1. public override SPHealthRepairStatus Repair()
  2. {
  3. try
  4. {
  5. if (Check().Equals(SPHealthCheckStatus.Failed))
  6. {
  7. FileInfo info = new FileInfo(@"c:\importantfile.txt");
  8. info.Create();
  9. return SPHealthRepairStatus.Succeeded;
  10. }
  11. else
  12. {
  13. return SPHealthRepairStatus.Succeeded;
  14. }
  15. }
  16. catch
  17. {
  18. //TODO: Log the error
  19. return SPHealthRepairStatus.Failed;
  20. }
  21. }




2) Register the rule



Microsoft has a “How to: Create a Feature to Register a Health Rule” where they use a feature receiver to register rule with. But I’m big PowerShell fan, so it was naturally for me to create a simple PowerShell script to register and unregister.



Register PowerShell:



First we load the SharePoint DLL and my custom DLL. Then we call the static RegisterRules method with take the custom assembly as parameter. The RegisterRules return an IDictionary<Type, Exception>. We test if the IDictionary<Type, Exception> count is 0, if not, we display the exceptions by pipe the collection to the Format-List cmdlet.



  1. [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") | Out-Null
  2. $assembly = [System.Reflection.Assembly]::LoadWithPartialName("HealthAnalyzerDemo")
  3. $exceptions = [Microsoft.SharePoint.Administration.Health.SPHealthAnalyzer]::RegisterRules($assembly);
  4. if($exceptions -ne $null)
  5. {
  6. if($exceptions.Count -eq 0)
  7. {
  8. Write-Host "All rules were registered.";
  9. }
  10. else
  11. {
  12. $exceptions | fl
  13. }
  14. }
  15. $assembly = $null




Unregister PowerShell:



The only difference between the register script and the unregister script is, instead of call the RegisterRules method we call the UnRegisterRules.



  1. [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") | Out-Null
  2. $assembly = [System.Reflection.Assembly]::LoadWithPartialName("HealthAnalyzerDemo")
  3. $exceptions = [Microsoft.SharePoint.Administration.Health.SPHealthAnalyzer]::UnregisterRules($assembly);
  4. if($exceptions -ne $null)
  5. {
  6. if($exceptions.Count -eq 0)
  7. {
  8. Write-Host "All rules were unregistered.";
  9. }
  10. else
  11. {
  12. $exceptions | fl
  13. }
  14. }
  15. $assembly = $null




3) Test/execute the rule



Microsoft has a “How to: Test a Health Rule During Development” where they use a console application to test/execute the health rule. But this is so obviously a PowerShell thing :)



Execute rule PowerShell:



First we load the SharePoint DLL and my custom DLL. Then we create a new object of the rule class. Write the current return status from the Check method. Test if the status is equal to failed, if it is, we call the Repair method.



  1. [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") | Out-Null
  2. [System.Reflection.Assembly]::LoadWithPartialName("HealthAnalyzerDemo") | Out-Null
  3. $checkIfFileOnDiskExistRuleRepair = New-Object "HealthAnalyzerDemo.HealthAnalyzers.CheckIfFileOnDiskExistRuleRepair"
  4. $status = $checkIfFileOnDiskExistRuleRepair.Check()
  5. Write-Host "Status for"$checkIfFileOnDiskExistRuleRepair.Summary"is:"$status
  6. if($status -eq [Microsoft.SharePoint.Administration.Health.SPHealthCheckStatus]::Failed)
  7. {
  8. Write-Host "Calling the Repair method"
  9. Write-Host "Result:" $checkIfFileOnDiskExistRuleRepair.Repair()
  10. }




Summary:



It's really easy to make rules, that will give the It-pros a fight change to managed and maintain the SharePoint platform. Microsoft has some “Guidelines for Designing Health Rules”.



My demo code

Tuesday, September 14, 2010

Using GeSHi to syntax higligh

I just found this great tool to create syntax highligt in Windows Live Writer.

The tool is call GeSHi (Generic Syntax Highlighter) and has the following goals:

  1. Support for a wide range of popular languages.
  2. Easy to add a new language for highlighting.
  3. Highly customisable output formats.

For more infomation:

image

Managing Custom Areas and Categories with Powershell

The patterns & practices SharePoint Guidance team has posted this article on how to manag custom areas and categories i SharePoint 2010 http://msdn.microsoft.com/en-us/library/ff798462.aspx. But all the examples is written in C# (and that’s a good thing Smile) but I don’t want to have to use a feature receiver add my custom areas and categories, so I have create this demo PowerShell script, strongly inspire by the Microsoft article.

  1. [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Practices.ServiceLocation") | Out-Null
  2. [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Practices.SharePoint.Common") | Out-Null
  3.  
  4. #EventSeverity Description
  5. # None Indicates no event entries are written.
  6. # ErrorCritical Indicates a problem state that needs the immediate attention of an administrator.
  7. # Error Indicates a problem state requiring attention by a site administrator.
  8. # Warning Indicates conditions that are not immediately significant but that may eventually cause failure.
  9. # Information Contains noncritical information provided for the administrator.
  10. # Verbose
  11.  
  12. #TraceSeverity Description
  13. # None Writes no trace information to the trace log file.
  14. # Unexpected Represents an unexpected code path and actions that should be monitored.
  15. # Monitorable Represents an unusual code path and actions that should be monitored.
  16. # High Writes high-level detail to the trace log file.
  17. # Medium Writes medium-level detail to the trace log file.
  18. # Verbose Writes low-level detail to the trace log file.
  19.  
  20. #Create a List<DiagnosticsArea> to collect the Diagnostics Area
  21. $areaCollection = New-Object 'System.Collections.Generic.List[Microsoft.Practices.SharePoint.Common.Logging.DiagnosticsArea]'
  22.  
  23. #Add a DiagnosticsArea with the name Custom Area
  24. $customArea = New-Object 'Microsoft.Practices.SharePoint.Common.Logging.DiagnosticsArea' -ArgumentList "Custom Area"
  25. #Add a DiagnosticsCategory, to the Custom Areas DiagnosticsCategories collection, with the name Business logic, EventSeverity set to Warning and TraceSeverity to Medium
  26. $customArea.DiagnosticsCategories.Add((New-Object 'Microsoft.Practices.SharePoint.Common.Logging.DiagnosticsCategory'("Business logic", ([Enum]::Parse([Microsoft.SharePoint.Administration.EventSeverity], 'Warning')), ([Enum]::Parse([Microsoft.SharePoint.Administration.TraceSeverity], 'Medium')))))
  27. #Add a DiagnosticsCategory, to the Custom Areas DiagnosticsCategories collection, with the name Data layer, EventSeverity set to Error and TraceSeverity to Medium
  28. $customArea.DiagnosticsCategories.Add((New-Object 'Microsoft.Practices.SharePoint.Common.Logging.DiagnosticsCategory'("Data layer", ([Enum]::Parse([Microsoft.SharePoint.Administration.EventSeverity], 'Error')), ([Enum]::Parse([Microsoft.SharePoint.Administration.TraceSeverity], 'Medium')))))
  29. #Add the Custom Area to the List<DiagnosticsArea> collection
  30. $areaCollection.Add($customArea)
  31.  
  32. #Create a new DiagnosticsArea witht the name Test Area and adds it to the List<DiagnosticsArea> collection
  33. $areaCollection.Add((New-Object 'Microsoft.Practices.SharePoint.Common.Logging.DiagnosticsArea' -ArgumentList "Test Area"))
  34.  
  35. #Get a IConfigManager from the SharePointServiceLocator
  36. $configManager =[Microsoft.Practices.SharePoint.Common.ServiceLocation.SharePointServiceLocator]::GetCurrent().GetInstance([Microsoft.Practices.SharePoint.Common.Configuration.IConfigManager])
  37.  
  38. #Create a new DiagnosticsAreaCollection with the IConfigManager as parameter
  39. $configuredAreas = New-Object 'Microsoft.Practices.SharePoint.Common.Logging.DiagnosticsAreaCollection' $configManager
  40.  
  41. #loop through the newly collection of diagnosticsareas
  42. $areaCollection | % {
  43.  
  44. #get the instance from the current configuration
  45. $existingArea = $configuredAreas[$_.Name]
  46.  
  47. #if the area the is null, we add add the area from the List<DiagnosticsArea> collection
  48. #else we loop through the collection we got from current configuration
  49. if($existingArea -eq $null)
  50. {
  51. $configuredAreas.Add($_)
  52. }
  53. else
  54. {
  55. #loop through the collection we got from current configuration
  56. $customArea.DiagnosticsCategories | % {
  57.  
  58. #get the category instance from the $existingArea (DiagnosticsArea)
  59. $existingCategory = $existingArea.DiagnosticsCategories[$_.Name]
  60. #if the category is null, we add to the current configuration
  61. if($existingCategory -eq $null)
  62. {
  63. $existingArea.DiagnosticsCategories.Add($_);
  64. }
  65. }
  66. }
  67. }
  68. #save the current configuration
  69. $configuredAreas.SaveConfiguration()


The demo code.