We are currently working on integrating Vault with 3DX. As part of this process, it's important to note that 3DX enforces strict naming conventions within Enovia—parts must adhere to specific naming rules provided by 3DX. The customer has requested that all legacy data be renamed to align with these conventions. To support this, we are renaming the assemblies using the new names supplied by 3DX.
I am using below function RenameFileViaUpload to rename the parts first, then i am using another function RebuildAssemblyFromVaultStructure to update the references in assembly, then i am calling RenameFileViaUpload to rename assembly. Here are the functions:
public static void RenameFileViaUpload(
VDF.Vault.Currency.Connections.Connection connection,
Autodesk.Connectivity.WebServices.File file,
string newName)
{
try
{
var wsFolder = connection.WebServiceManager.DocumentService.GetFolderById(file.FolderId);
var vdfFolder = new VDF.Vault.Currency.Entities.Folder(connection, wsFolder);
// Step 2: Get the local working folder path
string localFolderPath = connection.WorkingFoldersManager.GetWorkingFolder(wsFolder.FullName).FullPath;
string originalFilePath = Path.Combine(localFolderPath, file.Name);
string newFilePath = Path.Combine(localFolderPath, newName);
//Checkout the file
MxLogger.LogEnovia("Checkout the file.");
VDF.Vault.Settings.AcquireFilesSettings aqSettings = new VDF.Vault.Settings.AcquireFilesSettings(connection)
{
DefaultAcquisitionOption = VDF.Vault.Settings.AcquireFilesSettings.AcquisitionOption.Checkout
};
FileIteration vdfFile = new FileIteration(connection, file);
aqSettings.AddEntityToAcquire(vdfFile);
AcquireFilesResults results = connection.FileManager.AcquireFiles(aqSettings);
FileAcquisitionResult fileAcquisitionResult = results.FileResults.FirstOrDefault();
// Step 3: Download the file to the local folder
MxLogger.LogEnovia("Download the file to the local folder.");
var acquireSettings = new VDF.Vault.Settings.AcquireFilesSettings(connection)
{
LocalPath = new VDF.Currency.FolderPathAbsolute(localFolderPath)
};
acquireSettings.AddEntityToAcquire(new VDF.Vault.Currency.Entities.FileIteration(connection, file));
connection.FileManager.AcquireFiles(acquireSettings);
// Step 4: Rename the file locally
MxLogger.LogEnovia("Rename the file locally.");
if (System.IO.File.Exists(newFilePath))
{
System.IO.File.Delete(newFilePath); // Avoid conflict
}
System.IO.File.Move(originalFilePath, newFilePath);
// Step 6: Upload the renamed file using FileManager.AddFile
MxLogger.LogEnovia("Upload the renamed file.");
using (var stream = new FileStream(newFilePath, FileMode.Open, FileAccess.Read))
{
var renamedFile = connection.FileManager.CheckinFile(
new FileIteration(connection, file),
"renaming to new name",
false,
DateTime.Now,
null,
null,
false,
newName,
Autodesk.Connectivity.WebServices.FileClassification.DesignDocument,
false,
stream
);
}
}
catch (Exception ex)
{
MessageBox.Show($"❌ Rename via upload failed for '{file.Name}': {ex.Message}", "Rename Error");
}
}
===============================================================
public static bool RebuildAssemblyFromVaultStructure(
Connection connection,
VaultFile renamedParentFile,
Dictionary<string, string> renameMap,
out string message)
{
message = string.Empty;
if (connection == null) { message = "❌ Null Vault connection."; return false; }
if (renamedParentFile == null) { message = "❌ Null parent file."; return false; }
if (renameMap == null || renameMap.Count == 0) { message = "❌ Empty rename map."; return false; }
Application invApp = null;
bool createdNewInstance = false;
try
{
// ---- Resolve latest WS File for the parent (the rename changed Name but ID stayed) ----
var ws = connection.WebServiceManager;
var parentLatest = ws.DocumentService.GetFileById(renamedParentFile.Id);
if (parentLatest == null)
{
message = $"❌ Could not resolve parent by Id: {renamedParentFile.Id}";
return false;
}
// ---- Acquire locally: CHECKOUT parent (we will Save), DOWNLOAD children ----
// Parent checkout
var parentIter = new FileIteration(connection, parentLatest);
var acqParent = new AcquireFilesSettings(connection)
{
DefaultAcquisitionOption = AcquireFilesSettings.AcquisitionOption.Checkout
};
acqParent.AddFileToAcquire(parentIter, AcquireFilesSettings.AcquisitionOption.Checkout);
connection.FileManager.AcquireFiles(acqParent);
// Gather children (latest) to compute their local paths and ensure they’re present
var childLatest = GetLatestChildFiles(connection, parentLatest);
if (childLatest.Count > 0)
{
var acqChildren = new AcquireFilesSettings(connection)
{
DefaultAcquisitionOption = AcquireFilesSettings.AcquisitionOption.Checkout
};
foreach (var f in childLatest.Values)
acqChildren.AddFileToAcquire(new FileIteration(connection, f),
AcquireFilesSettings.AcquisitionOption.Checkout);
connection.FileManager.AcquireFiles(acqChildren);
}
// Resolve parent local path using StatusResolution
var parentLocalPath = connection.WorkingFoldersManager.GetPathOfFileInWorkingFolder(parentIter).ToString();
if (string.IsNullOrWhiteSpace(parentLocalPath) || !System.IO.File.Exists(parentLocalPath))
{
message = $"❌ Local assembly path not found after acquire: {parentLocalPath}";
return false;
}
// Build NEW name -> local path lookup for renamed children
var newNameToLocalPath = BuildNewLocalPathLookup(connection, childLatest);
// ---- Attach or start Inventor headless ----
invApp = AttachOrStartInventor(out createdNewInstance);
invApp.SilentOperation = true;
// ---- Open assembly and replace references via descriptors ----
var asmDoc = (AssemblyDocument)invApp.Documents.Open(parentLocalPath, false);
int replaced = 0;
foreach (DocumentDescriptor dd in asmDoc.ReferencedDocumentDescriptors)
{
var oldLeaf = System.IO.Path.GetFileName(dd.FullDocumentName);
if (oldLeaf == null) continue;
if (renameMap.TryGetValue(oldLeaf, out var newLeaf))
{
if (newNameToLocalPath.TryGetValue(newLeaf, out var newFull) && System.IO.File.Exists(newFull))
{
dd.ReferencedFileDescriptor.ReplaceReference(newFull);// ✅ preserves constraints/placement
replaced++;
}
}
}
// Update & Save
asmDoc.Update();
if (!System.IO.File.GetAttributes(parentLocalPath).HasFlag(FileAttributes.ReadOnly))
{
asmDoc.Save();
}
else
{
message += "\n❌ File is read-only. Cannot save.";
return false;
}
asmDoc.Close(true);
// ---- Check-in parent WITHOUT explicit associations (let server extract refs) ----
connection.FileManager.CheckinFile(
parentIter,
"Updated assembly after rename",
false, // keepCheckedOut
DateTime.Now,
null, // file associations
null, // file link settings
false, // allow library update
null, // file classification
Autodesk.Connectivity.WebServices.FileClassification.DesignDocument,
false, // is content source
null // content source info
);
message = $"✅ Assembly updated and checked in.\nReplaced references: {replaced}\n{parentLocalPath}";
return true;
}
catch (Exception ex)
{
message = $"❌ Error rebuilding assembly: {ex.Message}";
return false;
}
finally
{
if (createdNewInstance && invApp != null)
{
try { invApp.Quit(); } catch { /* ignore */ }
Marshal.ReleaseComObject(invApp);
invApp = null;
GC.Collect(); GC.WaitForPendingFinalizers();
}
}
}