16 Replies Latest reply on Feb 14, 2014 12:26 PM by Tim Webb

    Prevent referenced files from being deleted?

    Joe Wilcoxson

      Is there any way I can prevent my users from deleting a file that has been referenced by another file, yet still allow them to delete unreferenced files? I noticed that when you delete a file, it gives you a dialog mentioning that a file is referenced by X number of other files, but you can just ignore this warning. The EPDM Admin tool allows you to turn warnings like this in to errors that cannot be ignored, but it only for the operations of change state, check in / out and increment revision. Does anyone have any ideas, or maybe I am just missing something? Using EPDM 2013 SP2.

        • Re: Prevent referenced files from being deleted?
          Tim Webb

          Hi Joe,

           

          You need a lightweight & low overhead addin that is called using EdmCmd_PreDelete hook (just before the file is deleted), scan for its parent references using GetFirstParentPosition2, and cancel the EPDM command thus blocking the delete if the list contains any parents.

           

          I quickly put an addin together and tested on a couple machines and it is working according to your requirements. If a file has parent files, the addin doesn't allow the file to be deleted and provides a nice little nag warning to the user notifying them of the parent files it is referencing.

           

          See my site here to download or use the attachment on this thread.

          http://www.equivaq.com/uploads/BlockDelete_v9.zip

          Disclaimer: addin provided as-is without warranty, express or implied.


          If you need assistance installing, email me at the contact information listed on the site.

           

          Let me know how it works.

          Tim CEPA

          http://www.equivaq.com

            • Re: Prevent referenced files from being deleted?
              Joe Wilcoxson

              Thank you Tim, I will try your add-in out. I was actually working on an add-in to do the very same thing last night, and got as far as displaying the FileID of the file about to be deleted and had written part of the code to scan for parent files. Got up to day to finish working on it, but if this works I may not have to. Is there any way you could send me the source code for this so I could compare to what I was working on?

               

              I contacted my VAR about this issue as well, just to see if there was an easy built-in way to accomplish this, and there is not. The best that had was that it was an enhancement request that didn't gain much popularity.

                • Re: Prevent referenced files from being deleted?
                  Tim Webb

                  Hey Joe, share your source code and I'll add pointers. Sorry mate, I don't have the source code with me today. Let me know if the addin loads.

                   

                  Tim CEPA

                  http://www.equivaq.com

                    • Re: Prevent referenced files from being deleted?
                      Joe Wilcoxson

                      Tim,

                      It wasn't loading, giving an "Archive Server could not open the Windows Registry" error.

                       

                      Heres the code I'm working with, not very far along right now, but admittedly I'm not working very hard on it today, mainly just toying around. Was mainly just trying to display the file ID and indicate if it is a referenced file or not at this point when the file was deleted. Once I had this worked out, I was going to remove the dialog boxes and add in the code to cancel the delete operation, maybe leaving a dialog box saying the file couldnt be deleted due to it being referenced.

                       

                                          case EdmCmdType.EdmCmd_PreDelete:

                                              EdmVault5 vault = new EdmVault5();

                                              vault.LoginAuto("Simplex_Vault", 0);

                                              for (int i = 0; i < ppoData.Length; i++)

                                              {

                                                  EdmCmdData data = (EdmCmdData)ppoData.GetValue(i);

                                                  int fileID =data.mlObjectID1;

                                                  MessageBox.Show(fileID.ToString());

                                                  IEdmFile5 file = (IEdmFile5)vault.GetObject(EdmObjectType.EdmObject_File, fileID);

                                                  for (int x = 1; x <= file.CurrentVersion; x++)

                                                  {

                                                      IEdmReference7 refTree = (IEdmReference7)file.GetReferenceTree(file.GetNextFolder(file.GetFirstFolderPosition()).ID, x);

                                                      if (!(refTree.GetFirstParentPosition2(1, true, 15).IsNull))

                                                      {

                                                          MessageBox.Show("This file is referenced in version " + x);

                                                      }

                                                      else

                                                      {

                                                          MessageBox.Show("This file is NOT referenced in version " + x);

                                                      }

                       

                                                  }

                                              }

                       

                       

                                              break;

                        • Re: Prevent referenced files from being deleted?
                          Tim Webb

                          Oh wow, that's c#. I will need to translate since I use vb.net

                           

                          What version of .Net framework is on your archive server?

                           

                          What version of EPDM are you running?

                          • Re: Prevent referenced files from being deleted?
                            Jim Sculley

                            When you are using an add-in you do not need to create a vault object.  A reference to the vault is passed to you when EPDM calls your GetAddinInfo() method.  Store it in a variable and you don't have to create one using new EDMVault() and you don't have to log in to it.

                             

                            I needed to do something in my addin that is similar to what you are doing.  I needed to take some action if a particular state change occurred and the file had parent references that were currently checked out.  Here is the piece of code I use to get a list of parent files that are checked out:

                             

                            ========================

                            /// <summary>

                            /// This method gathers the parent files that are checked out for the given file.

                            /// </summary>

                            /// <param name="file">the file whose checked out parents are to be determined</param>

                            /// <returns>a <see cref=">List"/> of <see cref="IEdmFile5"/> objects, one for each checked out parent file</returns>

                            private List<IEdmFile5> getCheckedOutParents(IEdmFile5 file)

                            {

                                List<IEdmFile5> checkedOutParents = new List<IEdmFile5>();

                                IEdmReference9 refTree = (IEdmReference9)file.GetReferenceTree(parentFolderID, 0);

                                IEdmPos5 pos = refTree.GetFirstParentPosition2(0, false, (int)EdmRefFlags.EdmRef_File);

                                while (!pos.IsNull)

                                {

                                    IEdmFile5 nextParent = refTree.GetNextParent(pos).File;

                                    if (nextParent.IsLocked)

                                    {

                                        checkedOutParents.Add(nextParent);

                                    }

                                }

                                return checkedOutParents;

                            }

                            ========================

                             

                            If the returned list has something in it, I pop up a warning dialog giving the user the option to proceed, cancel, or view the checked out parent files.  There is a handy .NET control called a ListView that you can use to display a list of files with an icon and multiple columns of useful information.  Mine shows the file name, who has it cheecked out and where it is checked out.

                             

                            This is all part of a much larger add-in, so I can't provide it or post all of the code, but if you have any questions on how to do it, feel free to ask.

                             

                            Jim S.

                            • Re: Prevent referenced files from being deleted?
                              Tim Webb

                              Joe,

                               

                              To aid in troubleshooting why the addin won't install, I usually have to do the following:

                              1. Determine what .Net framework is on the target server
                              2. Determine what version of EPDM is on the server

                               

                              If you can prvovide those, I can make changes on this end to get it running. Would you have time for a web conference? 10 minutes ought to do it.

                               

                              Tim

                                • Re: Prevent referenced files from being deleted?
                                  Joe Wilcoxson

                                  Server is running .NET Framework 4.5 and EPDM 2013 SP2. The addin I have made were compiled with .NET 2.0 and all seem to install fine. There was something I read in the API reference that says the error could be caused by the addin being compiled for .NET 4.0, as they mention that EPDM does not support it.

                                    • Re: Prevent referenced files from being deleted?
                                      Tim Webb

                                      Hi again Joe.

                                       

                                      From my very painful experience, the server running .Net 4.5.1 will not allow you to install a .Net addin, period. SW opened an SR on it for me SR:1-5200028166.

                                       

                                      Actually EPDM 2013 supports .Net 4 addins, no worries there but your server and any clients running .Net 4.5.1 will not run any .Net addins.

                                       

                                      In fact, your own addin will probably never install even following the KB recommendations even though you compile it yourself. I have 2 development computers, 1 running .Net 4 and 1 running .Net 4.5.1 and no matter what I do with my program I cannot get any .Net addin targeting any .Net framework to ever install on the .Net 4.5.1 server.

                                       

                                      My recommendation is removing .Net 4.5.1, installing .Net 4 (not client profile but the whole extended one), and using that same install I copied above.

                                       

                                      Here's the VB.Net source code:

                                       

                                      Imports EdmLib

                                       

                                      Public Class BlockDelete

                                          Implements IEdmAddIn5

                                       

                                          Public Sub GetAddInInfo(ByRef poInfo As EdmLib.EdmAddInInfo, ByVal poVault As EdmLib.IEdmVault5, ByVal poCmdMgr As EdmLib.IEdmCmdMgr5) Implements EdmLib.IEdmAddIn5.GetAddInInfo

                                              'Just some information for the Administrate Add-ins dialog box

                                      poInfo.mbsAddInName = "BlockDelete"

                                      poInfo.mbsCompany = "equivaQ Software, LLC."

                                      poInfo.mbsDescription = "Blocks a delete operation if the file is referenced."

                                      poInfo.mlAddInVersion = 8

                                      poInfo.mlRequiredVersionMajor = 12

                                      poInfo.mlRequiredVersionMinor = 0

                                       

                                      poCmdMgr.AddHook(EdmCmdType.EdmCmd_PreDelete)

                                       

                                          End Sub

                                       

                                          Public Sub OnCmd(ByRef poCmd As EdmLib.EdmCmd, ByRef ppoData As System.Array) Implements EdmLib.IEdmAddIn5.OnCmd

                                              Try

                                                  If poCmd.meCmdType = EdmCmdType.EdmCmd_PreDelete Then

                                      Dim vault As IEdmVault11 = Nothing

                                      Dim file As IEdmFile5 = Nothing

                                      Dim folder As IEdmFolder5 = Nothing

                                      Dim Ctr As Integer = 0

                                       

                                      vault = poCmd.mpoVault

                                      For Ctr = 0 To UBound(ppoData)

                                      file = vault.GetObject(EdmObjectType.EdmObject_File, ppoData(Ctr).mlObjectID1)

                                      folder = vault.GetObject(EdmObjectType.EdmObject_Folder, ppoData(Ctr).mlObjectID2)

                                      'MsgBox("File: " & file.Name & vbNewLine & "Folder: " & folder.LocalPath)

                                      Dim RefCount As Integer = 0

                                                          RefCount = ShowItemRefs(vault, file, folder)

                                      If RefCount > 0 Then

                                                              Dim newPOcmd As EdmLib.EdmCmd = Nothing

                                                              newPOcmd = poCmd

                                                              newPOcmd.mbCancel = True

                                                              poCmd = newPOcmd

                                      End If

                                      Next Ctr

                                                  End If

                                              Catch ex As Exception

                                      MsgBox("Error in OnCmd: " & ex.Message, MsgBoxStyle.Exclamation)

                                              End Try

                                          End Sub

                                       

                                          Private Function ShowItemRefs(ByVal vault As IEdmVault11, ByRef iFile As IEdmFile5, ByRef ParentFolder As IEdmFolder5) As Integer

                                              Try

                                                  'Get the reference tree interface

                                                  Dim count As Integer = 0

                                                  Dim ref As IEdmReference7

                                      ref = iFile.GetReferenceTree(ParentFolder.ID)

                                                  'Enumerate parent references

                                                  Dim msg As String

                                      msg = "Items attached to file '" + iFile.Name + "':" + vbLf

                                                  Dim pos As IEdmPos5

                                      pos = ref.GetFirstParentPosition2(0, False, EdmRefFlags.EdmRef_File + EdmRefFlags.EdmRef_Item + EdmRefFlags.EdmRef_Dynamic + EdmRefFlags.EdmRef_Static)

                                                  While Not pos.IsNull

                                      count = count + 1

                                      Dim parent As IEdmReference7

                                      parent = ref.GetNextParent(pos)

                                      msg = msg + parent.FoundPath + vbLf

                                                  End While

                                      MsgBox(count & " Files reference this file. Cancelling 'DELETE' command." & vbNewLine & vbNewLine & msg)

                                                  Return count

                                              Catch ex As Exception

                                      MsgBox("Error in ShowItemRefs: " & ex.Message, MsgBoxStyle.Exclamation)

                                                  Return 1000

                                              End Try

                                          End Function

                                      End Class

                                      • Re: Prevent referenced files from being deleted?
                                        Tim Webb

                                        I noticed you said your .Net 2 addin seems to install fine. Question is, does it run?

                              • Re: Prevent referenced files from being deleted?
                                Larry Heir

                                I have a quick and most likely dumb question. Does this type of referenced file deletion prevention interfere with the ability to move files to different folders in the vault or is that not an issue? I ask since you need delete rights in the file's original folder to allow a file to be moved if duplicate file names are not allowed is active if I recall correctly. Thanks for an interesting thread!

                              • Re: Prevent referenced files from being deleted?
                                Joe Wilcoxson

                                Go it all working using a combo of Jim and Tims suggestions.

                                 

                                case EdmCmdType.EdmCmd_PreDelete:

                                 

                                 

                                          for (int i = 0; i < ppoData.Length; i++)

                                          {

                                                    EdmCmdData data = (EdmCmdData)ppoData.GetValue(i);

                                                    int fileID =data.mlObjectID1;

                                                    IEdmFile5 file = (IEdmFile5)edmVault.GetObject(EdmObjectType.EdmObject_File, fileID);

                                                    bool referenced = false;

                                                    for (int x = 1; x <= file.CurrentVersion; x++)

                                                    {

                                                              IEdmReference7 refTree = (IEdmReference7)file.GetReferenceTree(file.GetNextFolder(file.GetFirstFolderPosition()).ID, x);

                                                              IEdmPos5 pos = refTree.GetFirstParentPosition2(0, true, 15);

                                                              if (!pos.IsNull)

                                                              {

                                                                        referenced = true;

                                                              }

                                                    }

                                 

                                 

                                                    if (referenced)

                                                    {

                                                              MessageBox.Show("This file has been referenced and cannot be deleted");

                                                              EdmCmd newPOcmd = new EdmCmd();

                                                              newPOcmd = poCmd;

                                                              newPOcmd.mbCancel = 1;

                                                              poCmd = newPOcmd;

                                                    }

                                 

                                 

                                          }

                                 

                                 

                                          break;