Content Deployment error? How to find those checked out items within Sharepoint

If you have content deployment running you have probably seen this error before :

10/30/2008 1:01 AM You cannot perform this action on a checked out document. at Microsoft.SharePoint.SPListItem.SetRequiredInfoForUpdateItem(Boolean bDocLib, Boolean bAdd, Boolean bMigrate) at Microsoft.SharePoint.SPListItem.PrepareItemForUpdate(Guid newGuidOnAdd, Boolean bMigration, Boolean& bAdd, Boolean& bPublish, Object& objAttachmentNames, Object& objAttachmentContents, Int32& parentFolderId) at Microsoft.SharePoint.Deployment.ListItemSerializer.AddOrUpdateDoclibItemVersion(SerializationInfoHelper infoHelper, SPListItem& listItem, SPWeb web, Guid newId, String& listItemServerRelativeUrl, Boolean bIsPublish, Boolean exists, String version, Boolean isFirstVersion, Boolean isLastVersion, StreamingContext context, ISurrogateSelector selector, ImportObjectManager objectManager) at Microsoft.SharePoint.Deployment.ListItemVersionSerializer.AddListItemVersion(SPWeb web, SPListItem listItem, Guid newId, Boolean editHistory, Boolean existsInDb, Boolean isFirst, Boolean isLast, Boolean isDocLib, StreamingContext context, XmlElement listItemData, SPImportSettings settings, ImportObjectManager objectManager, SerializationInfoHelper listItemInfoHelper, String& listItemServerRelativeUrl, ISurrogateSelector selector) at Microsoft.SharePoint.Deployment.ListItemSerializer.UpdateListItemVersionData(SerializationInfoHelper infoHelper, SPWeb web, SPListItem& listItem, Guid newId, Boolean existsInDb, Boolean isDocLib, String& listItemServerRelativeUrl, StreamingContext context, SPImportSettings settings, ISurrogateSelector selector) at Microsoft.SharePoint.Deployment.ListItemSerializer.SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) at Microsoft.SharePoint.Deployment.XmlFormatter.ParseObject(Type objectType, Boolean isChildObject) at Microsoft.SharePoint.Deployment.XmlFormatter.DeserializeObject(Type objectType, Boolean isChildObject, DeploymentObject envelope) at Microsoft.SharePoint.Deployment.XmlFormatter.Deserialize(Stream serializationStream) at Microsoft.SharePoint.Deployment.ObjectSerializer.Deserialize(Stream serializationStream) at Microsoft.SharePoint.Deployment.ImportObjectManager.ProcessObject(XmlReader xmlReader) at Microsoft.SharePoint.Deployment.SPImport.DeserializeObjects() at Microsoft.SharePoint.Deployment.SPImport.Run()
10/30/2008 1:01 AM Content deployment job 'Remote import job for job with sourceID = bc232239-4545-4050-a8fe-85a5e4b8b112' failed.The exception thrown was 'Microsoft.SharePoint.SPException' : 'You cannot perform this action on a checked out document.'

 Pretty obviously this error is caused by a checked out document, which can be a real pain to find if you have a big site with multiple authors.  The following query when run on your content database (run this on your authoring database, not your production one!) will find all checked out items and tell you roughly where to look, which filename, and the user responsible.

SELECT tp_dirname, tp_leafName, userinfo.tp_title, userinfo.tp_email
FROM AllUserData
I
NNER JOIN AllLists on AllUserData.tp_listid = AllLists.tp_id
INNER JOIN userinfo on alluserdata.tp_checkoutuserid = userinfo.tp_id
WHERE tp_checkoutUserId != ''
order by tp_dirname, tp_leafname

Increasing the maximum upload limit on a Sharepoint Site

A new colleague here asked me today how to configure WSS v3 for files larger than the default limit of 50mb today.  I asked him to quickly tap it into google as I figured there would be hundreds of posts out there on how to do it, but sadly almost all of them seem to be for WSS v2.

Fortunately most of the principles are still the same, except there are far less steps to do :

1.  Increase the Web Applications Upload limit.
2.  Increase the HTTP Timeout.
3.  Increase the Execution Timeout and MaxRequestLength in web.config

Typically step 1 should only be necessary on an Intranet environment, but steps 2 and 3 should only be necessary if you are on a slow connection, or getting timeout errors when attempting to upload large files.

The instructions for each step are below :

1.  Open Central Administration. Go to "Application Management", then "Web Application General Settings".  Ensure you are on the correct web application and modify the "Maximum Upload Size" field.

2.  Open IIS, find the appropriate website and open its properties.  The timeout setting is on the Website tab and in the connections setting under "Http Connection Timeout".  I'd probably consider adding 120 seconds per extra 50 mb, more or less depending on your connection.

3.  Edit C:Program FilesCommon FilesMicrosoft SharedWeb server extensions12TEMPLATELAYOUTSweb.config

From : 

  <location path="upload.aspx">
    <system.web>
      <httpRuntime maxRequestLength="2097151" />
    </system.web>
  </location>

To : 

  <location path="upload.aspx">
    <system.web>
      <httpRuntime maxRequestLength="2097151" executionTimeout="999999"/>
    </system.web>
  </location>

Edit the web.config in the home directory of the IIS Site of your web application.

From :

<httpRuntime maxRequestLength="51200" />

To :

<httpRuntime maxRequestLength="51200" executionTimeout="999999" />

Force Deletion of an SSP

There is a lot of pain involved with removing an SSP thats having errors due to the database no longer existing.  Of course trying to remove the database via Central Administration and even STSADM, I got alot of errors such as "Cannot open database." and "Failed to delete SSP".

Fortunately there is an undocumented switch for the "STSADM -o DeleteSSP" command that will help in this situation. 

"Stsadm -o deletessp -title SSPNAME -force".

 The -force will delete the entry even if there are errors occuring. 

There are less aggressive methods, such as using stsadm -o deleteconfigurationobject, but if you are trying to connect to a non-existant database, that one probably wont work.  To do this one, query the objects table in the config database for your server, looking for the SSP name in the "name" column, Then take the ID of that object and use it against the stsadm -o deleteconfigurationobject command.

.NET Loading extremely slowly

One of my Sharepoint servers has been painfully slow after installation, even running stsadm would take about 10 seconds.  Whats really infuriating about it is that during the time frame where STSADM is typed into the command prompt, and its response, the server is doing next to nothing.

I've seen this behaviour before, however it was on an extremely overloaded ESX platform, so I initially thought it was due to that and didn't bother to look closely into it.  This time is on a glorious HyperV system that has resources out the wazoo, so should have absolutely no reason to run anything slow.  My guess from the outset was that something was timing out, and eventually erroring and after spending some time with FileMon trying to find something, I eventually turned to NetMon and ran a couple of captures.

The first time I found nothing interesting, but the second time I ran it I found a frame referring to an outbound HTTP connection attempt to 131.107.115.28.  A few frames later I saw the same request again, but never saw a response.   I did a quick tracert to that IP address and immediately noticed this :

Tracing route to crl.microsoft.com [131.107.115.28]

CRL is short for "Certificate Revocation List", for more information click on the link.  It turns out for every single signed assembly being loaded, .Net is checking the CRL to ensure that the key used to sign the assembly is legitimate. 

To confirm that it was this problem contacting the CRL server that was the problem, I decided to try a quick fix and added an entry for CRL.microsoft.com into my hosts file, pointing to localhost.  After doing this the problems I'd had were almost instantly resolved.  This however is only useful as a diagnosis, stopping the server from accessing crl.microsoft.com has some long term security risks, and is not advisable. 

Methods to fix the error :

  • Fix the problem with the internet access

If you can't do the above solution :

  • Point CRL.microsoft.com to 127.0.0.1 in a hosts file
  • Untick the "Check for Publishers Certificate Revocation" under security in the advanced Internet Explorer options.
  • Put <generatePublisherEvidence enabled="false" /> into your application's .config file.

I'd really recommend just going with the first one however.

Accidental cross domain results in People Picker

For a while I have had an open ticket with a client in regards to odd behavior while trying to create a new site collection.  The odd behaviour follows : "In Central Administration – when trying to create a new site collection and using the people picker to select the Site Collection Administrator, users from other domains are appearing."  Obviously for a hosting provider this is pretty bad behavior to have happen. 

It turns out that there are a very large amount of posts out there for allowing a people picker to search cross forest or cross domain, and very few about how to lock them down or limit them, so here we are.

Like most organisations, we try to lock our active directory environments down as much as possible, and this means removing list view for all authenticated users, except to their own OU.  Having a client be able to view entire organisations that were in different domains or forests is fairly counter-productive and needs immediate resolution.

I had initially thought that this might be fixed with AD permissions, but thats a bridge I'd rather not cross right now, if possible I'd rather fix this up at the people picker level.

There are quite a few commands that might help out here :

  • We could limit the people picker to a specific OU.  That would fix the problem, unless the same OU exists on one of the other domains.
  • We could limit the people picker to only show people within the site collection.  That would work ordinarily, but when creating a new site collection, you may want users that dont exist in a site collection yet.  And besides, which site collection would this pick to find the users in?  Thats one for another time.
  • We could limit the people picker to only one domain.  Bingo.

The peoplepicker-searchadforests command is perfect for this.   So I tap in the following command :

stsadm -o setproperty -pn peoplepicker-searchadforests -pv "domain:domaintosearch.com,USERNAME,PASSWORD" -url http://centraladminurl

Sidenote : The first time I ran this I got an error

Cannot retrieve the information for application credential key.

This was as I had not set an apppassword.  A quick run of "stsadm -o setapppassword -password PASSWORD" fixed this very quickly.  Make sure you keep that password written down, just in case.

Figuring that this is happening at the Central Administration level, I use the Central Admin web application as my target.  This returns a successful result, and so I go off to Central Administration again to test this.  It didn't work, I could still see multiple other domains. 

After a bit of musing, I decided to this feature against the Web Application I was trying to create the site collection into.  Bingo this worked.   Obviously when creating a new site collection,  the Central Administration people picker must inherit the settings from the selected Web Application, this would probably explain that long wait when you select a different Web Application.

Additional Note :

Make sure if you run this, you add the username and password to the command.  If you don't you'll lock your people picker down so well you wont find anyone.

Locking down the people picker to an OU

I thought I'd already covered this, but a quick look through my history shows I didn't.

Locking down a Web Application's people picker to a specific OU is very easy, but not well known.

stsadm -o setsiteuseraccountdirectorypath -url http://WEBAPPLICATIONURL -path "OU=OU,DC=DOMAIN,DC=COM"

Its really that simple, just point the path to the distinguished name of your OU, and you're set!

 

Hey, Where the hell did IP restrictions go?

I spent about 30 minutes looking around IIS7 for the IP restrictions that used to be a easily accessible part of IIS6. 

I finally gave up and emailed jorke asking if they were left out of IIS7.  I got back :

They definately are available, check that you've installed the feature

Now I'm publishing my ignorance about this, I must have missed the checkbox when I was installing the webserver roles.  It was right there under "IP and Domain Restrictions". 

Unable to activate publishing features.

I've seen a bug a couple of times where you for no great reason just can't activate publishing features on your site collection.  I click the button to activate the feature, and absolutely nothing happens, it stays deactivated.  The error appears to be caused because the application pool that the sharepoint site is running as can't activate that particular feature. 

There are a couple of blog posts out there with solutions to these, such as the following :

http://blog.thekid.me.uk/archive/2007/02/05/activating-office-sharepoint-server-publishing-infrastructure-access-denied.aspx
http://brijesh.spaces.live.com/blog/cns!BFBD772FBDA58C6D!196.entry

The fixes suggested are to changing the user your application pool runs as to the one used by CA, but I'm pretty lazy, and that seems like alot of work.

My way of fixing it?  Open up a command prompt and run the following for your site.

stsadm -o activatefeature -name PublishingSite -url http://sitecollection/
stsadm -o activatefeature -name PublishingWeb -url http://sitecollection/site

Same result, much less effort 🙂

Enumerating user and group membership for an entire site.

Stsadm will let you list the groups on your sharepoint site.  It will also let you list the users on your sharepoint site.  It just wont let you enumerate the group memberships of the users on your site. 

This really simple SQL query will list all active users on the site and the groups they are members of.

SELECT Groups.Title, UserInfo.tp_Login, UserInfo.tp_Title, UserInfo.tp_Email
FROM GroupMembership INNER JOIN
Groups ON GroupMembership.GroupId = Groups.ID INNER JOIN
UserInfo ON GroupMembership.MemberId = UserInfo.tp_ID
where userinfo.tp_isactive = '1'
order by userinfo.tp_Login

It does the trick, but not as well as a custom stsadm extension.  Maybe next time.

Fixing Local Activation DCOM errors in the eventlog

I'm sure this has been covered elsewhere, but its been a while since I put anything here.

Every now and again you might find an annoying error popping up in the event logs like the following :

The application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID
{61738644-F196-11D0-9953-00C04FD919C1} to the user DOMAINusername SID.
This security permission can be modified using the Component Services administrative tool.
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
 

This just means that an application pool user does not have launch or activate permissions set for a specific component, or permissions are incorrectly set.

The first task is to track down which component is causing the error, and the easiest way is to take the CLSID and just search the registry for it.  The local service key will probably give you a decent idea of what it is, in the case of the above error it was the IIS Admin Service.

Next open up Component Services and drill down until you find the previously mentioned service.  If you open up the properties and view the security tab you should be able to click edit and modify the "Launch and Activation" permissions.  Add your missing user to this and ensure both "Local Launch" and "Local Activation" are both set, as "Local Launch" is the default permission.

Viola!