This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Object Type Properties - Connection External Database - Change Object ID

Hello everyone,

We have a Project Object connected to an external Database. We've used the Project Number as the M-Files Object ID.
Unfortunately, we've noticed (a bit too late) that the customer was changing the Project Numbers on the external application which created inconsistent metadata in certain documents. We had documents where the project was removed/deleted because the Object ID was changed from the Project Number.

For example : The project was created in M-Files with Project Number 021004 and the Object ID with the same identifier.
The customer changed the Project Number to 622003 and the reaction on M-Files was that 021004 project was deleted, it only remained a project with the number 622003 without the history before that changement (Creation of 622003 Project)

We've asked the Database Projects Provider to add in the DB's view a unique identifier that we'll use as Object ID in M-Files.

My question is : Changing the object ID will unlink the project in the documents metadata right ? (Project deleted metadata)

Thanks for your answers,
Leitao Claudio

Parents
  • Dear All,

    I've created a PowerShell script that does the work.
    If it can help any of you, here it goes.

    <#
    @Author : Claudio Leitao
    @Date : 28.04.2022
    @LastModification : 28.04.2022
    @Version : 1.0
    @Description : This scripts replaces deleted lookups in documents and replace them with the new ones
    #>
    
    # Retrieve the necessary DLL in order for this script to call the native M-Files COM API Function
    Add-Type -Path "C:\Program Files\M-Files\$env:mfilesversion\Common\Interop.MFilesAPI.dll"
    
    # Returns the M-Files VaultConnection Object
    Function Get-MFilesVault {
        [CmdletBinding()]
        Param(
            [Parameter(Mandatory=$True)]
            [string]$Name,
            [parameter(Mandatory=$True)]
            [object[]]$Connection
        )
    
        $Connection.GetVaultConnection($Name)
    }
    
    # Tests the connection to the Specified Vault and returns its result
    Function Test-MFilesVaultConnection {
        [CmdletBinding()]
        Param(
            [parameter(Mandatory=$True)]
            [object[]]$VaultConnection
        )
    
        return $VaultConnection.TestConnectionToVaultSilent()
    }
    
    # Create a connection to the vault and returns the Vault with the user connected to it
    Function Connect-MFilesVault {
        [CmdletBinding()]
        Param(
            [parameter(Mandatory=$True)]
            [object[]]$VaultConnection,
            [Parameter(Mandatory=$True)]
            [object]$AuthType,
            [Parameter(Mandatory=$False)]
            [string]$UserName,
            [Parameter(Mandatory=$False)]
            [string]$Password,
            [Parameter(Mandatory=$False)]
            [string]$Domain
        )
        
        return $VaultConnection.LogInAsUser($AuthType, $UserName, $Password, $Domain)
    
    }
    
    # Binds the VaultConnection to the Vault
    Function Set-MFilesVaultConnection {
        [CmdletBinding()]
        Param(
            [parameter(Mandatory=$True)]
            [object[]]$VaultConnection
        )
    
        $VaultConnection.BindToVault(0, $true, $false)
    }
    
    # Get the content of a specfic VIEW ID
    Function Get-FolderContentItemsVIEW {
        [CmdletBinding()]
        Param(
            [parameter(Mandatory = $True)]
            [long]$ViewID,
            [parameter(Mandatory = $True)]
            [object]$Vault
        )
    
        $FolderDefsView = New-Object -COM MFilesAPI.FolderDefs
        $FolderDefView = New-Object -COM MFilesAPI.FolderDef
        $FolderDefView.SetView($ViewID)
        $FolderDefsView.Add(-1, $FolderDefView)
    
        Return $Vault.ViewOperations.GetFolderContents($FolderDefsView)
    }
    
    # Get the project lookup based on its submission number
    Function Get-ProjectLookup-FromSubNum {
        [CmdletBinding()]
        Param(
            [parameter(Mandatory = $True)]
            [long]$ViewID,
            [parameter(Mandatory = $True)]
            [object]$Vault,
            [parameter(Mandatory = $True)]
            [String]$ProjectSubNum
        )
    
        # Get the Folder Content items set with a view ID
        $FolderContentItems = Get-FolderContentItemsVIEW -ViewID $ViewID -Vault $Vault
    
        # Look for each Project
        foreach ($item in $FolderContentItems){
    
            # Get the property of the current ObjVer Item
            $ObjVerProp = $Vault.ObjectOperations.GetObjectVersionAndProperties($item.ObjectVersion.ObjVer, $true).Properties
    
            # Get the projects name
            $ProjectSubNumber = $ObjVerProp.SearchForProperty(1435).TypedValue.DisplayValue
    
            if ($ProjectSubNumber -eq $ProjectSubNum){
                $ProjectLookup = New-Object -COM MFilesAPI.Lookup
                $ProjectLookup.item = $item.ObjectVersion.ObjVer.ID
                $ProjectLookup.version = -1
                Return $ProjectLookup
            }
        }
    
    }
    
    # Set the new project on the document
    Function Set-NewProject {
        [CmdletBinding()]
        Param(
            [parameter(Mandatory = $True)]
            [long]$ViewID,
            [parameter(Mandatory = $True)]
            [object]$Vault
        )
    
        # Get the Folder Content items set with a view
        $FolderContentItems = Get-FolderContentItemsVIEW -ViewID $ViewID -Vault $Vault
    
        foreach ($item in $FolderContentItems){
            
            # Get the property of the current ObjVer's Item
            $ObjVerProp = $Vault.ObjectOperations.GetObjectVersionAndProperties($item.ObjectVersion.ObjVer, $true).Properties
    
            # Get the projects name
            $ProjectName = $ObjVerProp.SearchForProperty(1320).TypedValue.DisplayValue
            # Get the projects submission number from its name
            $ProjectSubNumber = $ProjectName.Substring(0,8)
    
            # Gets the project Lookup
            $ProjectObjLookup = Get-ProjectLookup-FromSubNum -ViewID 428 -Vault $Vault -ProjectSubNum $ProjectSubNumber
    
            # Creates a new ObjVer for Check Out and Check In
            $newDocObjId = New-Object -COM MFilesAPI.ObjID
            $newDocObjId.SetIDs(0, $item.ObjectVersion.ObjVer.ID)
            $newDocObjVer = $Vault.ObjectOperations.GetLatestObjVer($newDocObjId, $False, $True)
            $newDocObjVer.Version = ([int]$newDocObjVer.Version + [int]1)
    
            # checks out the document
            $Vault.ObjectOperations.CheckOut($newDocObjVer.ObjID)
    
            # Sets the new project lookup
            $projectPropVal = New-Object -COM MFilesAPI.PropertyValue
            $projectPropVal.PropertyDef = 1320
            $ProjectPropVal.Value.SetValue([MFilesAPI.MFDataType]::MFDatatypeLookup, $ProjectObjLookup)
            $Vault.ObjectPropertyOperations.SetProperty($newDocObjVer, $ProjectPropVal)
    
            # Checks the object IN
            $Vault.ObjectOperations.CheckIn($newDocObjVer)
    
            
        }
    }
    
    # MAIN PART OF THIS SCRIPT
    # Execute all the correct functions with the correct paramaters 
    
    # Using M-Files Client
    $MFClient = New-Object -COM MFilesAPI.MFilesClientApplication
    
    # Get M-Files Vault Connection
    $VaultConnection = Get-MFilesVault -Name "PPSA" -Connection $MFClient
    
    # Test Connection to Document Vault
    $ConnectResult = Test-MFilesVaultConnection -VaultConnection $VaultConnection
    
    # View ID
    $ViewID = 427
    
    If($ConnectResult -eq 0){
        # Connect to Document Vault
        $Vault = Set-MFilesVaultConnection -VaultConnection $VaultConnection
    
        Set-NewProject -ViewID $ViewID -Vault $Vault
    
    } ElseIf ($ConnectResult -eq 1){
        # Connect to Document Vault using different credentials
        $Vault = Connect-MFilesVault -VaultConnection $VaultConnection -AuthType $([MFilesAPI.MFAuthType]::MFAuthTypeSpecificWindowsUser) -UserName "xxxxxx" -Password "xxxxxx" -Domain "AD"   
    
        Set-NewProject -ViewID $ViewID -Vault $Vault
    } Else {
    
       $SMTPPwd = "xxxxx"
       $SMTPUsername = "xxxxxx"
       $secpasswd = ConvertTo-SecureString $SMTPPwd -AsPlainText -Force;             
       $credentials = New-Object System.Management.Automation.PSCredential($SMTPUsername, $secpasswd);
    
       Send-MailMessage -To "xxxxxx" -from "xxxxx" -SmtpServer "xxxxxx" -Port xxxx -Subject "xxxxxxx" -Credential $credentials -BodyAsHtml  -Encoding utf8;    
    }


    Regards,
    Claudio

  • Hi Claudio, can you explain what does the script do exactly?

Reply Children
  • Dear Karlo,

    It's a Powershell script using the COM.API of M-Files.
    It starts a vault session with a specific account and replaces all (deleted) lookups with  new ones.

    I made this script because we had references problems with external objects and needed to change their Object ID. When you do so, you lose the ref to other documents.
    So i'm just looking for those deleted references and replace them with the new and correct ones.

    Hope it helps,
    Claudio

  • Thanks for the info! Does the script needs to be adjusted based on certain class? Because in my scenario we have a class "Items" which is currently connected to Access DB and it has IDs as number from DB "123" but we need to connect it to the different one where IDs dont match, in that second database the IDs are "HR123". Would this script help in this situation?

  • The script is given as it is. You'll definitely need to change a few things in the script.
    However, you'll probably find all the necessary functions inside.

    If you have any further questions, do not hesitate to contact me on my pro mail address (link in my profile)

  • Well you can expect me in your mailbox then :)