Archive for the ‘Developer’ Category

What’s that IIS Process ID again?

Sunday, August 18th, 2013

First off, I’ll admit that it has been some time since my last post. I’ve moved into a new role at work that has much less emphasis on day-to-day development. However, I’ll still plan on posting interesting tidbits from time to time as I encounter them – just as I always have!

This one came up during a recent sprint of coding in which I was debugging a SharePoint 2013 farm solution (I know – apps are the way to go now!) with Visual Studio 2012. Let me say, since first starting development in MOSS 2007, this is a totally different and much smoother experience. I switched back-and-forth between using Visual Studio’s “Play” button – also known as “Start Debugging” – and a more traditional Build, Deploy, Attach to Process method.

When looking to attach to IIS, it’s always a gamble as to which w3wp.exe process to attach. However, this can be avoid by using the appcmd.exe utility. There is a nifty set of parameters that will allow you to view the currently running w3wp processes, their process IDs, and the names of the associated application pools. It’s just the right amount of information.

Enjoy and happy debugging!

Extracting Zip Files using PowerShell

Tuesday, July 17th, 2012

To help troubleshoot some SharePoint issues, I had a need to analyze some log files that were contained in multiple zip files; one log file per zip file. Since there were several hundred zip files to extract, I figured PowerShell could help! There are several posts I found with example scripts for how to perform this operation. I took pieces from many posts, added some COM object clean-up code, and wrapped this in a function. I hope it helps you in your scripting activities!

The code below is the function I’m using to extract a single zip file. It leverages the Windows Shell COM object (i.e. Windows Explorer) to extract the files by exploiting the fact that Windows Explorer treats zip files as folders. Therefore, the operation can leverage existing file copy methods between two folders.

Latest Code Not Working Quite Right?

Tuesday, July 3rd, 2012

I’m going to start this post with an example. See if you have ever found yourself in this situation when working on developing updates for previously deployed code; most often in a test and/or development environment:

1. I start out with an existing feature receiver that uses a web-scoped feature. The feature is already deployed to my development environment. To make this example very simple to illustrate the issue – this feature receiver will set the web’s title to an arbitrary value. The title will be reset back to its original state when the feature is deactivated.

2. Activating the feature on my test site reveals the following site title change.
Pre-activation:
Post-activation:

3. Now I’m going to illustrate a change to my previously deployed code. Let’s say for example that I wanted the title to be changed to “*** NEW WEB TITLE ***” instead of “EXISTING WEB TITLE”. I’ll make the change on Line 16 of the code above and create a new WSP for deployment.

4. I then open a new PowerShell window and execute the following six PowerShell commands using the same window. These commands will deploy the latest code and reactivate the feature on my test site so I can see the latest change.

5. I will then visit the site to see the change…

What happened? The title didn’t change?! What is wrong?

The problem occurred during Step 4. When the first command deactivated the feature, that cmdlet called the SharePoint DLLs which in turn called the SMayes.SharePoint assembly. This loaded the assembly in the PowerShell.exe process. Once the assembly is loaded, it will not be unloaded.

That’s the issue here: Once a DLL is loaded in a .NET process, it will not and cannot be unloaded!

So what? This means that when I executed the Enable-SPFeature cmdlet, PowerShell was still referring to my old code that was loaded earlier and therefore was not using my updated code! Opening a new PowerShell instance and executing the activation in that instance will cause the latest code to be used since the new process will be getting the updated DLL from the GAC.

In summary: Whenever you are deploying code updates, the proper way to execute the redeployment would include closing the current PowerShell process and opening a new PowerShell process as soon as new assemblies are deployed. This will ensure that further commands, such as feature activations, will not use outdated code.

Note that while the issue I described above pertains specifically to a feature receiver, it would also equally pertain to an event receiver, timer job, or other piece of code within a deployed assembly called by the SharePoint API. This issue is also a general issue across the board whenever a process (PowerShell, W3WP, OWSTimer, etc.) is using a custom-built assembly. This is why, when deploying new assemblies, W3WP is typically recycled. Also ensure that OWSTimer is recycled if there are any timer jobs being deployed.

Happy coding!

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.

Missing Intellisense and/or Code Folding?

Thursday, May 17th, 2012

This afternoon, I was getting quite frustrated because I was working on a .master file in Visual Studio and all of the code folding and Intellisense was missing! It seems that when the .master file is opened by double-clicking it in the Solution Explorer, these items will be missing. To resolve the problem, right-click the .master file and select View Code!

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.

Access Denied when Enabling PowerShell Remoting

Thursday, February 2nd, 2012

Quick tip: Are you receiving Access Denied messages when you are attempting to run the Enable-PSRemoting cmdlet? I’ve received them on machines connected to a domain, even when I’m running in an elevated PowerShell window. An easy trick is to open a PowerShell window as the built-in administration account on the machine. Not sure why, but for whatever reason, it seems to work!

VirtualBox Unidentified Network

Thursday, February 2nd, 2012

Thanks to Oisin Grehan and his Nivot Ink blog for providing the foundation of this post!
VMWare VMNET Adapters Triggering Public Profile for Windows Firewall


I use Oracle’s VirtualBox to run x64 SharePoint virtual machines from my laptop. I’ve also noticed an Unidentified Network in my Windows 7 list of networks. That is caused by VirtualBox’s Host-Only Network Adapter. It wasn’t harming anything at the time so I left it alone.

However, I later attempt to enable PowerShell remoting on my host laptop for work with SharePoint scripting. Upon doing so, I was greeted with the following error message while attempting the Enable-PSRemoting cmdlet:

Set-WSManQuickConfig : WinRM firewall exception will not work since one of the network connection types on this machine is set to Public. Change the network connection type to either Domain or Private and try again.

Another helpful error message! That seems easy enough; Windows makes it very easy to modify the settings for each individual network adapter to Private, Work, or Public depending on your personal preference. However, this is not the case with an unidentified network. With an unidentified network, Windows sticks to its Public settings and will not change it.

So can I now not enable PowerShell remoting since I can’t remove the Public designation of VirtualBox’s unidentified network? No! VirtualBox’s Host-Only network isn’t really a true network connection at all. It is an endpoint adapter. Kudos to Oisin Grehan for developing a nice PowerShell script that will solve the issue by telling Windows, via the registry, that the network adapter is an endpoint device and not a true external network connection. This will cause Windows to stop treating the VirtualBox Host-Only adapter as a network and thus remove the unidentified network (and its public designation) from my list of networks. Problem solved! I’ve modified Oisin’s script to account for VirtualBox’s Host-Only instead of VMware adapters.

Note: This script will need to be executed every time VirtualBox is updated because the update will replace the existing adapter and cause the settings in the registry to be lost.

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!