Monday, December 27, 2010

Attaching to IIS Worker Process Server 2008

Here's the situation: You want to attach to an already-deployed web application, but you need to know which worker process is running your application. You've discovered that the trusty iisapp script you've used for years is gone.

That worked fine, so Microsoft decided to change it in Server 2008. The script is gone and replaced by an executable called APPCMD.

To list the process IDs for each worker process:

APPCMD list wb

The program is located in C:\Windows\System32\inetsrv. If you do this regularly, you should think about adding it to your system path.

Thanks to Carey Roth for running this down for the rest of us.

Wednesday, December 22, 2010

More About Removing Site Columns

Even after you've removed lists or content types that use site columns, you may still not be able to remove them.

That may well be because they're in the recycle bin.

In SharePoint 2010, the recycle bin is two tiers deep. Users can empty their recycle bin but the site collection administrator still needs to empty theirs before the object is really and truely gone.

To do this (if you are a site collection admin, of course):

1) Site Actions -> Site Collection Administration -> Recycle bin
2) Select all the files (can be done in one step by clicking on the header) and pressing the "Delete Selection" button on the ribbon control.
3) Click on the "Deleted from end user Recycle Bin. All the things you just deleted are now here.
4) Select everything and click the "Delete Selection."
5) Press "OK" to the warning about permanent deletion.
Of course, you can turn off the recycle bin or change the hold times. Here's how.

Friday, December 10, 2010

Finding Content Type References to a Site Column

If you try to delete a site column that is being used by one or more content types, you'll be rewarded with this message:

"Site columns which are included in content types cannot be deleted. Remove all references to this site column prior to deleting it."

That's true, but finding these conent types is not an easy matter. After some searching, I concluded that none of the approaches suggested are very efficient. Existing approaches are:

  1. Brute force. Search all the content types in all the sites and sub-sites on your farm.
  2. Use the Content Query Web Part. (I'm not actually sure this works)
  3. Write code based on the SharePoint API. (Time consuming)
  4. Rename the column (Doesn't work).

Here's a more efficient alternative: Look in the content database. The following query returns a list of webs and lists using a site column:

select ctu.ContentTypeId, w.FullUrl, l.tp_Title from ContentTypeUsage ctu
inner join Webs w on ctu.WebId = w.Id
inner join AllLists l on ctu.ListId = l.tp_ID
inner join ContentTypes ct on ct.ContentTypeId = ctu.ContentTypeId
where ct.Definition like '%Your Column Name Here%'

This returns the name of the content type ID of the field, the site and list name where it is used.

Tuesday, November 30, 2010

SQL Orphaned Users

This is well-documented but for some reason I can never remember the name of the procedure used to fix "orphaned" users in SQL server.

The name is sp_change_users_login.

Usually, you want to do this: sp_change_users_login 'Auto_Fix', 'login_here'

More information can be found here

Monday, November 1, 2010

Word, Excel files very slow to open on XP

This has happened to me twice in the last few months:

I experience a 2-3 minute delay after double-clicking on a Word or Excel document in Windows Explorer before the file is opened.

After an hour or so of Googling, it appears that the problem is fairly common and that there may be several very different causes. This posting is my attempt to deal with this on my computer. You may or may not have the same problem.

I'm running XP, but I think the problem spans all Windows versions since NT (Vista, Window 7, too).

Most articles (especially from Microsoft) talk about problems with inaccessible network locations or locations with lots of files. Here's one such example: In my case, this wasn't the issue. Disconnecting all network favorites and network drives made not difference at all.

For me, it turns out that DDE doesn't work properly and that the best fix was to stop using.

Windows Explorer can take actions based on the file extention. These can be configured in Windows Explorer under the Tools -> Folder Options dialog. The fix was to stop using DDE and launch Word or Excel directly.

To do this

  1. Open Windows Explorer, click Tools, Folder Options.
  2. Select the "File Types" tab.
  3. Locate the offending file extension. (In my case, it was doc, docx, xls, xlsx). Select it.
  4. Click on the Advanced button.
  5. Click on the Open Action, and press Edit

  6. Go to the end of the "Application used to perform this action" line

  7. Add "%1" to the end (include the quotes).

  8. Uncheck the "Use DDE" checkbox.

This launches the application directly instead of using DDE.

For me, some unanswered questions persist:

  1. Is DDE broken on my computer?
  2. If so, what broke it?
  3. I fixed this about a month ago. Why am I having to do it again?
  4. Are there other side effects?

Thursday, May 27, 2010

Using WindowsIdentity.Impersonate in SharePoint applications

Let's say that you have a SharePoint workflow that needs to call a web service and that the web service needs to be called using the identity of the user that started the workflow.

Unfortuately, workflows run don't run as the user who started the workflow instance, so you can't just use the current context's user.

I found the following in a blog posting that has since been deleted. (I rescued it from the Google cache.)

Wanted to record this so I can come back to it later....

0) Get the user that started the workflow from SPWorkflowActivationProperties.

Convert the SPUser to a WindowsIdentity. To accomplish this, create the user principal name (UPN) for the user. Then instantiate a new WindowsIdentity using the UPN.

private static string GetUpn(SPUser spUser)
string[] tmp = spUser.LoginName.Split('\\');
System.DirectoryServices.ActiveDirectory.Domain domain =
return tmp[1] + "@" + domain.Name;
SPUser spUser = GetMySPUser();
WindowsIdentity spUserIdentity = new WindowsIdentity(GetUpn(spUser));

Restrictions: This approach will only work when the user is actually a member of the Domain.GetCurrentDomain. Otherwise you need to search for the domain name through the active directory service. Also this approach will only work if the process user has the local security policy “Act As Part of the Operating System” = “true”. By default the NT Authority\Network Service user has this privilege. Additionally the WindowsIdentity instantiation is also restricted to the Server 2003 or Sever 2008 operating systems, but so is SharePoint.

Next perform the impersonation.

WindowsImpersonationContext context = spUserIdentity.Impersonate();
try {
MyLegacyData data = ExecuteLegacyLogic();
using (SPSite site = new SPSite(mySiteId))
using (SPWeb web = site.OpenWeb(myWeb)
AddLegacyDataResults( web, data );

Notes: In the above block the SPSite object access is the same as if were performed using new SPSite(mySiteId, spUser.UserToken).

Restrictions: Never run this code block inside a SPSecurity.RunWithElevatedPrivileges delegate. This appears to be unsupported by SharePoint. The resulting SPSite and SPWeb objects will be unusable. In this condition, a StackOverflowExcetion will be thrown if you attempt to access an SPUser in the SPWeb.Users collection and will bring down the entire process.

Outside of the above restriction, the code appears to work as expected.

Thursday, April 1, 2010

SSL Client Certificates

Here's the situation:

We have two servers in a secure environment where everything is protected by SSL with both server and client certificates. This means that clients need to present X509 certificates before the server will let them in.

The first server performs GIS functions, including some web services used by the second server. The second server is an intranet portal built with SharePoint. The server includes web parts that use the web services proved by the GIS server.

The rub happens when the web part tries to call a web service on the GIS server. We figured the web part could simply forward the client certificate it received, but we were wrong.

For what I presume are security concerns, the HTTP request won't use a certificate unless the private key used to create the certificate is available in its key store. In our case, the private key is on a key card back on the client's desktop, not on the SharePoint server.

I think the security concern is what's called a "man in the middle" attack. In our case, the SharePoint server is in the middle. If Windows permitted certificate forwarding, then a malicious programmer could create a "man in the middle" attack.

Tuesday, March 16, 2010

First Day with Amazon Web Services

I spent the day working for the first time with Amazon Web Services and I'm ready to give up on using this (for Windows systems anyway).

The first impression is, "wow, that's cheap!". You can get a Windows Server 2008 with 7.5GB memory for less than $.50 per hour. The best part of the deal is that you only pay when the machine is turned on.

The second impression is that storage is not so cheap. If you want your machine to remember anything when its not running, you'll need to pay for storage. If you have storage, then you'll need to pay for data transfers in and out of storage.

Still, I figured I could set up a nice SharePoint 2010 development/learning platform for less than $20 per month.

I've discovered some limitations:
  1. You can't create a Windows-based Amazon Machine Image from scratch due to licensing issues. The library has a selection of Windows images, but you can't roll your own.
  2. The platform won't run Hyper-V. While it might sound kind of dumb to put a VM on a VM, Microsoft has a Hyper-V for SharePoint all set up with a domain controller, database, Visual Studio and labs. It would have saved me a ton of time to just use that. But, there you go.
  3. Use Firefox instead of Internet Explorer. The biggest issue is there doesn't seem to be a way to download the necessary key files using IE. There also is a Firefox plug-in that you might find handy.
  4. It costs $100/yr to get a support agreement (and that's just web support).
The issue I'm having right now is a showstopper. As soon as I promote the computer domain controller status and restart it, I can't log in. None of the accounts I created work.

The lessons from today:
  • Amazon Web Service might not be as cheap as it seems.
  • Amazon Web Services isn't well-suited to Windows use.
  • You can't create a Windows machine that is a domain controller.
  • The tools are not as well polished as their counterparts in VMware Lab Manager.

Wednesday, February 3, 2010

Another Kerberos Battle

Having just done a couple of day's battle with a Keberos setup, I came away with one of those rare moments when the fog lifts and things become clear. I'm sure the fog will descent again soon, so I figured I'd better write this down before that happens.

Here are the bits of truth that made things work for me:
  1. In Windows, Kerberos Service Principle Names (SPNs) are stored in the Active Directory. They are not stored on the server. You don't need to be on the DC to run the setspn utility. In fact, you can enter the values directly using any AD editor.
  2. SPNs might be associated with a machine, but more often they're associated with a domain user account.
  3. An SPN must be unique across the domain (including both machine and user accounts).
  4. Active Directory happily stores duplicates. Duplicate SPNs always break Kerberos.
  5. Keberos errors are not added to the Event Log by default. You need to modify the registry if you want to see them in the event viewer.
  6. Make all your computers agree about the current time. Kerberos tickets don't work if client and server disagree about the current time by more than a few minutes.

Here's my attempt at de-mystifying a Kerboros exchange. I'm omitting details in favor of what I hope is a clearer explanation. This is strictly Windows, IIS and IE. Imagine that a user has just entered the URL of a web server on the local network and pressed the enter key.

  1. IE searches the AD for an SPN with the same name as the URL. There must be one and only one match. If there are no matches, you'll get kdc_err_s_principal_unknown and IE will fall back to NTLM. If there are multiple matches, the results are unpredictable.
  2. Active Directory uses the account where the SPN was found to encrypt a ticket and returns that ticket to IE.
  3. IE presents the encrypted ticket to the web server. If the application pool is running as a local machine account, the machine's domain account is used to decrypt the ticket. If the app pool is running as a domain user, that user's account is used instead.
  4. If the decryption is successful, you're in. If not, IIS falls back to NTLM.

Decryption can only succeed if the same account that was used to encrypt the ticket is used for decryption. If they don't match, you get krb_ap_err_modified.

Knowing this tells you where to register SPNs. If the app pool is a domain account, register the SPN in that user's AD object.

SPNs are automatically registered for machines, so you usually don't need to do them.

Wednesday, January 27, 2010

SharePoint Executes Commented web.config Entries

If you are in the habit of commenting out web.config entries in SharePoint, you should stop.

I got a rude reminder the other day that SharePoint doesn't honor comments if it finds something it can execute inside.

SharePoint will use this, even though it's embedded in comments.