/*****************************************************************************************/ public static List <AWS.FileAssocParam> UpdateFileAssociations(VDF.Vault.Currency.Connections.Connection connection, VDF.Vault.Currency.Entities.FileIteration fileIterationParent, List <AWS.FileAssocLite> fileAssocsLite) { List <AWS.FileAssocParam> fileAssocParams = new List <AWS.FileAssocParam>(); foreach (AWS.FileAssocLite fileAssocLite in fileAssocsLite) { AWS.File childAsReferenced = connection.WebServiceManager.DocumentService.GetFileById(fileAssocLite.CldFileId); // of any reason, the parent is referenced by it self in the list, but we dont want that if (fileIterationParent.EntityMasterId == childAsReferenced.MasterId) { continue; } AWS.File childLatest = connection.WebServiceManager.DocumentService.GetLatestFileByMasterId(childAsReferenced.MasterId); AWS.FileAssocParam fileAssocParam = new AWS.FileAssocParam(); fileAssocParam.CldFileId = childLatest.Id; fileAssocParam.RefId = fileAssocLite.RefId; fileAssocParam.Source = fileAssocLite.Source; fileAssocParam.Typ = fileAssocLite.Typ; fileAssocParam.ExpectedVaultPath = fileAssocLite.ExpectedVaultPath; fileAssocParams.Add(fileAssocParam); } return(fileAssocParams); }
public JobOutcome Execute(IJobProcessorServices context, IJob job) { try { Inventor.InventorServer mInv = context.InventorObject as InventorServer; #region validate execution rules //pick up this job's context mConnection = context.Connection; Autodesk.Connectivity.WebServicesTools.WebServiceManager mWsMgr = mConnection.WebServiceManager; long mEntId = Convert.ToInt64(job.Params["EntityId"]); string mEntClsId = job.Params["EntityClassId"]; // only run the job for files; handle the scenario, that an item lifecycle transition accidently submitted the job if (mEntClsId != "FILE") { context.Log(null, "This job type is for files only."); return(JobOutcome.Failure); } // only run the job for ipt and iam file types, List <string> mFileExtensions = new List <string> { ".ipt", ".iam", "idw", "dwg" }; ACW.File mFile = mWsMgr.DocumentService.GetFileById(mEntId); if (!mFileExtensions.Any(n => mFile.Name.EndsWith(n))) { context.Log(null, "Skipped Job execution as file type did not match iLogic enabled files (ipt, iam, idw/dwg"); return(JobOutcome.Success); } //run iLogic for Inventor DWG file types/skip AutoCAD DWG files ACW.PropDef[] mPropDefs = mWsMgr.PropertyService.GetPropertyDefinitionsByEntityClassId("FILE"); ACW.PropDef mPropDef = null; ACW.PropInst mPropInst = null; if (mFile.Name.EndsWith(".dwg")) { mPropDef = mPropDefs.Where(n => n.SysName == "Provider").FirstOrDefault(); mPropInst = (mWsMgr.PropertyService.GetPropertiesByEntityIds("FILE", new long[] { mFile.Id })).Where(n => n.PropDefId == mPropDef.Id).FirstOrDefault(); if (mPropInst.Val.ToString() != "Inventor DWG") { context.Log(null, "Skipped Job execution as DWG type did not match Inventor DWG"); return(JobOutcome.Success); } } ApplicationAddIns mInvSrvAddIns = mInv.ApplicationAddIns; ApplicationAddIn iLogicAddIn = mInvSrvAddIns.ItemById["{3BDD8D79-2179-4B11-8A5A-257B1C0263AC}"]; if (iLogicAddIn != null && iLogicAddIn.Activated != true) { iLogicAddIn.Activate(); } dynamic mAutomation = iLogicAddIn.Automation; if (mAutomation == null) { Trace.WriteLine("iLogic-AddIn automation is not available; exiting job processing"); context.Log(null, "iLogic-AddIn automation is not available"); return(JobOutcome.Failure); } #endregion validate execution rules #region VaultInventorServer IPJ activation //override InventorServer default project settings by your Vault specific ones Inventor.DesignProjectManager mInvIpjManager; Inventor.DesignProject mInvDfltProject, mInvVltProject; String mIpjPath = ""; String mWfPath = ""; String mIpjLocalPath = ""; ACW.File mIpj; VDF.Vault.Currency.Entities.FileIteration mIpjFileIter = null; //validate ipj setting, a single, enforced ipj is expected if (mWsMgr.DocumentService.GetEnforceWorkingFolder() && mWsMgr.DocumentService.GetEnforceInventorProjectFile()) { mIpjPath = mWsMgr.DocumentService.GetInventorProjectFileLocation(); mWfPath = mWsMgr.DocumentService.GetRequiredWorkingFolderLocation(); //Set mWfPath to alternate temporary working folder if needed, e.g. to delete all files after job execution } else { context.Log(null, "Job requires both settings enabled: 'Enforce Workingfolder' and 'Enforce Inventor Project'."); return(JobOutcome.Failure); } //download and activate the Inventor Project file in VaultInventorServer mIpj = (mWsMgr.DocumentService.FindLatestFilesByPaths(new string[] { mIpjPath })).FirstOrDefault(); try { String[] mIpjFullFileName = mIpjPath.Split(new string[] { "/" }, StringSplitOptions.None); String mIpjFileName = mIpjFullFileName.LastOrDefault(); //define download settings for the project file VDF.Vault.Settings.AcquireFilesSettings mAcqrIpjSettings = new VDF.Vault.Settings.AcquireFilesSettings(mConnection); mAcqrIpjSettings.LocalPath = new VDF.Currency.FolderPathAbsolute(mWfPath); mIpjFileIter = new VDF.Vault.Currency.Entities.FileIteration(mConnection, mIpj); mAcqrIpjSettings.AddFileToAcquire(mIpjFileIter, VDF.Vault.Settings.AcquireFilesSettings.AcquisitionOption.Download); //download project file and get local path VDF.Vault.Results.AcquireFilesResults mDownLoadResult; VDF.Vault.Results.FileAcquisitionResult fileAcquisitionResult; mDownLoadResult = mConnection.FileManager.AcquireFiles(mAcqrIpjSettings); fileAcquisitionResult = mDownLoadResult.FileResults.FirstOrDefault(); mIpjLocalPath = fileAcquisitionResult.LocalPath.FullPath; //activate this Vault's ipj mInvIpjManager = mInv.DesignProjectManager; mInvDfltProject = mInvIpjManager.ActiveDesignProject; mInvVltProject = mInvIpjManager.DesignProjects.AddExisting(mIpjLocalPath); mInvVltProject.Activate(); //[Optionally:] get Inventor Design Data settings and download all related files --------- } catch { context.Log(null, "Job was not able to activate Inventor project file. - Note: The ipj must not be checked out by another user."); return(JobOutcome.Failure); } #endregion VaultInventorServer IPJ activation #region download source file(s) //build download options including DefaultAcquisitionOptions VDF.Vault.Currency.Entities.FileIteration mFileIteration = new VDF.Vault.Currency.Entities.FileIteration(mConnection, mFile); VDF.Vault.Currency.Entities.FileIteration mNewFileIteration = null; VDF.Vault.Settings.AcquireFilesSettings mAcqrFlsSettings; VDF.Vault.Results.AcquireFilesResults mAcqrFlsResults2; VDF.Vault.Results.FileAcquisitionResult mFileAcqsResult2; string mLocalFileFullName = "", mExt = ""; if (mFileIteration.IsCheckedOut == true && mFileIteration.IsCheckedOutToCurrentUser == false) { //exit the job, as the job user is not able to edit the file reserved to another user mInvDfltProject.Activate(); context.Log(null, "Job stopped execution as the source file to process is checked-out by another user."); return(JobOutcome.Failure); } //download only if (mFileIteration.IsCheckedOut == true && mFileIteration.IsCheckedOutToCurrentUser == true) { mAcqrFlsSettings = CreateAcquireSettings(false); mAcqrFlsSettings.AddFileToAcquire(mFileIteration, mAcqrFlsSettings.DefaultAcquisitionOption); mAcqrFlsResults2 = this.mConnection.FileManager.AcquireFiles(mAcqrFlsSettings); mNewFileIteration = mFileIteration; mFileAcqsResult2 = mAcqrFlsResults2.FileResults.Where(n => n.File.EntityName == mFileIteration.EntityName).FirstOrDefault(); mLocalFileFullName = mFileAcqsResult2.LocalPath.FullPath; mExt = System.IO.Path.GetExtension(mLocalFileFullName); } //checkout and download if (mFileIteration.IsCheckedOut == false) { try { mAcqrFlsSettings = CreateAcquireSettings(true); //checkout (don't checkout related children) mAcqrFlsSettings.AddFileToAcquire(mFileIteration, mAcqrFlsSettings.DefaultAcquisitionOption); mAcqrFlsResults2 = this.mConnection.FileManager.AcquireFiles(mAcqrFlsSettings); mFileAcqsResult2 = mAcqrFlsResults2.FileResults.Where(n => n.File.EntityName == mFileIteration.EntityName).FirstOrDefault(); mNewFileIteration = mFileAcqsResult2.NewFileIteration; mAcqrFlsSettings = null; mAcqrFlsSettings = CreateAcquireSettings(false);//download (include related children) mAcqrFlsSettings.AddFileToAcquire(mNewFileIteration, mAcqrFlsSettings.DefaultAcquisitionOption); mAcqrFlsResults2 = this.mConnection.FileManager.AcquireFiles(mAcqrFlsSettings); mLocalFileFullName = mFileAcqsResult2.LocalPath.FullPath; mExt = System.IO.Path.GetExtension(mLocalFileFullName); } catch (Exception) { mInvDfltProject.Activate(); context.Log(null, "Job stopped execution as the source file to process did not download or check-out."); return(JobOutcome.Failure); } } #endregion download source file(s) #region capture dependencies //we need to return all relationships during later check-in List <ACW.FileAssocParam> mFileAssocParams = new List <ACW.FileAssocParam>(); ACW.FileAssocArray mFileAssocArray = mWsMgr.DocumentService.GetLatestFileAssociationsByMasterIds(new long[] { mFile.MasterId }, ACW.FileAssociationTypeEnum.None, false, ACW.FileAssociationTypeEnum.All, false, false, false, true).FirstOrDefault(); if (mFileAssocArray.FileAssocs != null) { foreach (ACW.FileAssoc item in mFileAssocArray.FileAssocs) { ACW.FileAssocParam mFileAssocParam = new ACW.FileAssocParam(); mFileAssocParam.CldFileId = item.CldFile.Id; mFileAssocParam.ExpectedVaultPath = item.ExpectedVaultPath; mFileAssocParam.RefId = item.RefId; mFileAssocParam.Source = item.Source; mFileAssocParam.Typ = item.Typ; mFileAssocParams.Add(mFileAssocParam); } } #endregion capture dependencies #region iLogic Configuration //avoid unplanned rule execution triggered by the document itself mAutomation.RulesOnEventsEnabled = false; mAutomation.RulesEnabled = false; //set the iLogic Advanced Configuration Settings dynamic mFileOptions = mAutomation.FileOptions; mFileOptions.AddinDirectory = mSettings.iLogicAddinDLLs; //add the job extension app path and configured external rule directories to the FileOptions.ExternalRuleDirectories for iLogic List <string> mExtRuleDirs = new List <string>(); mExtRuleDirs.Add(mAppPath); mExtRuleDirs.AddRange(mSettings.ExternalRuleDirectories.Split(',').ToList <string>()); mFileOptions.ExternalRuleDirectories = mExtRuleDirs.ToArray(); //enable iLogic logging dynamic mLogCtrl = mAutomation.LogControl; switch (mSettings.iLogicLogLevel) { case "None": mLogCtrl.Level = 0; break; case "Trace": mLogCtrl.Level = 1; break; case "Debug": mLogCtrl.Level = 2; break; case "Info": mLogCtrl.Level = 3; break; case "Warn": mLogCtrl.Level = 4; break; case "Error": mLogCtrl.Level = 5; break; case "Fatal": mLogCtrl.Level = 6; break; default: mLogCtrl.Level = 5; break; } //enable iLogic to save a log file for each job Id. string mILogicLogFileFullName = ""; if (mLogCtrl.Level != 0) { string mLogName = job.Id + "_" + mFile.Name + "_iLogicSampleJob.log"; System.IO.DirectoryInfo mLogDirInfo = new System.IO.DirectoryInfo(mSettings.iLogicLogDir); if (mLogDirInfo.Exists == false) { mLogDirInfo = System.IO.Directory.CreateDirectory(mSettings.iLogicLogDir); } mILogicLogFileFullName = System.IO.Path.Combine(mLogDirInfo.FullName, mLogName); } //read rule execution settings string mVaultRule = mSettings.VaultRuleFullFileName; string mExtRule = mSettings.ExternalRuleName; string mExtRuleFullName = null; string mIntRulesOption = mSettings.InternalRulesOption; if (mVaultRule != "") { ACW.File mRuleFile = mWsMgr.DocumentService.FindLatestFilesByPaths(new string[] { mVaultRule }).FirstOrDefault(); //build download options including DefaultAcquisitionOptions VDF.Vault.Currency.Entities.FileIteration mRuleFileIter = new VDF.Vault.Currency.Entities.FileIteration(mConnection, mRuleFile); VDF.Vault.Settings.AcquireFilesSettings mAcqrRuleSettings = CreateAcquireSettings(false); mAcqrRuleSettings.AddFileToAcquire(mRuleFileIter, mAcqrRuleSettings.DefaultAcquisitionOption); //download VDF.Vault.Results.AcquireFilesResults mAcqrRuleResults = this.mConnection.FileManager.AcquireFiles(mAcqrRuleSettings); //pick-up the new file iteration in case of check-out VDF.Vault.Results.FileAcquisitionResult mRuleAcqResult = mAcqrRuleResults.FileResults.Where(n => n.File.EntityName == mRuleFileIter.EntityName).FirstOrDefault(); if (mRuleAcqResult.LocalPath != null) { mExtRuleFullName = mRuleAcqResult.LocalPath.FullPath; System.IO.FileInfo fileInfo = new System.IO.FileInfo(mExtRuleFullName); if (fileInfo.Exists == false) { context.Log(null, "Job downloaded rule file but exited due to missing rule file: " + mExtRuleFullName + "."); mConnection.FileManager.UndoCheckoutFile(mNewFileIteration); return(JobOutcome.Failure); } else { mExtRule = fileInfo.Name; if (!mExtRuleDirs.Any(n => fileInfo.DirectoryName.Equals(n))) { context.Log(null, "Job downloaded rule file but exited due to missing iLogic External Rule Directory configuration: Add the path" + fileInfo.DirectoryName + " to the list of External Rule Directories."); mConnection.FileManager.UndoCheckoutFile(mNewFileIteration); return(JobOutcome.Failure); } } } else { context.Log(null, "Job could not download configured rule file and exited. Compare the 'VaultRuleFullFileName' setting and available rule in Vault."); return(JobOutcome.Failure); } } #endregion iLogic Configuration #region Run iLogic Rule(s) //Open Inventor Document Document mDoc = mInv.Documents.Open(mLocalFileFullName); //use case - apply external rule with arguments; additional Vault UDP, status or any information might fill rule arguments if (mExtRule != "") { //required rule arguments to continue Vault interaction within the rule (iLogic-Vault library) NameValueMap ruleArguments = mInv.TransientObjects.CreateNameValueMap(); ruleArguments.Add("ServerName", mConnection.Server); ruleArguments.Add("VaultName", mConnection.Vault); ruleArguments.Add("UserId", mConnection.UserID); ruleArguments.Add("Ticket", mConnection.Ticket); //additional rule arguments to build rule conditions evaluating Vault lifecycle information, properties, etc. if (mSettings.PropagateProps == "True") { ACW.PropInst[] mSourcePropInsts = mWsMgr.PropertyService.GetPropertiesByEntityIds("FILE", new long[] { mFileIteration.EntityIterationId }); string mPropDispName; string mThumbnailDispName = mPropDefs.Where(n => n.SysName == "Thumbnail").FirstOrDefault().DispName; foreach (ACW.PropInst item in mSourcePropInsts) { mPropDispName = mPropDefs.Where(n => n.Id == item.PropDefId).FirstOrDefault().DispName; //filter thumbnail property, as iLogic RuleArguments will fail reading it. if (mPropDispName != mThumbnailDispName) { ruleArguments.Add(mPropDispName, item.Val); } } } //call external rule with arguments; return value = 0 in case of successful execution mRuleSuccess = mAutomation.RunExternalRuleWithArguments(mDoc, mExtRule, ruleArguments); if (mRuleSuccess != 0) { context.Log(null, "Job failed due to failure in external rule: " + mExtRule + "."); mDoc.Close(true); mConnection.FileManager.UndoCheckoutFile(mNewFileIteration); mLogCtrl.SaveLogAs(mILogicLogFileFullName); return(JobOutcome.Failure); } else { mAllRulesTextWrp = "External Rule: " + mExtRule; } mDoc.Save2(false); } //use case - run all, all active or filtered document rules dynamic mDocRules = mAutomation.Rules(mDoc); List <dynamic> mRulesToExec = new List <dynamic>(); switch (mSettings.InternalRulesOption) { case "None": break; case "Active": if (mDocRules != null) { foreach (dynamic rule in mDocRules) { if (rule.IsActive == true) { mRulesToExec.Add(rule); } } } break; case "All": if (mDocRules != null) { foreach (dynamic rule in mDocRules) { mRulesToExec.Add(rule); } } break; default: foreach (dynamic rule in mDocRules) { if (rule.Name.Contains(mSettings.InternalRulesOption)) { mRulesToExec.Add(rule); } } break; } if (mRulesToExec.Count >= 1) { foreach (dynamic rule in mRulesToExec) { mRuleSuccess = mAutomation.RunRule(mDoc, rule.Name); if (mRuleSuccess != 0) { context.Log(null, "Job failed due to failure in internal rule: " + rule.Name + "."); mDoc.Close(true); mConnection.FileManager.UndoCheckoutFile(mNewFileIteration); mLogCtrl.SaveLogAs(mILogicLogFileFullName); return(JobOutcome.Failure); } else { mAllRules.Add(rule.Name); } } } mDoc.Save2(false); mDoc.Close(true); mLogCtrl.SaveLogAs(mILogicLogFileFullName); if (mAllRules.Count > 0) { mAllRulesTextWrp += "\n\r Internal Rule(s):"; foreach (string name in mAllRules) { mAllRulesTextWrp += "\r\n " + name; } } #endregion Run iLogic Rules #region Check-in result // checkin new file version VDF.Currency.FilePathAbsolute vdfPath = new VDF.Currency.FilePathAbsolute(mLocalFileFullName); FileIteration mUploadedFile = null; try { if (mFileAssocParams.Count > 0) { mUploadedFile = mConnection.FileManager.CheckinFile(mNewFileIteration, "Created by Custom Job executing iLogic : " + mAllRulesTextWrp, false, mFileAssocParams.ToArray(), null, true, null, mFileIteration.FileClassification, false, vdfPath); } else { mUploadedFile = mConnection.FileManager.CheckinFile(mNewFileIteration, "Created by Custom Job executing iLogic : " + mAllRulesTextWrp, false, null, null, false, null, mFileIteration.FileClassification, false, vdfPath); } } catch { context.Log(null, "Job could not check-in updated file: " + mUploadedFile.EntityName + "."); return(JobOutcome.Failure); } #endregion check-in result #region reset mInvDfltProject.Activate(); //delete temporary working folder if imlemented here #endregion reset return(JobOutcome.Success); } catch (Exception ex) { context.Log(ex, "Job failed by unhandled exception: " + ex.ToString() + " "); return(JobOutcome.Failure); } }
/***********************************************************************************************************/ /***************** THIS DOES NOT CURRENTLY WORK BUT IT'S CLOSE - CONTINUE DEVELOPMENT HERE *****************/ /***********************************************************************************************************/ public static void publishDwf(VDF.Vault.Currency.Connections.Connection connection, AWS.File file, string localDirectoryPath, FileInfo actualDwfFile) { try { AWS.FilePathArray[] filePaths = connection.WebServiceManager.DocumentService.GetLatestAssociatedFilePathsByMasterIds(new long[] { file.MasterId }, AWS.FileAssociationTypeEnum.None, false, AWS.FileAssociationTypeEnum.Attachment, true, true, true, false); connection.WebServiceManager.DocumentService.SetTurnOffWarningForUserGeneratedDesignVisualization(true); VDF.Vault.Currency.Entities.Folder admcFolder = new VDF.Vault.Currency.Entities.Folder(connection, connection.WebServiceManager.DocumentService.GetFolderById(file.FolderId)); Option <AWS.File> existingDWF = FileOperations.GetFile(connection, admcFolder.FullName + "/" + actualDwfFile.Name); if (existingDWF.IsSome) { List <AWS.FileAssocLite> oldAssociations = new List <Autodesk.Connectivity.WebServices.FileAssocLite>(); AWS.FileAssocArray[] fass = connection.WebServiceManager.DocumentService.GetDesignVisualizationAttachmentsByFileMasterIds(new long[] { file.MasterId }); //if (fass.Length > 0) // return; Option <VDF.Vault.Results.AcquireFilesResults> result = CheckOutFile(connection, existingDWF.Get(), localDirectoryPath, oldAssociations); //string correctPath2 = result.Get().FileResults.First().LocalPath.FullPath; //actualDwfFile.CopyTo(correctPath2, true); //FileInfo newestDwfFile = new FileInfo(correctPath2); //connection.WebServiceManager.DocumentService.DeleteFileFromFolderUnconditional(existingDWF.Get().MasterId, file.FolderId); //connection.WebServiceManager.DocumentService.file VDF.Vault.Currency.Entities.FileIteration fIter = CheckInFile(connection, existingDWF.Get(), "updated dwf", oldAssociations, admcFolder.FullName + "/" + actualDwfFile.Name, actualDwfFile); /*AWS.FileAssocParam fileParam = new AWS.FileAssocParam(); * fileParam.CldFileId = existingDWF.Get().Id; * fileParam.RefId = null; * fileParam.Typ = AWS.AssociationType.Attachment; * connection.WebServiceManager.DocumentService.AddDesignVisualizationFileAttachment(file.Id, fileParam); */ //VDF.Vault.Currency.Entities.FileIteration fIter = connection.FileManager.AddFile(admcFolder, newDwfFile.Name, "added dwf", newDwfFile.LastWriteTime, null, null, AWS.FileClassification.DesignVisualization, true, stream); //actualDwfFile.CopyTo(result.Get().FileResults.First().LocalPath.FullPath, true); //CheckInFile(connection, existingDWF.Get(), "updated dwf", oldAssociations, admcFolder.FullName + "/" + existingDWF.Get().Name); //VDF.Vault.Currency.Entities.FileIteration fIter = connection.FileManager.AddFile(admcFolder, newDwfFile.Name, "added dwf", newDwfFile.LastWriteTime, null, null, AWS.FileClassification.DesignVisualization, true, stream); //AWS.BreakDesignVisualizationLinkCommandList blist = connection.WebServiceManager.DocumentService.GetBreakDesignVisualizationLinkCommandList(); //bool ya = connection.WebServiceManager.DocumentService.GetTurnOffWarningForUserGeneratedDesignVisualization(); //fass[0].FileAssocs[0].CldFile = connection.WebServiceManager.DocumentService.GetFileByVersion(fIter.EntityMasterId, fIter.VersionNumber); AWS.FileAssocParam fileParam = new AWS.FileAssocParam(); fileParam.CldFileId = fIter.EntityIterationId; fileParam.RefId = null; fileParam.Typ = AWS.AssociationType.Attachment; connection.WebServiceManager.DocumentService.AddDesignVisualizationFileAttachment(file.Id, fileParam); //CheckInFile(connection, existingDWF.Get(), "updated dwf", oldAssociations, admcFolder.FullName + "/" + newDwfFile.Name); } else { using (System.IO.FileStream stream = new FileStream(actualDwfFile.FullName, FileMode.Open)) { VDF.Vault.Currency.Entities.FileIteration fIter = connection.FileManager.AddFile(admcFolder, actualDwfFile.Name, "added dwf", actualDwfFile.LastWriteTime, null, null, AWS.FileClassification.DesignVisualization, true, stream); AWS.FileAssocParam fileParam = new AWS.FileAssocParam(); fileParam.CldFileId = fIter.EntityIterationId; fileParam.RefId = null; fileParam.Typ = AWS.AssociationType.Attachment; connection.WebServiceManager.DocumentService.AddDesignVisualizationFileAttachment(file.Id, fileParam); } } } catch { //errornstuff } //} }
private void mCreateExport(IJobProcessorServices context, IJob job) { List <string> mExpFrmts = new List <string>(); List <string> mUploadFiles = new List <string>(); // read target export formats from settings file Settings settings = Settings.Load(); #region validate execution rules mTrace.IndentLevel += 1; mTrace.WriteLine("Translator Job started..."); //pick up this job's context Connection connection = context.Connection; Autodesk.Connectivity.WebServicesTools.WebServiceManager mWsMgr = connection.WebServiceManager; long mEntId = Convert.ToInt64(job.Params["EntityId"]); string mEntClsId = job.Params["EntityClassId"]; // only run the job for files if (mEntClsId != "FILE") { return; } // only run the job for ipt and iam file types, List <string> mFileExtensions = new List <string> { ".ipt", ".iam" }; ACW.File mFile = mWsMgr.DocumentService.GetFileById(mEntId); if (!mFileExtensions.Any(n => mFile.Name.Contains(n))) { return; } // apply execution filters, e.g., exclude files of classification "substitute" etc. List <string> mFileClassific = new List <string> { "ConfigurationFactory", "DesignSubstitute" }; //add "DesignDocumentation" for 3D Exporters only if (mFileClassific.Any(n => mFile.FileClass.ToString().Contains(n))) { return; } // you may add addtional execution filters, e.g., category name == "Sheet Metal Part" if (settings.ExportFomats == null) { throw new Exception("Settings expect to list at least one export format!"); } if (settings.ExportFomats.Contains(",")) { mExpFrmts = settings.ExportFomats.Split(',').ToList(); } else { mExpFrmts.Add(settings.ExportFomats); } //remove SM formats, if source isn't sheet metal if (mFile.Cat.CatName != settings.SmCatDispName) { if (mExpFrmts.Contains("SMDXF")) { mExpFrmts.Remove("SMDXF"); } if (mExpFrmts.Contains("SMSAT")) { mExpFrmts.Remove("SMSAT"); } } mTrace.WriteLine("Job execution rules validated."); #endregion validate execution rules #region VaultInventorServer IPJ activation //establish InventorServer environment including translator addins; differentiate her in case full Inventor.exe is used Inventor.InventorServer mInv = context.InventorObject as InventorServer; ApplicationAddIns mInvSrvAddIns = mInv.ApplicationAddIns; //override InventorServer default project settings by your Vault specific ones Inventor.DesignProjectManager projectManager; Inventor.DesignProject mSaveProject, mProject; String mIpjPath = ""; String mWfPath = ""; String mIpjLocalPath = ""; ACW.File mProjFile; VDF.Vault.Currency.Entities.FileIteration mIpjFileIter = null; //download and activate the Inventor Project file in VaultInventorServer mTrace.IndentLevel += 1; mTrace.WriteLine("Job tries activating Inventor project file as enforced in Vault behavior configurations."); try { //Download enforced ipj file if (mWsMgr.DocumentService.GetEnforceWorkingFolder() && mWsMgr.DocumentService.GetEnforceInventorProjectFile()) { mIpjPath = mWsMgr.DocumentService.GetInventorProjectFileLocation(); mWfPath = mWsMgr.DocumentService.GetRequiredWorkingFolderLocation(); } else { throw new Exception("Job requires both settings enabled: 'Enforce Workingfolder' and 'Enforce Inventor Project'."); } String[] mIpjFullFileName = mIpjPath.Split(new string[] { "/" }, StringSplitOptions.None); String mIpjFileName = mIpjFullFileName.LastOrDefault(); //get the projects file object for download ACW.PropDef[] filePropDefs = mWsMgr.PropertyService.GetPropertyDefinitionsByEntityClassId("FILE"); ACW.PropDef mNamePropDef = filePropDefs.Single(n => n.SysName == "ClientFileName"); ACW.SrchCond mSrchCond = new ACW.SrchCond() { PropDefId = mNamePropDef.Id, PropTyp = ACW.PropertySearchType.SingleProperty, SrchOper = 3, // is equal SrchRule = ACW.SearchRuleType.Must, SrchTxt = mIpjFileName }; string bookmark = string.Empty; ACW.SrchStatus status = null; List <ACW.File> totalResults = new List <ACW.File>(); while (status == null || totalResults.Count < status.TotalHits) { ACW.File[] results = mWsMgr.DocumentService.FindFilesBySearchConditions(new ACW.SrchCond[] { mSrchCond }, null, null, false, true, ref bookmark, out status); if (results != null) { totalResults.AddRange(results); } else { break; } } if (totalResults.Count == 1) { mProjFile = totalResults[0]; } else { throw new Exception("Job execution stopped due to ambigous project file definitions; single project file per Vault expected"); } //define download settings for the project file VDF.Vault.Settings.AcquireFilesSettings mDownloadSettings = new VDF.Vault.Settings.AcquireFilesSettings(connection); mDownloadSettings.LocalPath = new VDF.Currency.FolderPathAbsolute(mWfPath); mIpjFileIter = new VDF.Vault.Currency.Entities.FileIteration(connection, mProjFile); mDownloadSettings.AddFileToAcquire(mIpjFileIter, VDF.Vault.Settings.AcquireFilesSettings.AcquisitionOption.Download); //download project file and get local path VDF.Vault.Results.AcquireFilesResults mDownLoadResult; VDF.Vault.Results.FileAcquisitionResult fileAcquisitionResult; mDownLoadResult = connection.FileManager.AcquireFiles(mDownloadSettings); fileAcquisitionResult = mDownLoadResult.FileResults.FirstOrDefault(); mIpjLocalPath = fileAcquisitionResult.LocalPath.FullPath; //activate this Vault's ipj temporarily projectManager = mInv.DesignProjectManager; mSaveProject = projectManager.ActiveDesignProject; mProject = projectManager.DesignProjects.AddExisting(mIpjLocalPath); mProject.Activate(); //[Optionally:] get Inventor Design Data settings and download all related files --------- mTrace.WriteLine("Job successfully activated Inventor IPJ."); } catch (Exception ex) { throw new Exception("Job was not able to activate Inventor project file. - Note: The ipj must not be checked out by another user.", ex.InnerException); } #endregion VaultInventorServer IPJ activation #region download source file(s) mTrace.IndentLevel += 1; mTrace.WriteLine("Job downloads source file(s) for translation."); //download the source file iteration, enforcing overwrite if local files exist VDF.Vault.Settings.AcquireFilesSettings mDownloadSettings2 = new VDF.Vault.Settings.AcquireFilesSettings(connection); VDF.Vault.Currency.Entities.FileIteration mFileIteration = new VDF.Vault.Currency.Entities.FileIteration(connection, mFile); mDownloadSettings2.AddFileToAcquire(mFileIteration, VDF.Vault.Settings.AcquireFilesSettings.AcquisitionOption.Download); mDownloadSettings2.OrganizeFilesRelativeToCommonVaultRoot = true; mDownloadSettings2.OptionsRelationshipGathering.FileRelationshipSettings.IncludeChildren = true; mDownloadSettings2.OptionsRelationshipGathering.FileRelationshipSettings.IncludeLibraryContents = true; mDownloadSettings2.OptionsRelationshipGathering.FileRelationshipSettings.ReleaseBiased = true; VDF.Vault.Settings.AcquireFilesSettings.AcquireFileResolutionOptions mResOpt = new VDF.Vault.Settings.AcquireFilesSettings.AcquireFileResolutionOptions(); mResOpt.OverwriteOption = VDF.Vault.Settings.AcquireFilesSettings.AcquireFileResolutionOptions.OverwriteOptions.ForceOverwriteAll; mResOpt.SyncWithRemoteSiteSetting = VDF.Vault.Settings.AcquireFilesSettings.SyncWithRemoteSite.Always; //execute download VDF.Vault.Results.AcquireFilesResults mDownLoadResult2 = connection.FileManager.AcquireFiles(mDownloadSettings2); //pickup result details VDF.Vault.Results.FileAcquisitionResult fileAcquisitionResult2 = mDownLoadResult2.FileResults.Where(n => n.File.EntityName == mFileIteration.EntityName).FirstOrDefault(); if (fileAcquisitionResult2 == null) { mSaveProject.Activate(); throw new Exception("Job stopped execution as the source file to translate did not download"); } string mDocPath = fileAcquisitionResult2.LocalPath.FullPath; string mExt = System.IO.Path.GetExtension(mDocPath); //mDocPath.Split('.').Last(); mTrace.WriteLine("Job successfully downloaded source file(s) for translation."); #endregion download source file(s) #region VaultInventorServer CAD Export mTrace.WriteLine("Job opens source file."); Document mDoc = null; mDoc = mInv.Documents.Open(mDocPath); foreach (string item in mExpFrmts) { switch (item) { case ("STP"): //activate STEP Translator environment, try { TranslatorAddIn mStepTrans = mInvSrvAddIns.ItemById["{90AF7F40-0C01-11D5-8E83-0010B541CD80}"] as TranslatorAddIn; if (mStepTrans == null) { //switch temporarily used project file back to original one mSaveProject.Activate(); throw new Exception("Job stopped execution, because indicated translator addin is not available."); } TranslationContext mTransContext = mInv.TransientObjects.CreateTranslationContext(); NameValueMap mTransOptions = mInv.TransientObjects.CreateNameValueMap(); if (mStepTrans.HasSaveCopyAsOptions[mDoc, mTransContext, mTransOptions] == true) { //open, and translate the source file mTrace.IndentLevel += 1; mTrace.WriteLine("Job opens source file."); mTransOptions.Value["ApplicationProtocolType"] = 3; //AP 2014, Automotive Design mTransOptions.Value["Description"] = "Sample-Job Step Translator using VaultInventorServer"; mTransContext.Type = IOMechanismEnum.kFileBrowseIOMechanism; //delete local file if exists, as the export wouldn't overwrite if (System.IO.File.Exists(mDocPath.Replace(mExt, ".stp"))) { System.IO.File.SetAttributes(mDocPath.Replace(mExt, ".stp"), System.IO.FileAttributes.Normal); System.IO.File.Delete(mDocPath.Replace(mExt, ".stp")); } ; DataMedium mData = mInv.TransientObjects.CreateDataMedium(); mData.FileName = mDocPath.Replace(mExt, ".stp"); mStepTrans.SaveCopyAs(mDoc, mTransContext, mTransOptions, mData); //collect all export files for later upload mUploadFiles.Add(mDocPath.Replace(mExt, ".stp")); mTrace.WriteLine("STEP Translator created file: " + mUploadFiles.LastOrDefault()); mTrace.IndentLevel -= 1; } } catch (Exception ex) { mTrace.WriteLine("STEP Export Failed: " + ex.Message); } break; case "JT": //activate JT Translator environment, try { TranslatorAddIn mJtTrans = mInvSrvAddIns.ItemById["{16625A0E-F58C-4488-A969-E7EC4F99CACD}"] as TranslatorAddIn; if (mJtTrans == null) { //switch temporarily used project file back to original one mTrace.WriteLine("JT Translator not found."); break; } TranslationContext mTransContext = mInv.TransientObjects.CreateTranslationContext(); NameValueMap mTransOptions = mInv.TransientObjects.CreateNameValueMap(); if (mJtTrans.HasSaveCopyAsOptions[mDoc, mTransContext, mTransOptions] == true) { //open, and translate the source file mTrace.IndentLevel += 1; mTransOptions.Value["Version"] = 102; //default mTransContext.Type = IOMechanismEnum.kFileBrowseIOMechanism; //delete local file if exists, as the export wouldn't overwrite if (System.IO.File.Exists(mDocPath.Replace(mExt, ".jt"))) { System.IO.File.SetAttributes(mDocPath.Replace(mExt, ".jt"), System.IO.FileAttributes.Normal); System.IO.File.Delete(mDocPath.Replace(mExt, ".jt")); } ; DataMedium mData = mInv.TransientObjects.CreateDataMedium(); mData.FileName = mDocPath.Replace(mExt, ".jt"); mJtTrans.SaveCopyAs(mDoc, mTransContext, mTransOptions, mData); //collect all export files for later upload mUploadFiles.Add(mDocPath.Replace(mExt, ".jt")); mTrace.WriteLine("JT Translator created file: " + mUploadFiles.LastOrDefault()); mTrace.IndentLevel -= 1; } } catch (Exception ex) { mTrace.WriteLine("JT Export Failed: " + ex.Message); } break; case "SMDXF": try { TranslatorAddIn mDXFTrans = mInvSrvAddIns.ItemById["{C24E3AC4-122E-11D5-8E91-0010B541CD80}"] as TranslatorAddIn; mDXFTrans.Activate(); if (mDXFTrans == null) { mTrace.WriteLine("DXF Translator not found."); break; } if (System.IO.File.Exists(mDocPath.Replace(mExt, ".dxf"))) { System.IO.FileInfo fileInfo = new FileInfo(mDocPath.Replace(mExt, ".dxf")); fileInfo.IsReadOnly = false; fileInfo.Delete(); } PartDocument mPartDoc = (PartDocument)mDoc; DataIO mDataIO = mPartDoc.ComponentDefinition.DataIO; String mOut = "FLAT PATTERN DXF?AcadVersion=R12&OuterProfileLayer=Outer"; mDataIO.WriteDataToFile(mOut, mDocPath.Replace(mExt, ".dxf")); //collect all export files for later upload mUploadFiles.Add(mDocPath.Replace(mExt, ".dxf")); mTrace.WriteLine("SheetMetal DXF Translator created file: " + mUploadFiles.LastOrDefault()); mTrace.IndentLevel -= 1; } catch (Exception ex) { mTrace.WriteLine("SMDXF Export Failed: " + ex.Message); } break; default: break; } } mDoc.Close(true); mTrace.WriteLine("Source file closed"); //switch temporarily used project file back to original one mSaveProject.Activate(); mTrace.WriteLine("Job exported file(s); continues uploading."); mTrace.IndentLevel -= 1; #endregion VaultInventorServer CAD Export #region Vault File Management foreach (string file in mUploadFiles) { ACW.File mExpFile = null; System.IO.FileInfo mExportFileInfo = new System.IO.FileInfo(file); if (mExportFileInfo.Exists) { //copy file to output location if (settings.OutPutPath != "") { System.IO.FileInfo fileInfo = new FileInfo(settings.OutPutPath + "\\" + mExportFileInfo.Name); if (fileInfo.Exists) { fileInfo.IsReadOnly = false; fileInfo.Delete(); } System.IO.File.Copy(mExportFileInfo.FullName, settings.OutPutPath + "\\" + mExportFileInfo.Name, true); } //add resulting export file to Vault if it doesn't exist, otherwise update the existing one ACW.Folder mFolder = mWsMgr.DocumentService.FindFoldersByIds(new long[] { mFile.FolderId }).FirstOrDefault(); string vaultFilePath = System.IO.Path.Combine(mFolder.FullName, mExportFileInfo.Name).Replace("\\", "/"); ACW.File wsFile = mWsMgr.DocumentService.FindLatestFilesByPaths(new string[] { vaultFilePath }).First(); VDF.Currency.FilePathAbsolute vdfPath = new VDF.Currency.FilePathAbsolute(mExportFileInfo.FullName); VDF.Vault.Currency.Entities.FileIteration vdfFile = null; VDF.Vault.Currency.Entities.FileIteration addedFile = null; VDF.Vault.Currency.Entities.FileIteration mUploadedFile = null; if (wsFile == null || wsFile.Id < 0) { // add new file to Vault mTrace.WriteLine("Job adds " + mExportFileInfo.Name + " as new file."); if (mFolder == null || mFolder.Id == -1) { throw new Exception("Vault folder " + mFolder.FullName + " not found"); } var folderEntity = new Autodesk.DataManagement.Client.Framework.Vault.Currency.Entities.Folder(connection, mFolder); try { addedFile = connection.FileManager.AddFile(folderEntity, "Created by Job Processor", null, null, ACW.FileClassification.DesignRepresentation, false, vdfPath); mExpFile = addedFile; } catch (Exception ex) { throw new Exception("Job could not add export file " + vdfPath + "Exception: ", ex); } } else { // checkin new file version mTrace.WriteLine("Job uploads " + mExportFileInfo.Name + " as new file version."); VDF.Vault.Settings.AcquireFilesSettings aqSettings = new VDF.Vault.Settings.AcquireFilesSettings(connection) { DefaultAcquisitionOption = VDF.Vault.Settings.AcquireFilesSettings.AcquisitionOption.Checkout }; vdfFile = new VDF.Vault.Currency.Entities.FileIteration(connection, wsFile); aqSettings.AddEntityToAcquire(vdfFile); var results = connection.FileManager.AcquireFiles(aqSettings); try { mUploadedFile = connection.FileManager.CheckinFile(results.FileResults.First().File, "Created by Job Processor", false, null, null, false, null, ACW.FileClassification.DesignRepresentation, false, vdfPath); mExpFile = mUploadedFile; } catch (Exception ex) { throw new Exception("Job could not update existing export file " + vdfFile + "Exception: ", ex); } } } else { throw new Exception("Job could not find the export result file: " + mDocPath.Replace(mExt, ".stp")); } mTrace.IndentLevel += 1; //update the new file's revision try { mTrace.WriteLine("Job tries synchronizing " + mExpFile.Name + "'s revision in Vault."); mWsMgr.DocumentServiceExtensions.UpdateFileRevisionNumbers(new long[] { mExpFile.Id }, new string[] { mFile.FileRev.Label }, "Rev Index synchronized by Job Processor"); } catch (Exception) { //the job will not stop execution in this sample, if revision labels don't synchronize } //synchronize source file properties to export file properties for UDPs assigned to both try { mTrace.WriteLine(mExpFile.Name + ": Job tries synchronizing properties in Vault."); //get the design rep category's user properties ACET.IExplorerUtil mExplUtil = Autodesk.Connectivity.Explorer.ExtensibilityTools.ExplorerLoader.LoadExplorerUtil( connection.Server, connection.Vault, connection.UserID, connection.Ticket); Dictionary <ACW.PropDef, object> mPropDictonary = new Dictionary <ACW.PropDef, object>(); //get property definitions filtered to UDPs VDF.Vault.Currency.Properties.PropertyDefinitionDictionary mPropDefDic = connection.PropertyManager.GetPropertyDefinitions( VDF.Vault.Currency.Entities.EntityClassIds.Files, null, VDF.Vault.Currency.Properties.PropertyDefinitionFilter.IncludeUserDefined); VDF.Vault.Currency.Properties.PropertyDefinition mPropDef = new PropertyDefinition(); ACW.PropInst[] mSourcePropInsts = mWsMgr.PropertyService.GetProperties("FILE", new long[] { mFile.Id }, new long[] { mPropDef.Id }); //get property definitions assigned to Design Representation category ACW.CatCfg catCfg1 = mWsMgr.CategoryService.GetCategoryConfigurationById(mExpFile.Cat.CatId, new string[] { "UserDefinedProperty" }); List <long> mFilePropDefs = new List <long>(); foreach (ACW.Bhv bhv in catCfg1.BhvCfgArray.First().BhvArray) { mFilePropDefs.Add(bhv.Id); } //get properties assigned to source file and add definition/value pair to dictionary mSourcePropInsts = mWsMgr.PropertyService.GetProperties("FILE", new long[] { mFile.Id }, mFilePropDefs.ToArray()); ACW.PropDef[] propDefs = connection.WebServiceManager.PropertyService.GetPropertyDefinitionsByEntityClassId("FILE"); foreach (ACW.PropInst item in mSourcePropInsts) { mPropDef = connection.PropertyManager.GetPropertyDefinitionById(item.PropDefId); ACW.PropDef propDef = propDefs.SingleOrDefault(n => n.Id == item.PropDefId); mPropDictonary.Add(propDef, item.Val); } //update export file using the property dictionary; note this the IExplorerUtil method bumps file iteration and requires no check out mExplUtil.UpdateFileProperties(mExpFile, mPropDictonary); } catch (Exception ex) { mTrace.WriteLine("Job failed copying properties from source file " + mFile.Name + " to export file: " + mExpFile.Name + " . Exception details: " + ex); //you may uncomment the action below if the job should abort executing due to failures copying property values //throw new Exception("Job failed copying properties from source file " + mFile.Name + " to export file: " + mExpFile.Name + " . Exception details: " + ex.ToString() + " "); } //align lifecycle states of export to source file's state name try { mTrace.WriteLine(mExpFile.Name + ": Job tries synchronizing lifecycle state in Vault."); Dictionary <string, long> mTargetStateNames = new Dictionary <string, long>(); ACW.LfCycDef mTargetLfcDef = (mWsMgr.LifeCycleService.GetLifeCycleDefinitionsByIds(new long[] { mExpFile.FileLfCyc.LfCycDefId })).FirstOrDefault(); foreach (var item in mTargetLfcDef.StateArray) { mTargetStateNames.Add(item.DispName, item.Id); } mTargetStateNames.TryGetValue(mFile.FileLfCyc.LfCycStateName, out long mTargetLfcStateId); mWsMgr.DocumentServiceExtensions.UpdateFileLifeCycleStates(new long[] { mExpFile.MasterId }, new long[] { mTargetLfcStateId }, "Lifecycle state synchronized by Job Processor"); } catch (Exception) { } //attach export file to source file leveraging design representation attachment type try { mTrace.WriteLine(mExpFile.Name + ": Job tries to attach to its source in Vault."); ACW.FileAssocParam mAssocParam = new ACW.FileAssocParam(); mAssocParam.CldFileId = mExpFile.Id; mAssocParam.ExpectedVaultPath = mWsMgr.DocumentService.FindFoldersByIds(new long[] { mFile.FolderId }).First().FullName; mAssocParam.RefId = null; mAssocParam.Source = null; mAssocParam.Typ = ACW.AssociationType.Attachment; mWsMgr.DocumentService.AddDesignRepresentationFileAttachment(mFile.Id, mAssocParam); } catch (Exception) { } mTrace.IndentLevel -= 1; } #endregion Vault File Management mTrace.IndentLevel = 1; mTrace.WriteLine("Job finished all steps."); mTrace.Flush(); mTrace.Close(); }