How to: Suppress File Change Notifications

When the physical file representing the text buffer has been changed, a dialog box displays with the message Do you want to save changes to the following items? This is known as file change notification. If many changes are going to be to the file, however, this dialog box displaying over and over again can quickly become annoying.

You can programmatically suppress this dialog box using the following procedure. By doing this, you can reload a file immediately without having to prompt the user to save the changes each time.

To suppress file change notification

  1. Call the FindAndLockDocument method to determine which text buffer object is associated with your open file.

  2. Direct the VsTextBuffer object that is in memory to ignore monitoring file changes by obtaining the IVsDocDataFileChangeControl interface from the VsTextBuffer (document data) object, and then implementing the IgnoreFileChanges method with the fIgnore parameter set to true.

  3. Call the methods on the IVsTextLines and the IVsTextBuffer interfaces to update the in-memory VsTextBuffer object with the file changes (such as when a field is added to your component).

  4. Update the file on disk with the changes without considering any pending edits the user might have in progress.

    In this way, when you direct the VsTextBuffer object to resume monitoring for file change notifications, the text buffer in memory reflects the changes that you generated, as well as all other pending edits. The file on disk reflects the latest code generated by you and any previously saved changes by the user in user-edited code.

  5. Call the IgnoreFileChanges method to notify the VsTextBuffer object to resume monitoring for file change notifications by setting the fIgnore parameter to false.

  6. If you plan to make several changes to the file, as in the case of source code control (SCC), then you must tell the global file change service to temporarily suspend file change notifications.

    For example, if you rewrite the file and then change the timestamp, you must suspend the file change notifications, as the rewrite and timestample operations each count as a separate file change event. To enable the global file change notification you should instead call the IgnoreFile method.

Example

The following demonstrates how to suppress file change notification.

//Misc. helper classes
 
CSuspendFileChanges::CSuspendFileChanges(
    /* [in] */ const CString& strMkDocument, 
    /* [in] */ BOOL fSuspendNow /* = TRUE */) 
:
    m_strMkDocument(strMkDocument),
    m_fFileChangeSuspended(FALSE)
{
    if(fSuspendNow)
        Suspend();
}
CSuspendFileChanges::~CSuspendFileChanges()
{
    Resume();
}
void CSuspendFileChanges::Suspend()
{
    USES_CONVERSION;
 
    // Prevent suspend from suspending more than once.
    if(m_fFileChangeSuspended)
        return;
 
    IVsRunningDocumentTable* pRDT = 
      _VxModule.GetIVsRunningDocumentTable();
    ASSERT(pRDT);
    if (!pRDT)
        return;
 
    CComPtr<IUnknown> srpDocData;
    VSCOOKIE vscookie = VSCOOKIE_NIL;
    pRDT->FindAndLockDocument(RDT_NoLock, T2COLE(m_strMkDocument),  
      NULL, NULL, &srpDocData, &vscookie);
    if ( (vscookie == VSCOOKIE_NIL) || !srpDocData)
        return;
    CComPtr<IVsFileChangeEx> srpIVsFileChangeEx;
    HRESULT hr = _VxModule.QueryService(SID_SVsFileChangeEx, 
      IID_IVsFileChangeEx, (void **)&srpIVsFileChangeEx);
    if (SUCCEEDED(hr) && srpIVsFileChangeEx)
    {
        m_fFileChangeSuspended = TRUE;
        srpIVsFileChangeEx->IgnoreFile(NULL, m_strMkDocument, TRUE); 
        srpDocData->QueryInterface(IID_IVsDocDataFileChangeControl, 
          (void**)&m_srpIVsDocDataFileChangeControl);
        if(m_srpIVsDocDataFileChangeControl)
            m_srpIVsDocDataFileChangeControl->IgnoreFileChanges(TRUE);
    }
}
void CSuspendFileChanges::Resume()
{
    if(!m_fFileChangeSuspended)
        return;
 
    CComPtr<IVsFileChangeEx> srpIVsFileChangeEx;
    HRESULT hr = _VxModule.QueryService(SID_SVsFileChangeEx, 
      IID_IVsFileChangeEx, (void **)&srpIVsFileChangeEx);
    if (SUCCEEDED(hr) && srpIVsFileChangeEx)
 
    srpIVsFileChangeEx->IgnoreFile(NULL, m_strMkDocument, FALSE); 
    if(m_srpIVsDocDataFileChangeControl)
        m_srpIVsDocDataFileChangeControl->IgnoreFileChanges(FALSE);
    m_fFileChangeSuspended = FALSE;
    m_srpIVsDocDataFileChangeControl.Release();
}
// Misc. helper classes

Robust Programming

If your case involves multiple changes to the file, as in the case of SCC, then it is important to resume global file change notifications before alerting the document data to resume monitoring for file changes.