Tuesday, December 28, 2010

Check In SharePoint Documents using Powershell while Preserving "Modified" and "Modified By" MetaData

The Problem:

I was recently handed the following tasks:
  1. Checkin thousands of recently migrated documents

  2. maintain modified by metadata

  3. maintain modified date metadata

  4. must be done in powershell
The Solution:

I did some research and found a good post describing how to preserve the modifed by data here, but I still had to find a way to get it into powershell and also address the "modified date" requirement.

Below is the powershell I came up with that is working for me. You will probably want to update the list query piece to ensure the correct items are retreived. Also, I'm not quite sure the "RunWithElevatedPriveleges" is required or not, so you can test that out as well.

Hopefully this helps someone out there!

#function to return bindings to use in GetMethod() function
function Bindings()
{
return [System.Reflection.BindingFlags]::CreateInstance -bor
[System.Reflection.BindingFlags]::GetField -bor
[System.Reflection.BindingFlags]::Instance -bor
[System.Reflection.BindingFlags]::NonPublic
}

#Function to checkin a file using a specific user
function CheckInFileByUser([Microsoft.SharePoint.SPFile]$file, [string]$comment, [Microsoft.SharePoint.SPCheckinType]$checkInType, [Microsoft.SharePoint.SPUser]$user)
{
$bindings = Bindings
[System.Type[]] $types = [string],[Microsoft.SharePoint.SPCheckinType],[bool], [Microsoft.SharePoint.SPUser]
$method = $file.GetType().GetMethod("CheckIn",$bindings,$null,$types,$null)
$params = $comment,$checkInType,$false,$user
$method.Invoke($file,$params)
}

#Main code section
$baseUrl = "http://localhost/sites/records"
$listName = "Record Library"

Clear-Host
$site = Get-SPSite $baseUrl
$web = $site.OpenWeb($site.RootWeb.ID)
$list = $web.Lists[$listName]

#example only, get items using view or query of your choice
Foreach($item in $list.Items)
{
$file = $item.File
if($file.Level -eq [Microsoft.SharePoint.SPFileLevel]::Checkout)
{
#get the current date to use later
[System.DateTime]$date = $item["Modified"]
[Microsoft.SharePoint.SPFile]$file = $item.File

#get the current editor SPUser to use when checking in the file
$user = New-Object microsoft.SharePoint.SPFieldUserValue($web, $item["Editor"])

#check in the file
CheckInFileByUser $file "My Comment" "MajorCheckIn" $user.User
#change the modified date back to the original value
[Microsoft.SharePoint.SPSecurity]::RunWithElevatedPrivileges(
{
$item = $list.Items.GetItemById($item.ID);
$item["Modified"] = $date
$item.Update()
} )
}
}

9 comments:

Jeff said...

Thank you!! I was looking all over for the PowerShell equivalent of RunWithElevatedPrivileges() and am glad to see a working example.

There are a few rare cases when it is needed for a console script. When modifying SPSite.UserAccountDirectoryPath I have found no other way.

It always fails without elevation and works perfectly with. Thanks again! =)

Kevin Talbot said...

Awesome, I'm glad that helped you out!

Andy said...

Hi,

Is this scripts works for SP 2010 only?

i am looking for one in SP 2007 and also want to get the checkout documents based on username and then checked them in.

Regards.

Albert-Jan said...

Great post, but i have small node to add, as soon as you use the $item.UpdateOverwriteVersion() it will create a new minor version (or atleast it did on my PublishingPage).

Also i would suggest using:
$item[[Microsoft.SharePoint.SPBuiltInFieldId]::Modified]

But that's just a quicky,

Sebastian said...

Hi,
I sat down to code this, then came accross your script.
Very grateful!
Cheers,
Sebastian

Petri Asikainen said...

Thanks, this save my day or better my week!

Suresh Kumar Senapati said...

This works fine.
However when i use this on pages library, the publishing pages are not getting published.
Is there a code snippet to Publish the pages while preserving the modified by field like the CheckInFileByUser method suggested above.

Unknown said...

Bravo! Thank you sir!

yaklibber924 said...

This really answered my downside, thanks! betfair online casino