Ejemplo n.º 1
0
        public void Activate(Inventor.ApplicationAddInSite addInSiteObject, bool firstTime)
        {
            // This method is called by Inventor when it loads the addin.
            // The AddInSiteObject provides access to the Inventor Application object.
            // The FirstTime flag indicates if the addin is loaded for the first time.

            // Initialize AddIn members.
            //m_inventorApplication = addInSiteObject.Application;
            m_inventorServer = addInSiteObject.InventorServer;

            // TODO: Add ApplicationAddInServer.Activate implementation.
            // e.g. event initialization, command creation etc.
            m_commands = new Commands(m_inventorServer);
        }
        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);
            }
        }
        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();
        }