9 Replies Latest reply on Aug 15, 2016 6:10 PM by Tyler Johnson

    Using the API to move files

    Tyler Johnson

      I have a custom created add-in to handle moving files based on card variables, using the IEdmFolder6.Move method.  99% of the time it works fine, but every once and awhile I'm getting a failed task.  I've finally narrowed down the exact scenario as described below.

       

      If UserA manually moves a file (drag/drop, cut/paste) from FolderA to FolderB and then UserB tries to run the task which would move the file from FolderB to FolderA.  The task fails.  The error generated is "An attempt was made to create a new file or folder with the same name as an existing one."  Which is because we do not allow files with the same name in our vault, but I'm moving a file not creating one...

       

      I've confirmed this only applies to a task (created from the custom addin).  If I do this from a stand alone application the issue does not exist.

      Actually, I just tried this again and I must have not tested correctly the first time around because this doesn't work from an external exe either.

       

      Also, oddly, if prior to executing the task UserB browses to FolderA in the vault, then runs the task.  The task runs successfully.  Based on that, it seems as though their needs to be some kind of refresh the task needs to do because that file location isn't getting updated after it's moved by someone else.  But why it only applies to a task/addin and not the stand alone application I don't understand.

       

      I've actually run into this exact issue before but it was with the creation of folders behaving the same way, created on one computer but unseen on another (from the addin's perspective) unless the parent folder was browsed too.  In that case it was solved by using a batchadd which must do some kind of magic.

       

      So I'm not really sure what I'm suppose to do here.

        • Re: Using the API to move files
          Lee CS Young

          Try calling vault.RefreshFolder(FolderA). This will force a refresh on the folder.

          • Re: Using the API to move files
            Jim Sculley

            I see this same behavior with one of my add-ins, but I'm not using Tasks at all.  Occasionally, a user will make a mistake and release a file incorrectly.  The release process is handled by my add-in and one of the steps in the process is to rename/move the file.  When a release is done incorrectly, I have to delete/destroy the file as admin and then the user can attempt to release again (using a copy of the file made before I destroyed the original).  Back when I wrote the add-in (EPDM 2012), this always worked without problems.  When we moved from EPDM 2013 to EPDM 2015, the file rename/move would fail unless the user browsed into the directory where the deleted file was located.  I didn't find a cause, and since it happens infrequently now that users are familiar with the release process, I simply send an email reminder (after I delete/destroy the file) to browse into the appropriate directory before attempting the release a second time.

             

            It is as if client machines are not informed of file deletions on other client machines until the user browses into the folder where the deletion took place.

             

            Jim S.

              • Re: Using the API to move files
                Tyler Johnson

                Yeah that sounds very similar.

                 

                Mine is part of our custom import process (we are only a few months into using EPDM) for setting vault revisions of existing files.  On release it runs my task to convert the file and move it.  This issue only comes up when a user accidentally released something early and they have to move it back into the special Import folder we are using.  Then on the 2nd release it can't move it into the folder it was just in unless it is browsed to first. 

                 

                Thankfully I don't have to go so far as destroying the file.

              • Re: Using the API to move files
                Tyler Johnson

                VAR was able to track down a workaround.  I'll just quote it because I can't really explain it.

                I think the problem lies in the local cache.  For example.  User 1 caches the file then User 2 moves the file.  Until User 1 browses to the folder the file was moved out of the locally cached file still exists in the actual windows file system.  To work around it I check at the file system level if the file exists in the same location and rename it to a unique name if it does (Delete doesn't work in this case because of some permissions problems).  This way the local file doesn't interfere with the operation.

                Anyway, checking for a local file with the same name as my source file in the destination folder and renaming it allows me to move my vault file and there is no junk file left over.  *shrug*

                 

                 

                UPDATE 8/15/2016

                 

                I ran into this issue again with a PDF creation function I have for dwg files.  The software thinks the file is there as read-only and won't overwrite when no file exists.  I did some more testing I discovered what I think is the root cause.  When files are deleted in PDM they still exist in the deleted items of the folder properties. 

                 

                If you call IEdmFolder7::DestroyDeletedItems, System.IO.File.Exists will return false.  The only downside is the method destroys everything in the folder, you can't specify a single file.

                 

                You can try it yourself with the below code if you so wish.  Create a file in the vault and close your explorer window.  Run the function on the file path.  You should find the vault file and get a local copy.  Then from a remote or 2nd computer delete the file from the vault.  Run the function again and it will not find the vault file but the windows api will still see a file.  Uncomment one of the methods and it should correct it so windows doesn't see the file anymore.

                 

                I like the destroy method because it makes more sense to me as to why it's happening.  When using the System.IO.File.Move(fpath, path & "Temp" & name) method it's a magic ether file as far as I can tell and have no clue what, if any, problems it may cause.

                 

                This was on Windows 10 and EPDM 15.2

                    Private Sub VaultTest(ByVal fPath As String)

                        Try

                 

                 

                            Dim vault As IEdmVault5 = New EdmVault5

                            If Not vault.IsLoggedIn Then

                                vault.LoginAuto("PPI Vault", 0)

                            End If

                 

                            Dim path As String = System.IO.Path.GetDirectoryName(fpath)

                            Dim name As String = System.IO.Path.GetFileName(fpath)

                            Dim vfile As IEdmFile10 = vault.GetFileFromPath(fpath)

                            Dim vfolder As IEdmFolder7 = vault.GetFolderFromPath(path)

                            Dim msg As String = Nothing

                 

                            If vfile Is Nothing Then

                                msg += "No vault file" & vbNewLine

                 

                                If System.IO.File.Exists(fpath) Then

                                    msg += "...but system file was found." & vbNewLine

                 

                                    'Method One: Uses Windows Api to move and rename to an magic invisible file

                                    'System.IO.File.Move(fpath, path & "Temp" & name)

                 

                                    'Method Two: Destroy the deleted files of the folder, but you have to destroy all of them.

                                    'Dim ppoDestroyedItems() As EdmFileInfo = Nothing

                                    'Dim paErrors() As EdmBatchDelErrInfo = Nothing

                                    'vfolder.DestroyDeletedItems(False, Date.Now, ppoDestroyedItems, paErrors)

                                    'For idx As Integer = LBound(ppoDestroyedItems) To UBound(ppoDestroyedItems)

                                    '    msg += "Deleted File: " & ppoDestroyedItems(idx).mbsPath & vbNewLine

                                    '    If ppoDestroyedItems(idx).mhResult = 0 Then

                                    '        msg += "Status: Destroyed" & vbNewLine

                                    '    Else

                                    '        msg += "Status: Failed: " + "HRESULT = 0x" + CStr(paErrors(idx).mlErrorCode) & vbNewLine

                                    '    End If

                                    'Next

                 

                                    If System.IO.File.Exists(fpath) Then

                                        msg += "...and it's still there!?" & vbNewLine

                                    Else

                                        msg += "but it's gone now." & vbNewLine

                                        If System.IO.File.Exists(path & "Temp" & name) Then

                                            msg += "but now the temp file is there" & vbNewLine

                                        Else

                                            msg += "and the temp file disappeared too." & vbNewLine

                                        End If

                                    End If

                                Else

                                    msg += "...and No System File!" & vbNewLine

                                    If System.IO.File.Exists(path & "Temp" & name) Then

                                        msg += "but a temp file is there." & vbNewLine

                                    Else

                                        msg += "...and no temp file!" & vbNewLine

                                    End If

                                End If

                            Else

                                msg += "Vault file found." & vbNewLine

                                If System.IO.File.Exists(fpath) Then

                                    msg += "System file found pre get." & vbNewLine

                                Else

                                    msg += "No System File pre get." & vbNewLine

                                End If

                                Dim batch As IEdmBatchGet = vault.CreateUtility(EdmUtility.EdmUtil_BatchGet)

                                Dim selection(0) As EdmSelItem

                                selection(0) = New EdmSelItem

                                selection(0).mlDocID = vfile.ID

                                selection(0).mlProjID = vfolder.ID

                                batch.AddSelection(vault, selection)

                                batch.CreateTree(Nothing, EdmGetCmdFlags.Egcf_Nothing)

                                batch.GetFiles(0)

                                If System.IO.File.Exists(fpath) Then

                                    msg += "System file found post get." & vbNewLine

                                Else

                                    msg += "No System File post get." & vbNewLine

                                End If

                            End If

                 

                            MessageBox.Show(msg)

                 

                        Catch ex As Exception

                            MessageBox.Show(ex.Message & vbNewLine & ex.ToString)

                        End Try

                 

                    End Sub