Merge supports virtual file systems, which enable Merge to access files and folders that aren’t necessarily present on the user’s hard disk or computer. Example file systems include FTP, HTTP, and SCM integrations.
Support for new (or currently unsupported) file systems can be added to Merge by writing a small set of COM components that implement a set of defined interfaces. The primary interface is the IFileSystem interface, which provides an entry-point into a virtual file system.
Registering new file systems with Merge
File system plugins are registered with Merge by adding a section to the vfsplugins.ini file that is found in the Merge installation
folder. The vfsplugins.ini file lists the URL schemes for which plugins are available and provides Merge with the name of the COM component responsible
for implementing access to the scheme’s file system. An example vfsplugins.ini file is shown below:
[.] progid=Merge.Win32VFS description=Win32 autoregister=fsplugin.dll [ftp] progid=Merge.FtpVFS description=FTP autoregister=fsplugin.dll
The vfsplugins.ini file consists of an unlimited number of sections. Each section begins with the URL scheme that is to be handled by a file
system plugin component. The component that is registered for the . scheme is used to handle any URL that isn’t explicitly handled by the other sections.
The first section (beginning [.]) registers the Win32 file system plugin, which handles Win32 file paths (for example, c:\temp\file.txt, \\server\path\file.txt, \path\file.txt) and any URLs that aren’t handled by the other registered plugins. The second section (beginning [ftp]) registers a plugin to handle URLs that use the ftp scheme (for example, ftp://ftp.microsoft.com/).
Each line within a section consists of a key and value, separated by an equals sign. The following table describes the keys that can be used, and the values with which they should be provided:
| Key | Value |
|---|---|
| progid | The progid for the COM component that implements the IFileSystem interface. The progid can be either version dependent (Merge.Win32VFS.1) or version independent (Merge.Win32VFS).
|
| description | A description of the file system support provided by the plugin. |
| autoregister | If the component specified by the progid can’t be created by Merge, the DLL specified by the autoregister key is registered using its DllRegisterServer entry point, and the creation operation is retried. The value of this key should specify the location of the plugin DLL relative
to the Merge installation folder.
|
A component that implements this interface typically implements IFileSystemInit as well.
Threading Models
Virtual file system component servers can be implemented either as in-process or as local servers. For performance reasons, we recommend that servers are in-process, and that they use the Apartment, Both, or Free threading model. Merge may create instances of plugin components in multiple threads, so components must follow standard thread-safety guidelines applicable to the threading model that is being used.
Error Handling
Merge will use the standard OLE ISupportErrorInfo mechanism to obtain error information when a method or property fails. Error messages provided through this mechanism are usually displayed verbatim to the user, and should therefore be as informative as possible.
Properties
Capability
| IDL | [propget] HRESULT Capability([in] Capability nCapability, [in] IUrlCollection* pHintUrls, [out, retval] CapabilityLevel* pValue) |
|---|---|
| .NET | CapabilityLevel get_Capability(Capability nCapability, IUrlCollection pHintUrls) |
| VB6 | Capability(nCapability As Capability, pHintUrls As IUrlCollection) As CapabilityLevel |
Operations on some filesystems may be harder or slower to perform than on others. Merge uses this property to determine the extent to which a particular capability is supported by a plugin, and its efficiency.
The property is read-only.
Arguments
-
nCapability
A specific capability for which the plugin’s level of support is required.
-
pHintUrls
A collection of hint URLs that may be specified along with the capability to help determine the level of support for the capability.
TemporaryFileName
| IDL | [propget] HRESULT TemporaryFileName([in] BSTR strUrl, [out, retval] BSTR* pValue) |
|---|---|
| .NET | String get_TemporaryFileName(String strUrl) |
| VB6 | TemporaryFileName(strUrl As String) As String |
This property should return the URL for a file that can be used by Merge to store a temporary copy of the file specified by
strUrl. The temporary file should be located close to the file specified by strUrl. When Merge saves over a file, it takes a temporary
backup copy in case the save fails due to there being insufficient storage space. If the save fails, the user is told where
the temporary backup is located so that they can sort out the problem.
The property is read-only.
Arguments
-
strUrl
The URL to an existing file located within the plugin’s file system.
Methods
AppendPathToURL
| IDL | HRESULT AppendPathToURL([in] BSTR strUrl, [in] BSTR strPath, [out, retval] BSTR* pValue) |
|---|---|
| .NET | String AppendPathToURL(String strUrl, String strPath) |
| VB6 | AppendPathToURL(strUrl As String, strPath As String) As String |
This method should append strPath to strURL to form a valid URL within the filesystem.
Arguments
-
strUrl
The URL to which the path is to be appended.
-
strPath
The path that is to be appended to the URL.
BindFile
| IDL | HRESULT BindFile([in] BSTR strUrl, [in] VARIANT_BOOL bMustExist, [out, retval] IFile** pValue) |
|---|---|
| .NET | IFile BindFile(String strUrl, Boolean bMustExist) |
| VB6 | BindFile(strUrl As String, bMustExist As Boolean) As IFile |
This method returns the IFile interface for an object representing a file within the plugin’s file system.
Arguments
-
strUrl
The URL for a file located within the plugin’s file system.
-
bMustExist
If
True, a result should only be returned if the file exists. IfFalse, a result should always be returned (thus enabling files to be created).
BindFolder
| IDL | HRESULT BindFolder([in] BSTR strUrl, [in] VARIANT_BOOL bMustExist, [out, retval] IFolder** pValue) |
|---|---|
| .NET | IFolder BindFolder(String strUrl, Boolean bMustExist) |
| VB6 | BindFolder(strUrl As String, bMustExist As Boolean) As IFolder |
This method returns the IFolder interface for an object representing a folder within the plugin’s file system.
Arguments
-
strUrl
The URL for a folder located within the plugin’s file system.
-
bMustExist
If
True, a result should only be returned if the folder exists. IfFalse, a result should always be returned (thus enabling folders to be created).
CopyFile
| IDL | HRESULT CopyFile([in] BSTR strFromUrl, [in] BSTR strToUrl, [in] IContinueOperation* pContinue) |
|---|---|
| .NET | void CopyFile(String strFromUrl, String strToUrl, IContinueOperation pContinue) |
| VB6 | CopyFile(strFromUrl As String, strToUrl As String, pContinue As IContinueOperation) |
This method is used to copy a file within the plugin’s file system. The source and target URLs are guaranteed to
refer to files within the plugin’s file system. Lengthy copy operations should use the pContinue argument to check whether
the user wants to abort the copy. This method should replace an existing target file unless prevented from doing so by an
error.
Arguments
-
strFromUrl
The URL for a file located within the plugin’s file system.
-
strToUrl
The URL for a file located within the plugin’s file system.
-
pContinue
A reference to an object that can be checked during lengthy copy operations to see if the copy should continue.
Delete
| IDL | HRESULT Delete([in] IUrlCollection* pItems, [in] VARIANT_BOOL bNeverPrompt, [in] VARIANT_BOOL bRecursive) |
|---|---|
| .NET | void Delete(IUrlCollection pItems, Boolean bNeverPrompt, Boolean bRecursive) |
| VB6 | Delete(pItems As IUrlCollection, bNeverPrompt As Boolean, bRecursive As Boolean) |
Deletes the URLs specified within the collection.
Arguments
-
pItems
A collection of URLs that are to be deleted.
-
bNeverPrompt
Whether the user should not be prompted to delete the items.
-
bRecursive
Whether folders within the URL collection should be deleted recursively.
