Thursday, December 1, 2011

PowerShell script for creation of Custom Event Source and Event Log

Copy the PowerShell script below and save it as EventSourceCreation.ps1 for creation of Event Source and Event Log:

#Write-Host "Remove event source SharePointEventSource"
Remove-EventLog -Source SharePointEventSource
#Write-Host "SharePointEventSource removed"

#Write-Host "Create event source SharePointEventSource"
New-EventLog -LogName "SharePoint Event Source" -Source SharePointEventSource
#Write-Host "Event source SharePointEventSource created"

Once event source has been created, go to Run => eventvwr and you will see that the new
"SharePoint Event Source" has be created under the Application and Services Logs, see snapshot below:

To automatically run the above script as a batch utility, copy and paste the code below and save it as a .bat file extension:

cd /d %~dp0
powershell -noexit -file ".EventSourceCreation.ps1" "%CD%"
pause

Can write custom logging in SharePoint using the SPDiagnosticsService class to log messages and exceptions against the above custom source created namely: SharePointEventSource

Run the script and enjoy :)

Thursday, November 10, 2011

Programmatically find SharePoint 2010 Web Control references in your code-behind files


Programmatically find SharePoint 2010 Web control references in the code-behind files like .aspx.cs for Page Layouts or Custom Application Pages and .ascx.cs for User Controls and Visual Webparts.

I tried to get a handle to the RichHtmlField control in SharePoint using the standard .NET way like this:
Control ctrl = this.FindControl("controlID") as Control;

Sadly it did not work.

So had to write a generic FindControlRecursive methods to get a reference to any SharePoint Web Control used in Page Layouts, Application Pages, Visual WebParts, User Controls etc. See the function call and the generic functions. Copy the code and use it to your advantage.

Function call:

RichHtmlField pageContent = FindControlRecursive(this.Page, "pageContent") as RichHtmlField;

Generic Methods:

         private static Control FindControlRecursive(Page page, string controlID)
        {
            foreach (Control controlToSearch in page.Controls)
            {
                Control controlToReturn = FindControlRecursive(controlToSearch, controlID);

                if (controlToReturn != null)
                {
                    return controlToReturn;
                }
            }

            return null;
        }
     

        private static Control FindControlRecursive(Control rootControl, string controlID)
        {
            if (String.Equals(rootControl.ID, controlID))
            {
                return rootControl;
            }

            foreach (Control controlToSearch in rootControl.Controls)
            {
                Control controlToReturn = FindControlRecursive(controlToSearch, controlID);

                if (controlToReturn != null)
                {
                    return controlToReturn;
                }
            }

            return null;
        }

Hope it helps. Happy Programming.

Wednesday, September 21, 2011

Powershell script to print Managed Metadata termsets in a .csv file

Here is the powershell script to retrieve all Managed metadata term sets for a SharePoint 2010 site collection and print them into a .csv file

1. Copy the code below and modify the variables highlighted in yellow below, save the following as PrintManagedMetadataTerms.ps1 file:

Add-PsSnapin "Microsoft.SharePoint.PowerShell"

$site = Get-SPSite "http://dev-sp-2010:1000/sites/sharepointfix/"
$termStoreName = "Managed Metadata Service"
$termStoreGroupName = "SharePointFixPortal"

set-variable -option constant -name out -value "C:\PrintAllManagedMetaDataTermSets.csv"

$session = new-object Microsoft.SharePoint.Taxonomy.TaxonomySession($site)
$termStore = $session.TermStores[$termStoreName]
$termStoreGroup = $termStore.Groups[$termStoreGroupName]

# Prints all Managed Metadata Termsets in the .csv file at the configured location
foreach($termsets in $termStoreGroup.TermSets)
{
"Termset Name: " + $termsets.Name + ", Description: " + $termsets.Description + ", Group: " + $termsets.Group + ", ID: " +$termsets.Id + ", Available for Tagging: " + $termsets.IsAvailableForTagging + ", Is Open for Term Creation : " + $termsets.IsOpenForTermCreation | Out-File $out -append;

foreach($terms in $termsets.GetAllTerms())
{
"Term Name:" + $terms.Name | Out-File $out -append
}
}

$site.Dispose()

Echo "Finished!"
Echo "Managed metadata termsets printed at:" $out

Remove-PsSnapin "Microsoft.SharePoint.Powershell"

2. To automatically run the above .ps1 script as a batch utility, Copy and paste code below and save it with a .bat file extension

cd /d %~dp0
powershell -noexit -file ".\PrintManagedMetadataTerms.ps1" "%CD%"
pause

Run the above .bat file, on the receipt of success message, traverse to the configured path to find the .csv file with all the managed metadata printed values.

Sunday, July 31, 2011

SharePoint 2010 List Item Event Receiver - Native Stack Error 0x81020089

When creating List Item Event Receivers, we added the ItemDeleting event to prevent List Items from being deleted:

public override void ItemDeleting(SPItemEventProperties properties)
{
    properties.Cancel = true;
    properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
    properties.ErrorMessage = "Bugs can only be resolved not deleted!";

    //You may also redirect to a custom error URL page:
    //SPUtility.Redirect(web.Url + Constants.ERROR_PAGE_URL + errorMessage, SPRedirectFlags.DoNotEndResponse, HttpContext.Current);
}

You would think that the above piece of code will show an appropriate validation message while deleting a list item, but instead it throws a native call stack error.

We identified that these code lines do not work very well with List Item event receivers:

properties.Cancel = true;  and
properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;

As a result we see a Native Stack Error Message:

We modified the ItemDeleting Event receiver code and it started working fine:

public override void ItemDeleting(SPItemEventProperties properties)
{
    properties.Status = SPEventReceiverStatus.CancelNoError;
    properties.ErrorMessage = "Bugs can only be resolved not deleted!";

     //You may also redirect to a custom error URL page:
    //SPUtility.Redirect(web.Url + Constants.ERROR_PAGE_URL + errorMessage, SPRedirectFlags.DoNotEndResponse, HttpContext.Current);
}


Elements.xml file for the List Item Event Receiver is as follows:

<?xml version="1.0" encoding="utf-8" ?> 
- <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
- <Receivers ListTemplateId="100">
- <Receiver>
  <Name>CustomItemDeleting</Name> 
  <Type>ItemDeleting</Type> 
  <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly> 
  <Class>SharePointFix.Project.ItemDeletingEvent</Class> 
  <SequenceNumber>10001</SequenceNumber> 
  </Receiver>
  </Receivers>
  </Elements>

Receiver ListTemplateId = 100, ensures that the validation works for both Pages library and Custom SharePoint Lists.

Friday, July 22, 2011

Powershell script to deploy multiple solutions (.wsp) to your SharePoint 2010 web application

The Powershell script below iterates through each .wsp files in your physical folder, installs and deploys them globally into all web-applications thus automating the solution deployment process.

Copy the PowerShell scriptlet below and paste it in a notepad and save it with a .ps1 extension in any of the directories in your hard disk.

NOTE: Do not forget to place all your solution files i.e..wsp files in the same directory as your .ps1 directory.
======================================================================

Add-PsSnapin Microsoft.SharePoint.PowerShell

#Do not modify anything in the script from here onwards
function Get-ScriptDirectory
{
 $Invocation = (Get-Variable MyInvocation -Scope 1).Value
 Split-Path $Invocation.MyCommand.Path
}

function Deploy-Solution{
param(
[string]$physicalPath,
[string]$name)

$SolutionName = $name
$SolutionPath = Join-Path ($physicalPath) $SolutionName
echo "Extracting information from $physicalPath"

#Admin service
$AdminServiceName = "SPAdminV4"
$IsAdminServiceWasRunning = $true;

if ($(Get-Service $AdminServiceName).Status -eq "Stopped")
{
    $IsAdminServiceWasRunning = $false;
    Start-Service $AdminServiceName
   Write-Host 'SERVICE WAS STOPPED, SO IT IS NOW STARTED'
}

#Uninstall
Write-Host 'UNINSTALLING SOLUTION ...'

$Solution = Get-SPSolution | ? {($_.Name -eq $SolutionName) -and ($_.Deployed -eq $true)}

if ($Solution -ne $null)
{
    if($Solution.ContainsWebApplicationResource)
    {
        Uninstall-SPSolution $SolutionName -AllWebApplications -Confirm:$false
    }
    else
    {
        Uninstall-SPSolution $SolutionName -Confirm:$false
    }
}

while ($Solution.JobExists)
{
    Start-Sleep 2
}

Write-Host 'SOLUTION HAS BEEN UNINSTALLED SUCCESSFULLY.'

Write-Host 'REMOVING SOLUTION ...'

if ($(Get-SPSolution | ? {$_.Name -eq $SolutionName}).Deployed -eq $false)
{
    Remove-SPSolution $SolutionName -Confirm:$false

Write-Host 'SOLUTION HAS BEEN REMOVED SUCCESSFULLY.'
}

Write-Host 'ADDING SOLUTION ...'

Add-SPSolution $SolutionPath  | Out-Null

Write-Host 'SOLUTION HAS BEEN ADDED SUCCESSFULLY.'

Write-Host 'DEPLOYING SOLUTION ...'

$Solution = Get-SPSolution | ? {($_.Name -eq $SolutionName) -and ($_.Deployed -eq $false)}

#use '-force' paramater to install all commands in this if statement

if(($Solution -ne $null) -and ($Solution.ContainsWebApplicationResource))
{
Install-SPSolution $SolutionName –AllwebApplications -GACDeployment -Force -Confirm:$false
}
else
{
Install-SPSolution $SolutionName -GACDeployment -Force -Confirm:$false
}

while ($Solution.Deployed -eq $false)
{
    Start-Sleep 2
}

Write-Host 'SOLUTION HAS BEEN DEPLOYED SUCCESSFULLY.'

if (-not $IsAdminServiceWasRunning)
{
    Stop-Service $AdminServiceName
}
}

#Get Current Physical Path
$currentPhysicalPath = Get-ScriptDirectory

#Iterate through all .wsp files in the current Physical Path to deploy solution
get-childitem $currentPhysicalPath -include *.wsp -recurse | foreach ($_) {Deploy-Solution $currentPhysicalPath $_.name}

#Remove SharePoint Snapin
Remove-PsSnapin Microsoft.SharePoint.PowerShell

Echo Finish

====================================================================


Automate the above .ps1 script as a batch utility, Copy and paste code below and save it with a .bat file extension, change the script file name in the highlighted yellow section below to your .ps1 name.

cd /d %~dp0
powershell -noexit -file ".AutomateDeploymentScript.ps1" "%CD%"
pause

Run the batch file and enjoy the automated deployment process:)