harleygreen.com
.net development
RSS-2.0

Harley Green

  • Avoid Security Trimming when using SPXMLContentMapProvider in MOSS 2007

    Had an interesting chat with MS Developer support today.

    Several weeks ago, we had a performance issue with a custom application hosted in MOSS 2007. By issue, I mean pages were loading exceedingly slowly, to the point where requests were timing out with some frequency. After much digging around, we eventually traced it to a custom site map file. We were using the SPXMLContentMapProvider with a custom sitemap file. The site map file had role information for each node, and the provider had securityTrimmingEnabled set to "true" in the web.config. Setting securityTrimmingEnabled to "false" immediately resolved the issue.

    After a fair bit of digging on their end, MS Developer support concluded that the SPXMLContentMapProvider should not be used with security trimming, or it could cause performance issues. Their recommendation was to " create a custom navigation provider inheriting from OOB SPXMLContentMapProvider and override the 'CreateChildNodes' method. You can implement the security trimming in the 'CeateChildNodes' method and can filter the nodes rather than relying on the parent SiteMapProvider which takes long time to do the security trimming in case of SPXMLContentMapProvider."
    10/28/2009 10:36:53 PM Published by Harley Green Category Sharepoint Comments 0
  • Sharepoint web.config updates via PowerShell

    OK - I know I'm slow to be blogging about SPWebConfigModification, but figured that I'd add a little value with a healthy dose of powershell.

    There are a number of approaches to using SPWebConfigModification to update the web.config (see here, here and here), but all of these essentially require deploying / retracting a feature to modify / retract the config modifications. It may just be that I'm a little picky, but I really don't want to have to deploy code to make a configuration change - kinda defeats the point of configuration IMHO. Of course, I really don’t want to log onto a bunch of different servers, and make manual updates to each, as the chance of my fat-fingering something is pretty high.

    Of late - whenever I'm dealing with something painful, I invariably turn to powershell and this was no exception. A quick translation of this example from Mark Wagner's blog:

     
    1. // Get an instance of my local web application   
    2. SPWebApplication webApp = new SPSite("http://localhost").WebApplication;   
    3.   
    4. // Create my new modification to set the mode attibute to "Off".  
    5. // Example: <customErrors mode="Off">   
    6. SPWebConfigModification modification = new SPWebConfigModification("mode""system.web/customErrors");  
    7. modification.Owner = "SimpleSampleUniqueOwnerValue";   
    8. modification.Sequence = 0;   
    9. modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute;   
    10. modification.Value = "Off";   
    11.   
    12. // Add my new web.config modification.   
    13. webApp.WebConfigModifications.Add(modification);   
    14.   
    15. // Save web.config changes.   
    16. webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();   
    17.   
    18. // Serialize the web application state and propagate changes across the farm.   
    19. webApp.Update();  

    Yields:

     
    1. $site = new-object Microsoft.SharePoint.SPSite -argumentList "http://localhost"  
    2. $webApplication = $site.WebApplication  
    3. $modification = New-Object -TypeName "Microsoft.SharePoint.Administration.SPWebConfigModification" -ArgumentList "mode""system.web/customErrors"  
    4. $modification.Value = "Off"  
    5. $modification.Owner = "SimpleSampleUniqueOwnerValue"  
    6. $modification.Sequence = 0  
    7. $modification.Type = "EnsureAttribute"  
    8. $webApplication.WebConfigModifications.Add($modification)  
    9. $method = [Microsoft.Sharepoint.Administration.SPServiceCollection].GetMethod("GetValue", [Type]::EmptyTypes)  
    10. $closedMethod = $method.MakeGenericMethod([Microsoft.Sharepoint.Administration.SPWebService])  
    11. $services = $webApplication.Farm.Services  
    12. $service = $closedMethod.Invoke($services, [Type]::EmptyTypes)  
    13. $service.ApplyWebConfigModifications()  
    14. $webApplication.Update()  
    15. $site.Dispose()  

    This is atypically more complex than the equivalent c# code above - almost entirely due to the generic "GetValue" method being called.

    Now, the only issue outstanding is to wrap it all up in a reusable script. I started down the path of using xml to define the configuration values, basically using Ryan's xsd . This does, unfortunately, get rather verbose due to the need to define each attribute in a given node. Once again - this was beginning to feel painful and my thoughts turned again to powershell - why not define the variables using powershell itself? If the configuration is a powershell script, I can simply dot-source it, and I'm good to go.

    Of course - I still need a convention to define the configuration, and eventually I settled on this:

     
    1. $mods =  
    2.     ,@{  
    3.     "name" = 'add[@key="TestConfig"]';  
    4.     "value" = '<add key="TestConfig" value="1000" />';  
    5.     "owner" = "hgreen";  
    6.     "path" = "/configuration/appSettings";  
    7.     "sequence" = "0";  
    8.     "type" = "EnsureChildNode";  
    9.     }  

    $mods is a list of Dictionary objects - each of which holds the relevant values to be used in the construction of a SPWebConfigModification. Defaults are provided for owner and sequence, the rest should all be provided by the configuration script. The driving force here was to keep the configuration script purely configuration.  This defines the modifications, and nothing else.

    The final script:

     
    1. param(  
    2.     $application = "$(throw 'application is a mandatory parameter.')",  
    3.     $fileName = "$(throw 'fileName is a mandatory parameter.')",  
    4.     [switch]$retract  
    5. )  
    6.   
    7. trap [Exception] {  
    8.       Write-Error $("TRAPPED: " + $_.Exception.GetType().FullName);  
    9.       Write-Error $("TRAPPED: " + $_.Exception.Message);   
    10.       if ($site -ne $null)  
    11.       { $site.Dispose() }  
    12.   
    13.    }  
    14.   
    15. function Coalesce-Args  
    16. {  
    17.     ([object[]]($args | Where-Object {$_}) + ,$null)[0]  
    18. }  
    19.   
    20. [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Sharepoint")   
    21.   
    22. $mods = $null  
    23. . (Resolve-Path $fileName)  
    24. $site = new-object Microsoft.SharePoint.SPSite -argumentList $application  
    25. $webApplication = $site.WebApplication  
    26.   
    27. #$mods should be initialized in input file  
    28. foreach($mod in $mods)  
    29. {  
    30.     $name = $mod.name  
    31.     $value = $mod.value  
    32.     $principal = [Security.Principal.WindowsIdentity]::GetCurrent()  
    33.     $owner = Coalesce-Args $mod.owner $principal.Name  
    34.     $path = $mod.path  
    35.     $sequence = Coalesce-Args $mod.sequence 0  
    36.     $type = $mod.type  
    37.       
    38.     $modification = New-Object -TypeName "Microsoft.SharePoint.Administration.SPWebConfigModification" -ArgumentList $name$path  
    39.     $modification.Value = $value  
    40.     $modification.Owner = $owner  
    41.     $modification.Sequence = $sequence  
    42.     $modification.Type = $type  
    43.       
    44.     if ($retract)  
    45.     {  
    46.         $webApplication.WebConfigModifications.Remove($modification)  
    47.     }  
    48.     else  
    49.     {  
    50.         $webApplication.WebConfigModifications.Add($modification)  
    51.     }  
    52.       
    53. }  
    54.   
    55. $method = [Microsoft.Sharepoint.Administration.SPServiceCollection].GetMethod("GetValue", [Type]::EmptyTypes)  
    56. $closedMethod = $method.MakeGenericMethod([Microsoft.Sharepoint.Administration.SPWebService])  
    57. $services = $webApplication.Farm.Services  
    58. $service = $closedMethod.Invoke($services, [Type]::EmptyTypes)  
    59. $service.ApplyWebConfigModifications()  
    60. $webApplication.Update()  
    61.   
    62. $site.Dispose()  

    This is available as a download here, this includes the sample configuration script shown above.
    2/7/2009 11:27:00 PM Published by Harley Green Category Sharepoint Comments 1
  • Using Powershell to get the strong name of an assembly

     

    Here's a short powershell script to get the strong name of an assembly:

     
    1. function Get-AssemblyName {  
    2. param($file)  
    3. $path = Resolve-Path $file  
    4. [System.Reflection.AssemblyName]::GetAssemblyName($path).FullName  
    5. }  

    If you add this to your profile, you can set up an external tool in Visual Studio to run this against the current project:

     


     

     

     


    12/3/2008 2:33:00 PM Published by Harley Green Category Powershell Comments 0
  • PowerText

    PowerText is a powershell snapin for file processing.
    The initial release has a single cmdlet - Import-DelimitedValues for importing character delimited values, available @ www.harleygreen.com/7/section.aspx/download/3

    Current cmdlets include:

    Import-DelimitedValues: Replacement for the Import-Csv cmdlet, providing the ability to specify the delimiter.

    This is an initial release, and is offered under the Apache 2.0 licence.

    Source code to follow shortly.

    Comments / criticism / suggestions are all welcome.

    Thanks
    Harley
    5/18/2008 11:08:00 PM Published by admin Category Powershell Comments 0
  • PowerQueue

    PowerQueue is a powershell snapin for accessing MSMQ messages and queues, available @ www.harleygreen.com/7/section.aspx/download/2

    Current cmdlets include:

    Clear-Queue: Purges all messages from a queue
    Get-Queue: Gets queues matching input parameters
    New-Queue: Creates a new queue
    Receive-Message: Reads / Peeks at messages in a queue
    Send-Message: adds a message to a queue
    Test-Queue: check if a queue exists

    This is an initial release, and is offered under the Apache 2.0 licence.

    Source code to follow shortly.
    update: These cmdlets have been included in Powershell Community Extentions - the source is available from codeplex @ http://www.codeplex.com/PowerShellCX

    Comments / criticism / suggestions are all welcome.

    Thanks
    Harley
    4/27/2008 11:39:00 PM Published by admin Category Powershell Comments 0
  • PowerSql

    PowerSql is a simple powershell snapin for easy execution of sql commands. There are 2 flavors - OleDb and SqlServer specific commands.

    The current cmdlets include:
    Get-SqlData - returns strongly typed objects
    Get-OleDbData - returns strongly typed objects
    Get-SqlDataSet
    Get-OleDbDataSet
    Invoke-SqlCommand - returns number of rows affected
    Invoke-OleDbCommand - returns number of rows affected

    update: These cmdlets have been included in Powershell Community Extentions - the source is available from codeplex @ http://www.codeplex.com/PowerShellCX
    2/4/2008 12:00:00 AM Published by admin Category Powershell Comments 1
Archive