A few days ago we ran into a situation where a user had uploaded dozens of documents into dozens of libraries on dozens of sites. The problem was that the user had uploaded multiple documents at a time into libraries that had multiple content types, so none of these documents were checked in. Since they had NEVER been checked in, the documents were only visible to the user who had uploaded them.
SharePoint offers a handy feature (Site Actions > View Reports > Checked Out To Me) where that user can see the documents checked out to them, and even check them in all at once. This is great, but in our situation since permission inheritance was broken on each of the subsites, there was no way to view all the documents across all the sites, just on one site at a time.
So, here we are faced with the daunting task of manually going thru dozens of sites looking for documents to check in. As a developer, your first instinct is to turn to a programmatic solution to avoid this huge manual process.
We needed a simple utility to look for items that had never been checked in across all sites in the collection, and check them in. Just a little console .exe…
First get a handle on the SPSite object:
using (SPSite mySite = new SPSite(siteCollectionURL))
Now you need to impersonate the user who uploaded the documents. Only that user can see those documents. A site collection admin can’t. The app pool account can’t. Only the original uploader.
SPUser impersonateUser = mySite.OpenWeb().AllUsers[@"DOMAINuser.name"];
SPUserToken token = impersonateUser.UserToken;
Now get a new SPSite object. All objects you create from the SPSite will run under the impersonated account.
mySite2 = new SPSite(siteCollectionURL, token);
Then loop thru the SPWeb’s:
foreach (SPWeb myWeb in mySite2.AllWebs)
Look for SPFolder’s:
foreach (SPFolder myFolder in myWeb.Folders)
Check each SPFile to see if it’s checked out:
foreach (SPFile myFile in myFolder.Files)
{
if (myFile.CheckOutStatus != SPFile.SPCheckOutStatus.None)
And check it in:
myFile.CheckIn("Checked in by utility.");
If you have publishing set on the document library, you may want to publish it too:
myFile.Publish("Published by utility.");
The only piece of this that surprised me (but probably shouldn’t have) was the need to impersonate the original uploader.
I should also note a few caveats:
- The above code will check in all files checked out to the impersonated user – not just the ones that have never been checked in. If you want, you can inspect the Versions collection on the SPFile object to see the history.
- The above code will also check in pages in the Pages library if you have a publishing site. You can add a conditional to skip over the Pages library in your loop if you want.
- I found that to work properly, my impersonated user had to be a Site Collection Admin.
You can use a tool like DMS-Shuttle for this purpose: http://dms-shuttle.com/. It can mass check in for a SharePoint site including all subsites and libraries.