Walkthrough: Debugging a SharePoint Solution by Using IntelliTrace

By using IntelliTrace, you can more easily debug SharePoint solutions. Traditional debuggers give you only a snapshot of a solution at the current moment. However, you can use IntelliTrace to review past events that occurred in your solution and the context in which they occurred and navigate to the code.

This walkthrough demonstrates how to debug a SharePoint 2010 or SharePoint 2013 project in Visual Studio Ultimate 2012 by using the standalone data collector in IntelliTrace. The collector collects data from apps that are running in production environments. To analyze that data, you must use Visual Studio Ultimate 2012. This project incorporates a feature receiver that, when the feature is activated, adds a task to the Task list and an announcement to the Announcements list. When the feature is deactivated, the task is marked as completed, and a second announcement is added to the Announcements list. However, the procedure contains a logical error that prevents the project from running correctly. By using IntelliTrace, you'll locate and correct the error.

Applies to: The information in this topic applies to SharePoint 2010 and SharePoint 2013 solutions that were created in Visual Studio.

This walkthrough illustrates the following tasks:

  • Create a Feature Receiver.

  • Add Code to the Feature Receiver.

  • Test the Project.

  • Install the Standalone Data Collector.

  • Set Permissions for the Data Collector Folder.

  • Install IntelliTrace PowerShell Cmdlets.

  • Create the .iTrace Folder, and Set its Permissions.

  • Deploy the SharePoint Solution.

  • Collect Debug Data from the SharePoint Solution.

  • Debug and Fix the SharePoint Solution.

Note

Your computer might show different names or locations for some of the Visual Studio user interface elements in the following instructions. The Visual Studio edition that you have and the settings that you use determine these elements. For more information, see Customizing Development Settings.

Prerequisites

You need the following components to complete this walkthrough:

Create a Feature Receiver

First, you create an empty SharePoint project that has a feature receiver.

To create a feature receiver

  1. Create a SharePoint 2010 or SharePoint 2013 solution project, and name it IntelliTraceTest.

    The SharePoint Customization Wizard appears, in which you can specify both the SharePoint site for your project and the trust level of the solution.

  2. Choose the Deploy as a farm solution option button, and then choose the Finish button.

    IntelliTrace operates only on farm solutions.

  3. In Solution Explorer, open the shortcut menu for the Features node, and then choose Add Feature.

    Feature1.feature appears.

  4. Open the shortcut menu for Feature1.feature, and then choose Add Event Receiver to add a code module to the feature.

Add Code to the Feature Receiver

Next, add code to two methods in the feature receiver: FeatureActivated and FeatureDeactivating. These methods trigger whenever a feature is activated or deactivated in SharePoint, respectively.

To add code to the feature receiver

  1. At the top of the Feature1EventReceiver class, add the following code, which declares variables that specify the SharePoint site and subsite:

    ' SharePoint site and subsite.
    Private siteUrl As String = "https://localhost"
    Private webUrl As String = "/"
    
    // SharePoint site and subsite.
    private string siteUrl = "https://localhost";
    private string webUrl = "/";
    
  2. Replace the FeatureActivated method with the following code:

    Public Overrides Sub FeatureActivated(ByVal properties As SPFeatureReceiverProperties)
        Try
            Using site As New SPSite(siteUrl)
                Using web As SPWeb = site.OpenWeb(webUrl)
                    ' Reference the lists.
                    Dim announcementsList As SPList = web.Lists("Announcements")
                    Dim taskList As SPList = web.Lists("Tasks")
    
                    ' Add an announcement to the Announcements list.
                    Dim listItem As SPListItem = announcementsList.Items.Add()
                    listItem("Title") = "Activated Feature: " & Convert.ToString(properties.Definition.DisplayName)
                    listItem("Body") = Convert.ToString(properties.Definition.DisplayName) & " was activated on: " & DateTime.Now.ToString()
                    listItem.Update()
    
                    ' Add a task to the Task list.
                    Dim newTask As SPListItem = taskList.Items.Add()
                    newTask("Title") = "Deactivate feature: " & Convert.ToString(properties.Definition.DisplayName)
                    newTask.Update()
                End Using
            End Using
    
        Catch e As Exception
            Console.WriteLine("Error: " & e.ToString())
        End Try
    
    End Sub
    
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        try
        {
            using (SPSite site = new SPSite(siteUrl))
            {
                using (SPWeb web = site.OpenWeb(webUrl))
                {
                    // Reference the lists.
                    SPList announcementsList = web.Lists["Announcements"];
                    SPList taskList = web.Lists["Tasks"];
    
                    // Add an announcement to the Announcements list.
                    SPListItem listItem = announcementsList.Items.Add();
                    listItem["Title"] = "Activated Feature: " + properties.Definition.DisplayName;
                    listItem["Body"] = properties.Definition.DisplayName + " was activated on: " + DateTime.Now.ToString();
                    listItem.Update();
    
                    // Add a task to the Task list.
                    SPListItem newTask = taskList.Items.Add();
                    newTask["Title"] = "Deactivate feature: " + properties.Definition.DisplayName;
                    newTask.Update();
                }
            }
        }
    
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.ToString());
        }
    
    }
    
  3. Replace the FeatureDeactivating method with the following code:

    Public Overrides Sub FeatureDeactivating(ByVal properties As SPFeatureReceiverProperties)
        ' The following line induces an error to demonstrate debugging.
        ' Remove this line later for proper operation.
        Throw New System.InvalidOperationException("Serious error occurred!")
        Try
            Using site As New SPSite(siteUrl)
                Using web As SPWeb = site.OpenWeb(webUrl)
                    ' Reference the lists.
                    Dim taskList As SPList = web.Lists("Tasks")
                    Dim announcementsList As SPList = web.Lists("Announcements")
    
                    ' Add an announcement that the feature was deactivated.
                    Dim listItem As SPListItem = announcementsList.Items.Add()
                    listItem("Title") = "Deactivated Feature: " & Convert.ToString(properties.Definition.DisplayName)
                    listItem("Body") = Convert.ToString(properties.Definition.DisplayName) & " was deactivated on: " & DateTime.Now.ToString()
                    listItem.Update()
    
                    ' Find the task that the feature receiver added to the Task list when the
                    ' feature was activated.
                    Dim qry As New SPQuery()
                    qry.Query = "<Where><Contains><FieldRef Name='Title' /><Value Type='Text'>Deactivate</Value></Contains></Where>"
                    Dim taskItems As SPListItemCollection = taskList.GetItems(qry)
    
                    For Each taskItem As SPListItem In taskItems
                        ' Mark the task as complete.
                        taskItem("PercentComplete") = 1
                        taskItem("Status") = "Completed"
                        taskItem.Update()
                    Next
                End Using
    
            End Using
    
        Catch e As Exception
            Console.WriteLine("Error: " & e.ToString())
        End Try
    
    
    End Sub
    
    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
        // The following line induces an error to demonstrate debugging.
        // Remove this line later for proper operation.
        throw new System.InvalidOperationException("A serious error occurred!"); 
        try
        {
            using (SPSite site = new SPSite(siteUrl))
            {
                using (SPWeb web = site.OpenWeb(webUrl))
                {
                    // Reference the lists.
                    SPList taskList = web.Lists["Tasks"];
                    SPList announcementsList = web.Lists["Announcements"];
    
                    // Add an announcement that the feature was deactivated.
                    SPListItem listItem = announcementsList.Items.Add();
                    listItem["Title"] = "Deactivated Feature: " + properties.Definition.DisplayName;
                    listItem["Body"] = properties.Definition.DisplayName + " was deactivated on: " + DateTime.Now.ToString();
                    listItem.Update();
    
                    // Find the task that the feature receiver added to the Task list when the
                    // feature was activated.
                    SPQuery qry = new SPQuery();
                    qry.Query = "<Where><Contains><FieldRef Name='Title' /><Value Type='Text'>Deactivate</Value></Contains></Where>";
                    SPListItemCollection taskItems = taskList.GetItems(qry);
    
                    foreach (SPListItem taskItem in taskItems)
                    {
                        // Mark the task as complete.
                        taskItem["PercentComplete"] = 1;
                        taskItem["Status"] = "Completed";
                        taskItem.Update();
                    }
                }
            }
    
        }
    
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e.ToString());
        }
    }
    

Test the Project

Now that the code is added to the feature receiver and the data collector is running, deploy and run the SharePoint solution to test whether it works correctly.

Important

For this example, an error is thrown in the FeatureDeactivating event handler. Later in this walkthrough, you locate this error by using the .iTrace file that the data collector created.

To test the project

  1. Deploy the solution to SharePoint, and then open the SharePoint site in a browser.

    The feature automatically activates, causing its feature receiver to add an announcement and a task.

  2. Display the contents of the Announcements and Tasks lists.

    The Announcements list should have a new announcement that's named Activated feature: IntelliTraceTest_Feature1, and the Tasks list should have a new task that's named Deactivate feature: IntelliTraceTest_Feature1. If either of these items is missing, verify whether the feature is activated. If it isn't activated, activate it.

  3. Deactivate the feature by performing the following steps:

    1. On the Site Actions menu in SharePoint, choose Site Settings.

    2. Under Site Actions, choose the Manage site features link.

    3. Next to IntelliTraceTest Feature1, choose the Deactivate button.

    4. On the Warning page, choose the Deactivate this feature link.

    The FeatureDeactivating() event handler throws an error.

Install the Standalone Data Collector

If you install the standalone data collector on the system that’s running SharePoint, you can debug SharePoint solutions by using data that's more specific than the generic information that IntelliTrace returns. The standalone data collector works outside of Visual Studio by using PowerShell cmdlets to capture debug information while your SharePoint solution runs.

Note

The configuration information in this section is specific to this example. For more information about other configuration options, see Collect IntelliTrace Data Outside Visual Studio with the Standalone Collector.

To install the standalone data collector

  1. On the computer that's running SharePoint, create a folder for the standalone data collector files, and name it c:\IntelliTraceCollectorFiles.

  2. Download the data collector in Visual Studio 2012 Update 2, and then save the file in the folder that you created in the previous step.

  3. Run IntelliTraceCollector.exe to extract the IntelliTraceCollection.cab file.

  4. Expand IntelliTraceCollection.cab by performing the following steps.

    1. On the server that's running SharePoint, open a Command Prompt window as an administrator.

    2. Change to the directory that contains the data collectorfolder (c:\IntelliTraceCollectorFiles).

    3. Expand IntelliTraceCollection.cab by running the following command and including the period at the end.

      expand /f:* IntelliTraceCollection.cab .

      Note

      The period creates subfolders that contain localized collection plans.

Set Permissions for the Data Collector Folder

Before server administrators can use the data collector, you must give them permission to access its folder so that they can run the collector’s PowerShell cmdlets.

To set folder permissions

  1. On the computer that's running SharePoint, open a Command Prompt window as an administrator.

  2. At the command prompt, run the following commandfolder:

    icacls "C:\IntelliTraceCollectorFiles" /grant "Domain\AdministratorID":F

    (Replace Domain\AdministratorID with the user's domain and ID.)

  3. To collect data for the SharePoint solution, give the person who will run the PowerShell cmdlets full permissions to the collector folder.

    icacls "C:\IntelliTraceCollectorFiles" /grant "Domain\UserID":F

  4. Give the application pool for the SharePoint solution read and execute permissions to the collector folder.

    folderFor example, to give a SharePoint solution in the SharePoint-80 application pool access, run the following command:

    icacls "C:\IntelliTraceCollectorFiles" /grant "IIS APPPOOL\SharePoint-80":RX

Install IntelliTrace PowerShell Cmdlets

Now you install the PowerShell cmdlets that run the standalone data collector in IntelliTrace.

To install the cmdlets

  1. On the server that's running SharePoint, make sure that PowerShell is enabled.

    On most versions of Windows Server, you can add this feature by using Server Manager, as the following illustration shows.

    Adding PowerShell by using Server Manager

  2. On the Start menu, choose All Programs, Accessories, Windows PowerShell.

  3. Open the shortcut menu for Windows PowerShell (64-bit operating systems) or Windows PowerShell (x86) (32-bit operating systems), and then choose Run as administrator.

  4. In the PowerShell command window, run the following command:

    Import-Module "C:\IntelliTraceCollectorFiles\Microsoft.VisualStudio.IntelliTrace.PowerShell.dll"

Create the .iTrace Folder, and Set Its Permissions

Create a folder for the .iTrace files that the standalone data collector generates, and then set the folder's permissions.

To create a folder and set permissions

  1. On your computer, create a folder that's named C:\IntelliTraceLogFiles.

    Note

    • To avoid slowing down your solution, create the folder on a local high-speed disk that's not very active.

    • You can put .iTrace files and the collector files in the same folder. However, if you have a web application or a SharePoint solution, make sure they're outside the folder that hosts the solution.

    Security noteSecurity Note
    • Restrict access to the .iTrace folder to only those users who must work with the collector. IntelliTrace can record any data that passes into method parameters, so an .iTrace file might contain sensitive information, such as data from users, databases, other source locations, and connection strings.

    • Make sure that users who can open .iTrace files have the authority to view sensitive data. Use caution when sharing .iTrace files. If people who don't have the authority to view sensitive data must have access to the .iTrace files, copy them to a secure shared location.

  2. Give the application pool for SharePoint full permissions to the .iTrace folder.

    For example, you would use the following command for a SharePoint application in the SharePoint - 80 application pool:

    icacls "C:\IntelliTraceLogFiles" /grant "IIS APPPOOL\SharePoint - 80":F

Collect Debug Data from the SharePoint Solution

Now that the code, the necessary cmdlets, and the permissions are ready, you can collect debug data from the SharePoint solution by using the IntelliTraceCollection cmdlet.

To collect debug data from the SharePoint solution

  1. Use the following syntax:

    Start-IntelliTraceCollection ApplicationPoolPathToCollectionPlanFullPathToITraceFileFolder

    For example, you would use the following command to collect data from a SharePoint solution in the SharePoint - 80 application pool:

    Start-IntelliTraceCollection "SharePoint - 80" "C:\IntelliTraceCollectorFiles\collection_plan.ASP.NET.default.xml" "C:\IntelliTraceLogFiles"

    The following table explains the parameters of this command.

    Parameter

    Description

    ApplicationPool

    The name of the application pool in which your SharePoint solution runs.

    PathToCollectionPlan

    The path to a collection plan.

    Use this parameter to specify a plan that comes with the data collector. You can use the following plans for SharePoint solutions:

    • collection_plan.ASP.NET.default.xml

      Collects only IntelliTrace events and SharePoint events, including exceptions, database calls, and web server requests.

    • collection_plan.ASP.NET.trace.xml

      Collects function calls and all the data specified in collection_plan.ASP.NET.default.xml. This plan is good for detailed analysis, but because of the extra data collected, it might slow your SharePoint solution more than the other plan will.

    To avoid slowing down your solution, customize an existing plan or create your own. For security, put any custom plans in the same secure location as the collector files. See Modifying an IntelliTrace Collection Plan for the Stand-Alone Collector.

    Note

    By default, the maximum size of the .iTrace file is 100 MB. When the .iTrace file reaches this limit, the collector deletes the file's earliest entries to make space for newer entries. To change this limit, edit the collection plan's MaximumLogFileSize attribute.

    If you need localized versions of collection plans, you can find them in the collector's subfolders.

    FullPathToITraceFileFolder

    The full path of the folder in which .iTrace files are saved.

    Security noteSecurity Note

    Provide a full path for this parameter, not a relative path.

    When you run this command, the collector attaches to the application pool and then starts to collect data.

    Note

    Because the .iTrace file is locked during data collection, you can't open it while IntelliTrace collects data. However, you can take snapshots of the file and then open them. See Collect IntelliTrace Data Outside Visual Studio with the Standalone Collector.

  2. Deactivate the feature by performing the following steps:

    1. On the Site Actions menu in SharePoint, choose Site Settings.

    2. Under Site Actions, choose the Manage site features link.

    3. Next to IntelliTraceTest Feature1, choose the Deactivate button.

    4. On the Warning page, choose the Deactivate this feature link.

    An error occurs (in this case, because of the error thrown in the FeatureDeactivating() event handler).

  3. To stop collecting data, run the following cmdlet in the PowerShell window:

    Stop-IntelliTraceCollection "SharePoint - 80"

    The debug data is saved in the .iTrace file.

Debug and Fix the SharePoint Solution

Now you view the .iTrace debug data file in Visual Studio to find and fix the error in the SharePoint solution.

To debug and fix the SharePoint solution

  1. In the \IntelliTraceLogFiles folder, open the .iTrace file in Visual Studio.

    The IntelliTrace Summary page appears. Because the error wasn't handled, a SharePoint correlation ID (a GUID) appears in the unhandled exception area of the Analysis section. Choose the Call Stack button if you want to view the call stack where the error occurred.

  2. Choose the Debug Exception button.

    If prompted, load symbol files. In the IntelliTrace window, the exception is highlighted as "Thrown: Serious error occurred!".

    In the IntelliTrace window, choose the exception to display the code that failed.

  3. Fix the error by opening the SharePoint solution and then either commenting out or removing the throw statement at the top of the FeatureDeactivating() procedure.

  4. Rebuild the solution in Visual Studio, and then redeploy it to SharePoint.

  5. Deactivate the feature by performing the following steps:

    1. On the Site Actions menu in SharePoint, choose Site Settings.

    2. Under Site Actions, choose the Manage site features link.

    3. Next to IntelliTraceTest Feature1, choose the Deactivate button.

    4. On the Warning page, choose the Deactivate this feature link.

  6. Open the Task list, and verify that the Status value of the Deactivate task is "Completed" and its % Complete value is 100%.

    The code now runs properly.

See Also

Concepts

Verifying and Debugging SharePoint Code

Debug Your App by Recording Code Execution with IntelliTrace

Other Resources

Walkthrough: Verify SharePoint Code by Using Unit Tests