A Practical Guide to SharePoint 2013

A Practical Guide to SharePoint 2013
A Practical Guide to SharePoint 2013 - Book by Saifullah Shafiq

Sunday, September 3, 2006

Updating Locked Files in SharePoint (using .NET Code)

Audience: Intermediate
Keywords: SharePoint, File lock

Q: When i try to update or delete a newly inserted file using .NET code, i get an error. SharePoint keeps the file locked for editing. I try to update file in the OnInsert() function.
Yes, this is true. SharePoint keeps your file locked. Easy solution is to rename the newly inserted document and then do manipulations on it. Interestingly, SharePoint won't allow you to rename the newly inserted file. So what should you do then? Create a copy of the newly inserted document with a different name and then you can update it's metadata easily. The other solution is given below but this won't work if you are working on a machine other than the server so this one is not very helpful but I am including it here for your learning.
NOTE: This code will not work if you are trying to update/delete file from a client machine.
Try this code:

-----------
spFile = EventWeb.GetFile( EventFileUrl );
spListItem = spFile.Item;
spListItem.ListItems.List.Items.DeleteItemById(spListItem.ID);
--------------
spListItem must be defined in the declaration section of EventSink class as following:
private SPListItem spListItem = null;

Be warned that if the file is open or if you have just finished some processing on the file then SharePoint won't let you delete or update it. The file is locked by SharePoint. If you are running the application on the SharePoint machine then you can use the following code to wait for SharePoint to release the lock on the file:

 private bool IsReadyToUpdate(string sDocName)
  {
   Process [] pWord = Process.GetProcessesByName("winword");

   int i ;
   if (pWord.Length >= 1)
   {
    for (i=0;i< pWord.Length;i++)
    {
     //pWordIdea.WaitForInputIdle();
     writeToEventLog("Status: Document is being added from machine: " + pWordIdea.MachineName.ToString()); 
     if (pWordIdea.MainWindowTitle.ToString()  == sDocName + " - Microsoft Word")
     {
      writeToEventLog("Status: Document "" + sDocName + "" found to be open. Waiting for it to be closed ...");
      
      if (!pWordIdea.HasExited)
      {
       pWordIdea.WaitForExit();
      }
      
      writeToEventLog("Status: Document "" + sDocName + " " closed down.");
      break;
     
     }
     else if (pWordIdea.MainWindowTitle.ToString()  == "Document1 - Microsoft Word")
     {
      writeToEventLog("Status: Document1 found to be open. Waiting for it to be closed ...");
      //if (!pWordIdea.HasExited)
      if (!pWordIdea.HasExited)
      {
       pWordIdea.WaitForExit();
      }
      writeToEventLog("Status: Document1 closed down.");
      break;
     }
     else
     {
      pWordIdea.CloseMainWindow();
      break;
     }
    
    }
    return true;
   }
   else
   {
    return true;
   }
  }   

 
WriteToEventLog() writes message in the Windows Log file. You can replace this function with your own code.
Here is another work around for this problem:
if (listEvent.Type == SPListEventType.Insert)
{

WindowsImpersonationContext wic = WindowsIdentity.GetCurrent().Impersonate();

SPWeb web = listEvent.Site.OpenWeb();

SPFile file = null;
SPListItem item = null;

file = web.GetFile(listEvent.UrlAfter);
item = file.Item;
item.ModerationInformation.Status = SPModerationStatusType.Pending;
item.Update();

wic.Undo();

}

Following snippet was sent by a friend. It is similar to the code shown above but contains error handling as well:
SPListItem item = listEvent.Site.OpenWeb().GetFile(listEvent.UrlAfter).Item;
//I think it's not a good method using while to check locked file.
String errorMsg = "Document Locked";
while(errorMsg.IndexOf("Document Locked")!=-1 || errorMsg.IndexOf("Save Conflict")!=-1)
{
Thread.Sleep(1000);
errorMsg = "";
item = listEvent.Site.OpenWeb().GetFile(listEvent.UrlAfter).Item;
//do something
  try
  {
    //update doc right now
    item.Update();
   }
   catch(Exception e)
   {
errorMsg = e.Message;
EventLog.WriteEntry("update Item", e.Message + "||" + e.StackTrace, EventLogEntryType.Error, 1);
   }
}

-SSA