AcquireFiles method download old version of file

AcquireFiles method download old version of file

ppauleSHGR6
Enthusiast Enthusiast
817 Views
5 Replies
Message 1 of 6

AcquireFiles method download old version of file

ppauleSHGR6
Enthusiast
Enthusiast

Hi everyone,

 

I'm facing the issue that the "IFileManager.AcquireFiles" method download an old version of the file.

I don't see any mistake in my source code but maybe I'm wrong.

 

If I open the file via double click from Vault Client, I get the current version.

If I use my download method it downloads an older version to the local directory.

 

This is my source code to download a single file (mainly idw, ipt or iam).

As parameter I'm passing the "ACW.File" object that I want to download, e.g. a idw file version 20. But what I get into the local directory is e.g. file version 15.

 

internal FileAcquisitionResult DownloadFileSingle(Connection connection, ACW.File file, string folderPath)
{
	AcquireFilesSettings acquireSettings = new AcquireFilesSettings(connection);
	acquireSettings.LocalPath = new FolderPathAbsolute(folderPath);
	acquireSettings.OptionsResolution.OverwriteOption = AcquireFilesSettings.AcquireFileResolutionOptions.OverwriteOptions.ForceOverwriteAll;
	acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.VersionGatheringOption = VDF.Vault.Currency.VersionGatheringOption.Latest;
	acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.RecurseChildren = true;
	acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.IncludeChildren = true;
	acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.IncludeLibraryContents = true;
	acquireSettings.OrganizeFilesRelativeToCommonVaultRoot = true;

	FileIteration fileIter = new FileIteration(connection, file);
	acquireSettings.AddFileToAcquire(fileIter, AcquireFilesSettings.AcquisitionOption.Download);

	AcquireFilesResults downloadedFiles = connection.FileManager.AcquireFiles(acquireSettings);
	FileAcquisitionResult downloadedFile = downloadedFiles.FileResults.FirstOrDefault(x => x.File.EntityName == file.Name && x.File.VersionNumber == file.VerNum);

	return downloadedFile;
}

 I tried a little with the "AcquireFilesSettings", but these options don't seem to help.

 

What I already found out:

If I go into the Vault client an right click the idw file and execute the "Retrieve" function from the context menu, the next download via my implemented method downloads the correct version.

 

Any help is very much appreciated.

Thank you.

0 Likes
Accepted solutions (2)
818 Views
5 Replies
Replies (5)
Message 2 of 6

ppauleSHGR6
Enthusiast
Enthusiast

Hi everyone,

 

for clarification I added a screencast of this behaviour.

 

The steps I did (that you can't see on the screencast are 1 & 2):

1. Creation of a new model with drawing on another PC

2. Check-in into Vault from this PC

3. Now I go into Vault on my PC and see the drawing

And as you can see I can even see in the history that there is something displayed on this drawing

4. Now I download this file via the method I showed in my first post (I implemented it to the conext menu for testing purposes plus I made sure that the local folder/file didn't already exist before downloading it)

5. I open the downloaded file in Inventor and as you can see it's just an empty drawing

 

Why does this function not download the latest checked-in state of the file but instead any "random" old version of it?

0 Likes
Message 3 of 6

Markus.Koechl
Autodesk
Autodesk

Your code and video don't clearly explain how you get the file iteration. The selection in the main view returns the master ID of your file. Use GetLatestFileByMasterId() to get the latest file iteration (version). Line 6 in your posted code affects the relationship gathering only, not the parent file.
Your video lists only a single available version. Does this drawing have more than one sheet (unfortunately, the browser is cut off)?
Do you also download and activate the Inventor project file (IPJ) to the temp folder?



Markus Koechl

Solutions Engineer PDM, Autodesk Central Europe
0 Likes
Message 4 of 6

ppauleSHGR6
Enthusiast
Enthusiast

I made sure that the "ACW.File" object instance is the right version that I want to download.

The code I posted is simplified but shows the general logic and it's running with logging on production systems where we now face this issue.

In debugging and log files I can confirm that the file iteration is the latest which is selected in the main view.

And yes - I'm using the "GetLatestFileByMasterId()" method to get the file iteration.

There are no more sheets in the drawing, I created the most basic drawing and the most basic part (ipt: one sketch, one extrusion. Drawing was created from the model in Inventor by clicking "Create drawing view" in the context menu via right click on the model).

Yes, at time when I captured the video there was only one version of the drawing checked in, that's why it was even more strange that the file that was downloaded was just an empty drawing - where does Vault (API) take it from?

 

Thank you for clarifying line 6 of my code.

 

Here's the rest of my code, again in a shortened, simplified version:

private ACW.File[] GetSelectedFiles(ICommandContext context)
{
	List<ACW.File> files = new List<ACW.File>();
	
	foreach (ISelection selection in context.CurrentSelectionSet)
		files.Add(m_serviceManager.DocumentService.GetLatestFileByMasterId(selection.Id));
	
	return files.ToArray();
}

private void cmdDownloadFile_Execute(object sender, CommandItemEventArgs e)
{
	string downloadPath = "C:\\temp\\VaultDownloads";
	List<string> downloadedFiles = new List<string>();

	ACW.File[] selFiles = GetSelectedFiles(e.Context);
	
	foreach (ACW.File file in selFiles)
	{
		string downloadFileName = Path.Combine(downloadPath, file.Name);
		DownloadFileSingle(e.Context.Application.Connection, file, downloadFileName);

		downloadedFiles.Add(downloadFileName);
	}

	MessageBox.Show($"Files downloaded:{Environment.NewLine}{string.Join(Environment.NewLine, downloadedFiles)}");
}

 

Do you also download and activate the Inventor project file (IPJ) to the temp folder?

No, I don't. I didn't think of that yet. This should be done? If yes, is there a "simple" way of doing so via the Vault API?

 

Thank you for your assistance.

0 Likes
Message 5 of 6

Markus.Koechl
Autodesk
Autodesk
Accepted solution

Vault API and Vault Client leverage the vaulted IPJ file. So, the download itself does not require a downloaded or activated project file. But your Inventor session must have a valid project file using your temp\folder name as the Inventor working folder. Again - I cannot see the model/drawing browser in the video. Does the browser list the view, referencing the downloaded part?

Another hint for production environments: if the Vault environment has multiple sites, always enforce the replication before downloading a file. You can review the sample code here how to do.



Markus Koechl

Solutions Engineer PDM, Autodesk Central Europe
0 Likes
Message 6 of 6

ppauleSHGR6
Enthusiast
Enthusiast
Accepted solution

Thanks for your reply.

 

Does the browser list the view, referencing the downloaded part?

I think that and the hint about the IPJ file (which was not referring to the temp folder) was the hint and the actual issue.

Unfortunately I wasn't able to reproduce it again since my first try when I recorded the screen capture.

If I will be able to reproduce the issue again, I will pay attention to that and update this thread.

 

Now I've set my goal to download the main file including all child references to the local Vault working folder and that seems to work as expected so far. I will not pass the temp folder anymore to my download method and force the "IFileManager.AcquireFiles()" method to download to the Vault working folder.

As I said, this way I wasn't able to reproduce the issue again.

 

This is my solution so far and maybe it will help others who will face the same issue in future:

 

internal FileAcquisitionResult DownloadFileSingle(Connection connection, ACW.File file, string folderPath)
{
	FileAcquisitionResult downloadedFile = null;
	try
	{
		SettingsHandler.log.Debug($"Directory={folderPath}");
		
		if (string.IsNullOrWhiteSpace(folderPath))
		{
			// If no folder is passed, files will be downloaded to local Vault working folder
			string vaultWorkingFolder = connection.WebServiceManager.DocumentService.GetRequiredWorkingFolderLocation();
			if (vaultWorkingFolder.Contains("%"))
				vaultWorkingFolder = ReplaceWindowsEnvironmentVariables(vaultWorkingFolder);
			
			SettingsHandler.log.Debug($"No directory passed -> Files will be downloaded to local Vault working folder: {vaultWorkingFolder}");
		}

		// Delete file before, if it already exists
		string localFileName = null;
		if (!string.IsNullOrWhiteSpace(folderPath))
			localFileName = Path.Combine(folderPath, file.Name);
		else
		{
			localFileName = GetLocalFileName(connection, file);
			if (localFileName.Contains("%"))
				localFileName = ReplaceWindowsEnvironmentVariables(localFileName);
		}

		FileInfo fiExisting = new FileInfo(localFileName);
		if (fiExisting.Exists)
		{
			SettingsHandler.log.Debug($"File already existing in target folder. File will be deleted before it will be downloaded from Vault... (FileName={fiExisting.FullName})");

			fiExisting.IsReadOnly = false;
			fiExisting.Delete();

			SettingsHandler.log.Debug($"File deleted: {fiExisting.FullName}");
		}

		AcquireFilesSettings acquireSettings = new AcquireFilesSettings(connection);
		if (!string.IsNullOrWhiteSpace(folderPath))
			acquireSettings.LocalPath = new FolderPathAbsolute(folderPath);
		else
			acquireSettings.LocalPath = null; // download to working folder
		acquireSettings.OptionsResolution.OverwriteOption = AcquireFilesSettings.AcquireFileResolutionOptions.OverwriteOptions.ForceOverwriteAll;
		acquireSettings.OptionsResolution.SyncWithRemoteSiteSetting = AcquireFilesSettings.SyncWithRemoteSite.Always;
		acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.VersionGatheringOption = VDF.Vault.Currency.VersionGatheringOption.Latest; // Get latest versions of file references
		acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.RecurseChildren = true; // Get children of children
		acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.IncludeChildren = true; // Get children files
		acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.IncludeParents = false; // Do not get the parents of the file to process
		acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.ReleaseBiased = false; // Get the latest version, not the latest released)
		acquireSettings.OptionsRelationshipGathering.FileRelationshipSettings.IncludeLibraryContents = true; // Include library files
		acquireSettings.OrganizeFilesRelativeToCommonVaultRoot = true; // Make sure to find all file references in expected folder

		FileIteration fileIter = new FileIteration(connection, file);
		acquireSettings.AddFileToAcquire(fileIter, AcquireFilesSettings.AcquisitionOption.Download);

		AcquireFilesResults downloadedFiles = connection.FileManager.AcquireFiles(acquireSettings);

		SettingsHandler.log.Debug($"FileResults.Count={downloadedFiles.FileResults?.Count()}");

		if (downloadedFiles == null || downloadedFiles.FileResults == null || downloadedFiles.FileResults.Count() == 0)
			throw new Exception($"Unexpected error downloading file to local directory (FileId={fileIter.EntityIterationId}, FileName={fileIter.EntityName}, FileVersion={fileIter.VersionNumber}, Directory={folderPath})");
		if (downloadedFiles.FileResults.Any(x => x.Exception != null))
			throw downloadedFiles.FileResults.First(x => x.Exception != null).Exception;

		foreach (FileAcquisitionResult acquisitionResult in downloadedFiles.FileResults)
			SettingsHandler.log.Debug($"{acquisitionResult.File.EntityName} -> {acquisitionResult.Status} (FullFileName={acquisitionResult.LocalPath}, NewFileIteration={acquisitionResult.NewFileIteration != null})");

		downloadedFile = downloadedFiles.FileResults.FirstOrDefault(x => x.File.EntityName == file.Name && x.File.VersionNumber == file.VerNum);

		if (downloadedFile != null)
		{
			foreach (FileAcquisitionResult fileAcquisitionResult in downloadedFiles.FileResults)
			{
				localFileName = fileAcquisitionResult.LocalPath.FullPath;
				if (localFileName.Contains("%"))
					localFileName = ReplaceWindowsEnvironmentVariables(localFileName);

				m_downloadedFiles.Add(localFileName); // All files in this list will get deleted
			}

			if (!string.IsNullOrWhiteSpace(folderPath))
				m_downloadPaths.Add(folderPath); // Folder will be deleted if it's not the Vault working folder
		}

		if (downloadedFiles.FileResults?.Count() > 1)
			SettingsHandler.log.Debug($"File downloaded successfully with all {downloadedFiles.FileResults?.Count() - 1} references (FullFileName={downloadedFile?.LocalPath.FullPath})");
		else
			SettingsHandler.log.Debug($"File downloaded successfully (FullFileName={downloadedFile?.LocalPath.FullPath})");
	}
	catch (Exception ex)
	{
		SettingsHandler.log.Error(ex);
	}
	return downloadedFile;
}

internal string GetLocalFileName(Connection vaultConn, ACW.File file)
{
	string vaultWorkingFolder = vaultConn.WebServiceManager.DocumentService.GetRequiredWorkingFolderLocation();
	ACW.Folder folder = vaultConn.WebServiceManager.DocumentService.GetFolderById(file.FolderId);
	string fileNameLocal = null;
	if (vaultWorkingFolder.EndsWith("\\"))
		fileNameLocal = Path.Combine(folder.FullName.Replace("/", "\\").Replace("$\\", vaultWorkingFolder), file.Name);
	else
		fileNameLocal = Path.Combine(folder.FullName.Replace("/", "\\").Replace("$", vaultWorkingFolder), file.Name);
	return fileNameLocal;
}

internal string ReplaceWindowsEnvironmentVariables(string fullFileName)
{
	// Regular expression to match any %<variable>% pattern
	string pattern = @"%([^%]+)%";

	// Use a MatchEvaluator to replace variables dynamically
	string updatedPath = Regex.Replace(fullFileName, pattern, match =>
	{
		// Extract the environment variable name from the match
		string variableName = match.Groups[1].Value;

		// Get the value of the environment variable
		string variableValue = Environment.GetEnvironmentVariable(variableName);
		if (variableValue == null)
			variableValue = Environment.GetEnvironmentVariable(variableName, EnvironmentVariableTarget.User);
		if (variableValue == null)
			variableValue = Environment.GetEnvironmentVariable(variableName, EnvironmentVariableTarget.Machine);

		// If the variable is not found, return the original match (keep placeholder)
		return string.IsNullOrEmpty(variableValue) ? match.Value : variableValue;
	});

	return updatedPath.Replace("\\\\", "\\");
}

 

0 Likes