IEdmFile::RenameEx fails when executed form out-of-process code

I have a need to rename files from outside SOLIDWORKS that are open inside SOLIDWORKS. The PDM API has a handy ForceReleaseLocks method that is supposed to detach a file from the file system so that it can be modified and such. I’ve found that this doesn’t seem to work for out-of-process code. To test this, I have a part file named ‘A.SLDPRT’ in my PDM vault and I open it in SOLIDWORKS:

The file is checked in, but is in a state and folder where I do have rename permissions.

I can write a macro like this:

Dim swApp As SldWorks.SldWorks
Dim v As EdmVault5
Dim f As IEdmFile18
Dim pFolder As IEdmFolder13
Dim retval As Integer
Dim nextDoc As ModelDoc2
Dim mExt As ModelDocExtension
Dim vDocs As Variant
Dim newPath As String

Sub main()
    Set swApp = Application.SldWorks
    Set v = New EdmVault5
    v.LoginAuto "_DEVELOPMENT", 0
    vDocs = swApp.GetDocuments()
    For i = LBound(vDocs) To UBound(vDocs)
        Set nextDoc = vDocs(i)
        If nextDoc.GetTitle = "A.sldprt" Then
            retval = nextDoc.ForceReleaseLocks()
            Set f = v.GetFileFromPath(nextDoc.GetPathName(), pFolder)
            f.RenameEx 0, "X" & nextDoc.GetTitle(), 0
            Set mExt = nextDoc.Extension
            newPath = f.GetLocalPath(pFolder.ID)
            retval = mExt.ReloadOrReplace(True, newPath, True, True)
            If retval <> swComponentReloadError_e.swReloadOkay Then
                retval = swApp.SendMsgToUser2("Error reloading", swMessageBoxIcon_e.swMbStop, swMessageBoxBtn_e.swMbOk)
            End If
            Exit Sub
        End If
    Next i
End Sub

and it works without problems. The file is renamed to XA.SLDPRT and the feature tree reflects this change:

If I write a console application to do the same thing:

using EPDM.Interop.epdm;
using System.Runtime.InteropServices;
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;

namespace ConsoleApp1
{
    class RenameExTest
    {
        private static IEdmVault22 vault;
        private const string VAULT_NAME = "_DEVELOPMENT";        
        private static SldWorks swApp;
        private static int windHandle = 0;

        static void Main(string[] args)
        {
            vault = new EdmVault5() as IEdmVault22;
            windHandle = (int)System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
            vault.LoginAuto(VAULT_NAME, windHandle);
            swApp = Marshal.GetActiveObject("SldWorks.Application") as SldWorks;            
            object[] openDocsObjArray = swApp.GetDocuments() as object[];
            foreach (object obj in openDocsObjArray)
            {
                ModelDoc2 nextDoc = obj as ModelDoc2;

                if (nextDoc.GetTitle().Equals("A.sldprt")) {                   
                    nextDoc.ForceReleaseLocks();                   
                    IEdmFolder5 pFolder;
                    IEdmFile18 f = vault.GetFileFromPath(nextDoc.GetPathName(), out pFolder) as IEdmFile18;
                    string newName = "X" + nextDoc.GetTitle();
                    f.RenameEx(windHandle, newName, 0);
                    string newPath = f.GetLocalPath(pFolder.ID);
                    ModelDocExtension mExt = nextDoc.Extension;
                    int retval = mExt.ReloadOrReplace(false, newPath, true, false);
                    if (retval != (int)swComponentReloadError_e.swReloadOkay) {
                        retval = swApp.SendMsgToUser2("Error reloading", (int)swMessageBoxIcon_e.swMbStop, (int)swMessageBoxBtn_e.swMbOk);
                    }                   
               }
            }
        }
    }
}

the program errors out with a rather cryptic PDM exception:

and strangely the file actually does get renamed in the vault, but SW doesn’t update. Also, if I wrap that RenameEx call in a try block and ignore the exception, I can inspect the Name property of the f variable and it still shows the old name, even though the file in the vault is renamed:
image
image

The subsequent attempt to call to ReloadOrReplace then fails because the call to GetLocalPath returns a file with the name A.SLDPRT but the file has been renamed XA.SLDPRT.

To add even more confusion, if I run the program when the only file open in SOLIDWORKS is an assembly that contains A.SLDPRT, the RenameEx call fails, but with a different error code:

This error sort of makes sense, but I thought that ForceReleaseLocks would prevent it. Ignoring the exception leads to ReloadOrReplace failing with a different error, stating that the document hasn’t changed.

All in all, a giant confusing mess.

Has anyone used these methods successfully in an out of process scenario? My particular use case will be doing stuff like this from a PDM add-in (which run outside the SW process) which fails in the same manner.

I didn’t realize that renaming a file that’s loaded in Solidworks was even possible. This is interesting.

Strange about that cryptic exception. We get that exact “The file-format plugin cannot handle…” error message from time to time when caching what appears to be random .sld files. I’m assuming they come from the pdm process. I need to pay more attention next time I get one to see if the file being cached (the dialog gives the file name) is loaded in SW.

As for f.GetLocalPath still returning the old name, it feels like the edmFile object reference needs updated, which is strange as that is what RenameEx was called from. If the file in vault view shows new name, what if f instance is refreshed with a second call to v.GetFileFromPath(pFolder.LocalPath + newName) before getting newPath from f.GetLocalPath? For that matter, can you build the file name for the mExt.ReloadOrReplace()? After checking that the pdm renamed succeeded.

Just a guess.

Filesystem and solidworks internal document references are probably not in sync.
The physical file on the disk is changed, but the SW file internal “database” of references is not.

This is likely the cause of the PDM warning “the file is opened by another application” when you try PDM operations from within explorer while you have a file already opened in SW and viceversa.

The document properties API kicks in from within SW or explorer and it probably wants exclusive access to perform both tasks in sync (rename file on disk and update of its internal references).

I could imagine that kind of limitation.

Yes, calling GetFileFromPathwith the new path does get the IEdmFile reference straightened out, but this is only helpful when dealing with a part file that is open directly in SOLIDWORKS. If the part is in an assembly, RenameEx throws the E_EDM_FILE_SHARE_ERROR and the file in the vault is not renamed at all.

Interestingly, the same file share error is thrown if I remove the ForceReleaseLocks call from the in-process macro. So ForceReleaseLocks is doing something, but only for in-process code apparently.

This issue is something I’ve been fighting with since 2016. My workaround has been to close the file (if it was opened directly), rename, and then re-open the file. If it was opened indirectly (as part of an assembly), I would programmatically replace the file temporarily with an empty part file, rename, and then replace the empty part file with the renamed file. All the extra opening and closing was prone to failures and really slowed things down when dealing with large subassemblies.

I’ve bundled up my latest test macro and application and sent it off to my VAR for clarification.

1 Like

Ok, that part went over my head before. So ForceReleaseLocks “always” works in process, for out of process it works on files directly open, but not on loaded reference files?

OT: Your VAR helps you with API projects? Is that part of your service agreement or pay by the hour type thing?

Not quite. It always works for in-process (even if I have the model and the assembly open).
For out of process it always fails, but fails in two different ways. For single files, the PLUGIN exception is thrown even though the file is renamed and in the running code, the corresponding IEdmFile thinks the file was not renamed. For files inside assemblies, the SHARING error occurs and the file is not renamed.

The API is part of SOLIDWORKS. If there is something in the API you think is broken, or isn’t documented properly and you are on subscription you are supposed to contact your VAR:

Humorous aside: The API Forums link still points to the old Jive forums and now gives a 404 error.

Of course nearly ever API issue I’ve contacted my VAR about has ben kicked up the chain to SOLIDWORKS and if it gets fixed (big IF) it only happens after 3 or more major versions have been released. I also have to make the absolute simplest examples I can, otherwise they will want me to send my entire codebase for them to pick apart trying to figure out how my code is at fault.

1 Like

The VAR got back to me. Essentially, ForceReleaseLocks only works for in-process code. So, I’ll have to get creative. I’m going to try creating a small SW add-in that I can hook into via ISldWorks::CallBack so that ForceReleaseLocks and ReloadOrReplace calls happen in-process.

1 Like

So they offer debugging too then. :wink:

I’m curious, is the SW PDM Add-in loaded in SW when you tried this?

Yo. Turn off Prefer 32 bits from the project properties.

It works fine for me with PDMShell and that’s an out of process application.

I use it with these two command :

Amen,
Blue Byte Systems Inc.
bluebyte.biz