Consider this very simple C# SOLIDWORKS Macro:
using SolidWorks.Interop.sldworks;
using System.Runtime.InteropServices;
using System;
using System.IO;
using System.Windows.Forms;
using EdmLib;
namespace FileMoveTest.csproj
{
public partial class SolidWorksMacro
{
private const string VAULTNAME = "YOUR VAULT NAME";
private const string FILEPATH = "PATH TO A FILE IN YOUR VAULT";
private const string DESTFOLDERPATH = "PATH TO A FOLDER IN YOUR VAULT";
public void Main()
{
IEdmVault16 vault =new EdmVault5() as IEdmVault16;
vault.LoginAuto(VAULTNAME,0);
IEdmFolder5 folder = null;
IEdmFile11 testFile = (IEdmFile11)vault.GetFileFromPath(FILEPATH, out folder);
IEdmFolder5 destFolder = vault.GetFolderFromPath(DESTFOLDERPATH);
try
{
testFile.Move(0, folder.ID, destFolder.ID, 0);
}
catch (COMException cex)
{
MessageBox.Show(cex.Message);
}
catch (FileLoadException fle)
{
MessageBox.Show(fle.Message);
}
}
///
/// The SldWorks swApp variable is pre-assigned for you.
///
public SldWorks swApp;
}
}
My testing has shown that for some file types, attempting to move an open file will result in an undocumented FileLoadException with the exception message:
The process cannot access the file because it is being used by another process
For example, attempting to move a SOLIDWORKS part file that is open in SOLIDWORKS will result in a FileLoadException. Attempting to move the same file when it is open in eDrawings will not throw the exception. If a Word document is open in MS Word, the exception is thrown. If a text file is open in Notepad, no exception is thrown.
I have delved into the assembly code via the Visual Studio debugger and determined that the call to IEdmFile6::Move calls into an EPDM DLL (aptly named named Move.dll). This DLL is responsible for executing the necessary stored procedures to keep the database up to date with respect to the moved file. Once that is done, the Win32 API function MoveFileEx is called, which performs a CopyFileEx, followed by a DeleteFileEx. The DeleteFileEx call ultimately goes deep down into a Windows system kernel call where something goes wrong and the return status is ERROR_SHARING_VIOLATION. The .NET framework detects this error and somewhere inside mscorlib.dll, the sharing violation is converted into a FileLoadException. The EPDM API totally ignores the fact that this can occur.
To further compound the problem, whether the exception is thrown or not, the file is "moved" to the destination directory but a local copy is left behind since the call to CopyFileEx succeeded but the call to DeleteFileEx failed.
So, the point of all this is that if you are using IEdmFile6::Move, you should should be looking for the FileLoadException and if it occurs you should:
- Check to see if the file was copied to the new location.
- If it was, check to see if a local copy of the original is still present by using System.IO.File.Exists().
- If the local copy exists, ask the user to close the open file and then use System.IO.File.Delete() to remove it.