Posts Tagged ‘SharePoint Server 2010’

Adding a PowerShell Snap-in

Tuesday, May 29th, 2012

A typical scenario when developing PowerShell scripts for SharePoint is to need the use of the SharePoint PowerShell snap-in. This snap-in provides all of the great SharePoint cmdlets that have quickly become critical to any SharePoint developer or administrator’s toolkit.

Some scripts may assume that the script will be executed within the SharePoint 2010 Management Shell – which is simply a standard PowerShell window with some extras: including the SharePoint PowerShell snap-in. However, what if an unsuspecting or unexperienced administrator executes the SharePoint script in a standard PowerShell instance?

To cover this circumstance, most script developers will choose to add the snap-in at the beginning of the script using the following code.

While this seems sufficient, there is an issue if the snap-in has already been added. This would easily occur if the script was run within the SharePoint 2010 Management Shell. PowerShell reports the following error pertaining to the fact that the snap-in has already been added:

Add-PSSnapin : Cannot add Windows PowerShell snap-in Microsoft.SharePoint.PowerShell because it is already added. Verify the name of the snap-in and try again.
At line:1 char:13
+ Add-PSSnapin < <<< Microsoft.SharePoint.PowerShell -PassThru + CategoryInfo : InvalidArgument: (Microsoft.SharePoint.PowerShell:String) [Add-PSSnapin], PSArgumentException + FullyQualifiedErrorId : AddPSSnapInRead,Microsoft.PowerShell.Commands.AddPSSnapinCommand

A typical solution to this issue I’ve seen is to instruct PowerShell to ignore the error using the following code.

That bothers me. I should be looking to suppress only the error where the snap-in is already added. What if I get another unrelated error? Therefore, instead of instructing PowerShell to silently continue, I would prefer the following code below. This code first checks for the snap-in before adding it and also allows for unrelated errors to still be reported.

It should be noted that this code could be used with any snap-in; not just SharePoint’s PowerShell snap-in. Here is a function one could use for any snap-in.

Finding Files Linked To A Specific File (Publishing Pages Linked to a Specific Page Layout)

Monday, March 19th, 2012

Ever had a need to find all of the files in a site collection that link to a specific file? A colleague of mine made an excellent find a few weeks ago and taught me this gem from the SharePoint object model. He had a need to find all publishing page layouts on a site and catalog which were being used and which weren’t. Check out his post here: SharePoint Fix: Powershell script to get SharePoint Page Layouts inventory and its usage across site collection

Passing Parameters to Delegate Controls

Tuesday, March 13th, 2012

I have a requirement for a DelegateControl where I need the child candidate control to render a link that opens in a new window in certain instances of the DelegateControl and open the link in the same window otherwise. The design that made the most sense to me was to use the same code for the child control to compute and render the link in both circumstances and pass a boolean parameter, OpenLinkInNewWindow, to control the target of the link.

The reader might be wondering why I need a control just to render a link. For the purposes of this article, just assume that the control has some built-in intelligence to render a link that cannot otherwise be easily generated!

But how would I pass a parameter to the child control that the DelegateControl uses? Unfortunately, the DelegateControl itself does not have the ability to accept parameters. However, the Control element that defines child controls for a DelegateControl, within the elements.xml file for a feature, does have the ability to accept parameters. Perfect!

To define parameters for a control, one can setup property name/value pairs using the Property element, which is a child of the Control element. It’s pretty straightforward!

Example
Say I have an application page, master page, etc. that needs to put the my fancy link-generating control in two separate places: one opens the link in a new window and one opens the link in the same window. In my page’s ASP.NET code, I have my two separate DelegateControls. I give each DelegateControl its own unique ControlId so that I can differentiate between the two.

With the above DelegateControls, I can use the first one wherever I need the link to open in a new window and the second wherever I need the link to open in the same window.

I would then define the following in the elements.xml file within the feature that adds the children to these DelegateControls.

Notice that I’m using the same control for both of the DelegateControls. I’m only changing the value of the OpenLinkInNewWindow parameter. This will use the same code in both DelegateControls to render the desired link. This allows me to use the LinkNewWindow DelegateControl wherever I want the link opened in a new window and the LinkSameWindow DelegateControl wherever I want the link opened in the same window.

Update: Adding parameters to custom controls
After sharing this article, I had a few colleagues suggest that I add a quick update around how to allow custom controls to accept parameters in the method described above. Parameters for a control can be created by using public properties defined on the control.

As long as the property is public, one can use the method outlined in this article to pass parameters when the control is used with a DelegateControl. If used in a more traditional context on an ASP.NET page, the public property could be used directly in the source code as follows.

There are several attributes that can decorate the public property to enhance its functionality as a property of the control. See the Attributes Applied to Public Properties section of the Metadata Attributes for Custom Server Controls article on MSDN for details.

IIS Termination during Visual Studio Debugging

Thursday, January 26th, 2012

What a familiar situation: You are debugging a SharePoint solution (or any ASP.NET code) and have Visual Studio attached to IIS. As you are stepping through your code, checking variables and getting a lot done, all of the sudden you are presented with the following message:

The web server process that was being debugged has been terminated by Internet Information Services (IIS). This can be avoided by configuring Application Pool ping settings in IIS. See help for further details.

It typically occurs within two minutes of Visual Studio pausing on a breakpoint. It is possible to extend this timeframe and the error message gives the answer. The reason Visual Studio presents this message is because IIS is forcefully terminating the worker process being debugged. Why? Because IIS (by default) performs health monitoring pings against each of its worker processes to ensure they are still responding. If IIS does not receive a response from the worker process to one of these pings within a given timeframe, IIS forcefully terminates the worker process. When debugging in Visual Studio, the worker process is stopped while Visual Studio is paused on a breakpoint. Therefore, the worker process has no way to respond to a health monitoring ping. Therefore, the worker process gets terminated.

How does one stop this vicious cycle and allow debugging to continue unimpeded? As the error message states, modify the IIS settings for health monitoring pings! To do this on a particular application pool:

  1. Open IIS Manager.
  2. On the left in the Connections pane, click Application Pools. The list of all of the application pools in IIS will display in the middle section of the window.

  3. Select the particular application pool used for debugging and click Advanced Settings under Edit Application Settings on the right in the Actions pane.

  4. Modify the two Ping settings: Ping Maximum Response Time (seconds) and Ping Period (seconds). The Ping Period is the interval used by IIS to ping the worker process. The Ping Maximum Response Time is the amount of time IIS will wait for a ping response. If IIS doesn’t get a response after the maximum response time has elapsed, that is when the termination occurs. By default, the ping period is 30 seconds and the maximum response time in 90 seconds. These are great in normal situations, but only give you about two minutes for debugging! Therefore, I would suggest throwing a few extra zeros in there – I personally set my ping period to 3000 seconds (50 minutes) and my maximum response time to 9000 seconds (150 minutes or 2.5 hours). Those values give me plenty of time to debug without needing to worry about termination. Once you have modified these values, click OK.

  5. While I would recommend developers to modify the health monitoring ping settings on their local development servers, these modifications should never be made in a testing or production environment.

    Happy debugging!

Expanding Warm Up Script Triggers

Wednesday, September 7th, 2011

This post is a follow up to a post I wrote a few months ago around triggering a warm up script for SharePoint to execute only when a specific application pool is recycled. You may want to read that post before this one: “Application Pool”-Specific Warm Up Scripts


After using what I recommended in the previous post, I realized there were still issues with this approach. To step back and explain the larger picture, I had a scenario where I needed to execute a warm up script whenever the application pool was freshly started. The script is responsible for filling application-level cache. Therefore, I want to execute the script any time the application pool will be freshly started. This means not just when it is recycled, but also in instances like server reboots. I have previously described how to do this using the Windows Task Scheduler to trigger the script to execute based on certain events being logged.

Side Note: I did brainstorm ideas to trigger execution when the application pool started, instead of triggering when the application pool recycled, etc. Regrettably, I was unable to find any Windows events that are logged when the application pool starts. Therefore, that paradigm could not be leveraged. However, one could feasibly create a custom extension to the OOTB SharePoint HttpApplication class (SPHttpApplication) and add logic to one of the class’ methods or events to trigger the warm up script.

This method would be a bit expensive in terms of the need for extra custom development, impacts to the entire web application due to the need to customize the IIS web application’s HttpApplication class, extra deployment steps, interoperability issues with other global.asax customizations, etc. Evaluate this carefully before proceeding with the suggestion above.

As it would be too difficult to trigger when the application pool is started (see the Side Note), I needed to continue triggering the event based on what would occur immediately prior to the application pool being started. I found three things that need to be used:

  1. Server Start/Reboot
  2. IIS Reset
  3. Application Pool Recycle

Server Start/Reboot
Whenever the server is started, one may wish to trigger the warm up script. If the server will take requests or the script will perform a function desired soon after the server is started, then this trigger can be used. Fortunately, the Windows Task Scheduler allows one to add a trigger that will begin the task At startup. Therefore, one can easily add this trigger!

IIS Reset
Whenever IIS is reset, then all of the application pools will be shut down. If requests will come shortly after resetting IIS, it would make sense to use this as a trigger for the warm up script. After analyzing all of the events that the IISreset utility could log, the only one that applies to the situation of needing to track the application pool’s pending start would be when IIS is freshly started: ID 3201. All of the other events described above pertain to states where the warm up script would not need to be executed.

To add event 3201 as a trigger to the task scheduler, you can use the following settings:

  • Begin the task: On an event
  • Log: System
  • Source: IIS-IISReset
  • Event ID: 3201

Note that, per the TechNet links below, Microsoft no longer supports using the IISreset utility in IIS 7.0 & 7.5.

IISreset Event Reference for Windows Server 2008 / IIS 7.0
http://technet.microsoft.com/en-us/library/cc735265(WS.10).aspx

IISreset Event Reference for Windows Server 2008 R2 / IIS 7.5
http://technet.microsoft.com/en-us/library/dd364067(WS.10).aspx

Application Pool Recycle
This is the key event that need to be tracked. The application pool’s recycle settings in IIS are quite extensive! Each reason for recycling produces a different event. This is the major area I realized that I was lacking from the previous post.

IIS logs an event when the application pool recycles

  • (5074) automatically on a regular time interval,
  • (5075) automatically when a defined number of requests have been fulfilled,
  • (5076) automatically at specific times,
  • (5077) automatically when a defined amount of virtual memory is used or exceeded by the worker process,
  • (5078) automatically when an ISAPI extension reports an unhealthy condition,
  • (5079) manually by an administrator,
  • (5080) automatically upon making configuration changes,
  • (5081) automatically due to detected problems with the IIS configuration store,
  • (5117) automatically when a defined amount of private memory is used or exceeded by the worker process, or,
  • (5186) automatically when inactive.

Parameters for automatic recycles can be configured in the IIS Manager. After considering each event, if the warm up script needs to perform any function that should always be in place while the application pool is running, then each of these events should have a trigger set against it.

The good news is that we can use the notion from the previous post to configure the trigger. (“Application Pool”-Specific Warm Up Scripts) One simply needs to include all of the extra IDs in the event filter.

Example Event Filter for an example application pool SharePoint – 32767
Don’t forget to replace SharePoint – 32767 with your application pool’s name!
<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">
      *[System[Provider[@Name='Microsoft-Windows-WAS']
      and (EventID=5074 or EventID=5075 or EventID=5076 or EventID=5077 or EventID=5078
           or EventID=5079 or EventID=5080 or EventID=5081 or EventID=5117 or EventID=5186)]
      and EventData[Data[@Name="AppPoolID"]="SharePoint - 32767"]]
    </Select>
  </Query>
</QueryList>

Important Note: There are also settings in IIS to control if IIS generates recycle event log entries for each of the events listed above! For any warm up script triggers to function properly, ensure that all of the scnearios are set to generate events!

Application Pool Recycling Event Reference for Windows Server 2008 / IIS 7.0
http://technet.microsoft.com/en-us/library/cc735206(WS.10).aspx

Application Pool Recycling Event Reference for Windows Server 2008 R2 / IIS 7.5
http://technet.microsoft.com/en-us/library/dd349270(WS.10).aspx

Summary
In closing, don’t forget to include any necessary triggers to your own particular warm up script’s scheduled task in Windows so that it executes whenever desired! My suggestions are to include the server start/reboot, the IIS Reset event (3201), and the application pool recycle events (5074-5081, 5117, & 5186).

Thanks to Greg Rosati for providing the links to the event information on TechNet that led to the creation of this follow up post!

Discard Check Outs by the System Account

Wednesday, August 3rd, 2011

SharePoint has a wonderful check-in/check-out system for any library with minor versioning enabled. Users with the Override Check Out permission on a particular library have the powerful ability to discard or check in a document, page, etc. that is checked out to another user. This can typically be easily achieved via any of the library’s views using the out-of-the-box user interface.

Any user with the proper permissions can check in or discard the check out using the item's edit menu

If the System Account is the account that has the item checked out, users are no longer available to check in the item or discard the check out from the library’s views, even with the Override Check Out permission!

The options to check in or discard the check out are unavailable in the item's edit menu

However, there is an area where this can be done: Site Content and Structure. One can navigate there by selecting Manage Content and Structure under the Site Actions menu. If you find the same item in that area, you will be able to check in the item or discard the check out.

The missing options are available in the Site Content and Structure views

“Application Pool”-Specific Warm Up Scripts

Wednesday, June 29th, 2011

Thanks to Thomas Vuylsteke and his ADdict blog for providing the foundation of this post!
FIM 2010: Warm Up Your Portal (IIS)
Be sure to read this post first to get the foundation of how one can configure a scheduled task to execute a warm up script whenever IIS recycles an application pool or whenever IIS is reset.


I had a scenario recently where one of my clients needed a rather long running warm up script to execute upon the recycling of a particular application pool. Being a larger farm, there were several application pools and the client only desired the warm up script to run when one specific application pool was recycled. The Windows Task Scheduler allows tasks to be triggered for execution when specific events are logged. When an application pool is recycled (automatically or manually) or when IIS is reset, events are logged in the System event log. Those events can be used to trigger tasks to run a warm up script in the Windows Task Scheduler!

IIS Action Source Event ID
Application Pool Recycle (automatic) WAS 5076
Application Pool Recycle (manual) WAS 5079
IIS Reset IIS-IISReset 3201

One can implement triggers for a warm up script task on each one of these event IDs. However, the 5076 & 5079 events are logged for all application pools. Therefore, if either event is used for a trigger, it means that the task will execute once for every application pool recycle on that instance of IIS. This may or may not be desired; for my client, it was not desired.

I needed to inspect the 5076 & 5079 events to see if there was enough data to further filter the trigger so it would only match 5076 & 5079 events for a specific web application. In my example, I’m attempting to filter on a web application named “SharePoint – 32767” (the name of your application pool can be looked up in IIS Manager).

The following is an excerpt of the relevant sections of the 5079 event’s XML representation (the 5076 event logs similar data):
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Microsoft-Windows-WAS"
              Guid="{524B5D04-133C-4A62-8362-64E8EDB9CE40}"
              EventSourceName="WAS" />
    <EventID Qualifiers="16384">5079</EventID>
    ...
  </System>
  <EventData>
    <Data Name="AppPoolID">SharePoint - 32767</Data>
    <Binary></Binary>
  </EventData>
</Event>

Fortunately, the application pool’s name is logged! One can use that data to filter the trigger even more. To do this within the trigger, select Custom on the event trigger window. Then click on New Event Filter…

Trigger on Custom Event Filter

Once in New Event Filter window, select the XML tab and check the box at the bottom to Edit query manually. Copy and paste the following – which will cover both the 5076 and 5079 events. Don’t forget to replace the SharePoint – 32767 name in the example below with your application pool’s name!
<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">
      *[System[Provider[@Name='Microsoft-Windows-WAS'] and (EventID=5076 or EventID=5079)]
      and EventData[Data[@Name="AppPoolID"]="SharePoint - 32767"]]
    </Select>
  </Query>
</QueryList>

This will cause the warm up script task to trigger on the 5076 & 5079 events, but only for a specific application pool!

Thanks again to Thomas Vuylsteke and his ADdict blog for providing the foundation of this post!

Finding Sites with a Particular Feature Activated

Saturday, February 12th, 2011

I continually have a question arise that seems easy to answer, yet from what I can tell, is not yet available with SharePoint out-of-the-box in its user interfaces. That question is:

What are all of the sites with feature xyz enabled?

A few years ago with a MOSS 2007 client environment where I had to answer this question, I was left with writing a quick C# console application that would crawl a web application for me and discover all of the site collections with a particular feature enabled. Not quite the best way of doing things, but it’s what was the best at the time.

Fast forward to SharePoint 2010. Now, PowerShell is in the mix and required for all SharePoint installations. Thanks Microsoft! So now, I have the vast capabilities of PowerShell available on any SharePoint farm I may encounter on any client environment with which I may be working. Plus, there’s an added bonus that, for some reason, the word “script” seems to scare clients and IT departments less than “console applications”. Even though PowerShell scripting can often wield the same powers as a C# console application, it seems to be accepted with more ease which makes my life easier.

Now that PowerShell is widely available, I rewrote that “quick C# console application” I referenced above in PowerShell for use recently on a SharePoint 2010 environment. The script below has a slightly more specific task than solving the question I posed above:

Output all of the site collection URLs within a particular web application that have a particular site-scoped feature enabled.

Here’s my script to do just such a task. The code below is meant for a single ps1 file.

Please note that it should work with both the 2007 & 2010 SharePoint product lines: SharePoint 2010 (Foundation & Server), WSS 3.0, and MOSS 2007. I have only tested this code on a SharePoint Server 2010 environment, but have no reason to believe it wouldn’t work in the other environments.

Feel free to use this script or modify it to fit your needs. There are several extra features that could be added to this script to make it even more versatile:

  • Reporting on the status of multiple features, not just a single feature
  • Reporting based on feature name versus feature GUID
  • Reporting on features scoped at different levels besides Site
    • Farm
    • Web Application
    • Web
  • Crawling other scopes besides a single web application
    • The entire farm,
    • Multiple web applications,
    • A subset of site collections,
    • A subset of sites,
    • Based on another block of script and/or function call to determine if a site should be scanned by the script,
    • etc.

I think the above script is a great starting point. Hopefully either myself or someone will get around to adding the above suggestions. Please share in the comments if you do end up extending this script!

Hiding the SharePoint 2010 Ribbon for Readers – A Proof of Concept

Saturday, February 5th, 2011

In SharePoint 2010 publishing sites, the ribbon is the new way of life for authors. However for readers, the ribbon provides very little, if any, functionality. A few days ago, I was asked about hiding this empty space by a client. Their current 2010 master page had the ribbon moved to a custom position on their publishing sites. They had also suppressed the breadcrumb/folder navigation in the ribbon; thus for a typical reader view, there was no ribbon contents that would be displayed. However, the space on the page where the ribbon would live for authors still remained as empty space!

We very well could have developed some server-side logic to determine the permissions of the user and hide that area completely based on that. Given infinite time and resources, I probably would have opted for that solution.

However, several of us were tasked with coming up with an easier and simpler solution to implement. One of the other consultants in the room at the time suggested a solution using JavaScript to hide the area if no contents was found (i.e. if the ribbon hadn’t rendered anything for the reader). I thought it was a great idea and immediately opened up an out-of-the-box publishing site in SharePoint Designer to tinker and develop a bit of JavaScript.

The goal of my JavaScript POC was to hide the entire div tag containing the SharePoint out-of-the-box ribbon control. I investigated and discovered that, in the nightandday.master file, the ribbon is contained in a div with the ID s4-ribbonrow. With that ID, I would be able to hide that div based on its rendered HTML contents. I figured, for this example, that the existence of the text “Browse” would be enough to determine whether or not the ribbon had rendered something or not.

To do this, I added JavaScript code to nightandday.master and it worked like a charm. Below is the relevant excerpt of nightandday.master:

<div id="s4-ribbonrow" ...>
    <!-- SharePoint out-of-the-box Ribbon Controls & Code goes here -->
</div>
<script type="text/javascript">
    var ribbonRow = document.getElementById("s4-ribbonrow");
    if(ribbonRow.innerHTML.indexOf("Browse") == -1)
    {
        ribbonRow.style.display = "none";
    }
</script>

I should note that I only was able to spend about 30 minutes on this entire topic. Please treat the above code as a proof-of-concept and make sure to evaluate the impact or effectiveness of this code in your own environment before using it.

An Introduction to SharePoint

Saturday, February 5th, 2011

My professional focus for the last few years has been Microsoft’s SharePoint platform. I’ve been extremely happy with my consulting work on this platform thus far. Some people have heard of it and used it, especially if you’re in front of a computer most of the day for your job. SharePoint is one of, if not the, fastest growing Microsoft product/platform. I will be extensively blogging about SharePoint and its various features.

While I could go on for days and weeks describing SharePoint to my clients and friends alike, I’d rather have this short three-minute video demonstrate SharePoint to you instead. It’s a wonderful view into the world of SharePoint. Enjoy!