Job-creation made simple

Let’s say you want to do email notification on lifecycle change in Vault. Here is how the email might look like: powerJobs email In order to achieve this, you want to extend the Vault JobProcessor with an email job. Have you ever tried to create a custom job for your Vault JobProcessor using the Vault API? Here is a short list of tasks you have to do:

  • Install the Vault SDK (software Development Kit)
  • start Visual Studio and create a DLL-Project
  • reference the Vault API assemblies from the SDK
  • Extend your class with the according JobProcessor interface
  • Implement the interface functions
  • Start writing your code (expects coding skills and familiarity with Vault API)
  • copy the DLL bundle into the Extension folder
  • configure the config file in order to inform the JobProcessor about the new job

The tasks above are not familiar to you? Oh, you are not a developer? But you want to do more with your JobProcessor, right? Well, you are not alone! Now, let’s have a look how this works with powerJobs:

  • create a file with the extension .ps1 in the powerJobs\Jobs folder
  • start coding using a much simpler scripting language

Can you see the difference? All right, if you are still with me, then let’s do a practical example. Your interest might be around PDF creation from your CAD files. There is a standard job for this coming with powerJobs, and there are tons of ways to tailor it. But for the purpose of this blog post, let’s see how to create email notifications with powerJobs.

This way we get notified by the JobProcessor, every time a file gets either released, rejected, reviewed, etc. And here is how it works:

Start by creating a new file with the extension .PS1 in the powerJobs\Jobs folder. The easiest way to get there is to double click on the “powerJobs configuration” shortcut on your desktop. Let’s call the file sendEmail.ps1. Just pay attention when you create the file that the extension is really ps1 and not .ps1.txt or similar. You may also see that the symbol for your new file is identical to the one of the other PS1- files in the same folder. Edit the file with any text-editor. Well, it’s better to use either the Windows PowerShell-ISE (Integrated Scripting Environment) or download free editors such as powerGUI or PowerShell Plus. This is the content of the script we are looking for:

$file = PrepareEnvironmentForFile #get the file object of the processed file

#region collect information on lifecycle transition
$lfcTransId = $powerJobs.Job.Params["LifeCycleTransitionId"] #get the lifecycle trasition ID for the lifecycle transition the job has been triggered for
$lfcStateTransition = $vault.LifeCycleService.GetLifeCycleStateTransitionsByIds(@($lfcTransId)) #get the lifecycle trasition definition for the lifecycle transition the job has been triggered for
$lfcStateTransition[0].FromID
$lfcStates = $vault.LifeCycleService.GetLifeCycleStatesByIds(@($lfcStateTransition[0].FromID,$lfcStateTransition[0].ToID))
$fromState = $lfcStates[0]
$toState = $lfcStates[1]
Add-Log -Text "file $($file.Name) transiting from '$($fromState.DispName)' to '$($toState.DispName)'"
#endregion

#region collect information about the involved users
$allUsers = $vault.AdminService.GetAllUsers()
$user = $allUsers | Where-Object { $_.Name -eq $file.Originator }
$causer = $allUsers | Where-Object { $_.Name -eq $file."Created By" }
Add-Log -Text "file orginated by $($user.Name) and last modified by $($cause.Name)"
#endregion

#region build hyperlink to Vault file
$serverUrl = New-Object System.uri($vault.AdminService.Url)
$filePath = $file."Full Path"
$filePathUrl = $filePath.Replace("$","%24").Replace("/","%2f").Replace(" ","+")
$fileUrl = $serverUrl.Scheme+"://"+$serverUrl.Host+ "/AutodeskDM/Services/EntityDataCommandRequest.aspx?Vault=Vault&ObjectId=$($filePathUrl)&ObjectType=File&Command=Select"
Add-Log -Text "hyperlink: $fileUrl"
#endregion

[System.io.file]::WriteAllBytes("c:\Temp\image.bmp",$file.Thumbnail.Image) #save the file Thumbnail as picture so that it can be attached to the email

#region prepare and send the email
$emailSubject = "The file $($file.Name) trasitioned from '$($fromState.DispName)' to '$($toState.DispName)'"
$emailFrom = "aficio@coolorange.com"
$emailTo = $user.Email # "marco.mirandola@coolorange.com"
$emailBody = "
Dear $($user.FirstName), the file <b>$($file.Name)</b> transitioned to state <b>$($toState.DispName)</b>, as <b>$($causer.FirstName)</b> changed the state.

<img src="cid:image.bmp" alt="">
<a href="$fileUrl">$($filePath)</a>

If you like to contact $($causer.FirstName) for further explaination, send him an via at $($causer.Email)

sincerely, your humble powerJobs servant
"
Add-Log -Text "Sending email to $emailTo, from $emailFrom, with Subject $emailSubject"
Send-MailMessage -From $emailFrom -To $emailTo -Subject $emailSubject -Body $emailBody -BodyAsHtml -Attachments @("c:\Temp\image.bmp") -SmtpServer "10.0.0.26"
#endregion

Add-Log -Text "Job completed"

Now, the really interesting line is #45, where the Send-MailMessage commandlet is called with simple parameters, that even non-developers can easily understand. The variables above (all starting with $) should also be quite clear. In order to send a message with some individual Vault-related content, such as file information or information around the lifecycle transition etc., we have to “talk” with the Vault server and gather some more details.

Now, the good news is that for certain typical activities, powerJobs provides simple to use commandlets. Here an example: we want to know the file name, who performed the last change and know in which folder the file is located. If we would do it with the Vault API, then the tasks would be:

  • getting the properties definitions
  • getting the properties for the given file
  • getting the folder where the file resides

This would be about 5 to 10 lines of code. With powerJobs, the $file variable, set at the top of the script file, already contains all system and user defined properties and also information about folder location. So, one line does it all for you. Quite handy, huh?

As we like to provide some good information in the email, we have to identify the lifecycle transition we are in. As powerJobs does not yet provide simple commandlets for this task, we will use the Vault API.  These are the lines:

#region collect information on lifecycle transition 
$lfcTransId = $powerJobs.Job.Params["LifeCycleTransitionId"] #get the lifecycle trasition ID for the lifecycle transition the job has been triggered for 
$lfcStateTransition = $vault.LifeCycleService.GetLifeCycleStateTransitionsByIds(@($lfcTransId)) #get the lifecycle trasition definition for the lifecycle transition the job has been triggered for 
$lfcStateTransition[0].FromID 
$lfcStates = $vault.LifeCycleService.GetLifeCycleStatesByIds(@($lfcStateTransition[0].FromID,$lfcStateTransition[0].ToID)) 
$fromState = $lfcStates[0] 
$toState = $lfcStates[1] 
Add-Log -Text "file $($file.Name) transiting from '$($fromState.DispName)' to '$($toState.DispName)'" 
#endregion

Additionally, we like to add a hyperlink in the email body that leads the user directly to the related file inside Vault. Such hyperlink must be dynamically created, and these are the according lines:

#region build hyperlink to Vault file
$serverUrl = New-Object  System.uri($vault.AdminService.Url)
$filePath = $file."Full Path"
$filePathUrl = $filePath.Replace("$","%24").Replace("/","%2f").Replace(" ","+")
$fileUrl = $serverUrl.Scheme+"://"+$serverUrl.Host+ "/AutodeskDM/Services/EntityDataCommandRequest.aspx?Vault=Vault&ObjectId=$($filePathUrl)&ObjectType=File&Command=Select"
Add-Log -Text "hyperlink: $fileUrl"
#endregion

That’s it!

Now, in order to try it out, you have to configure the automatic job queuing for the lifecycle transitions you are looking for. This can be done via the LifecycleEventEditor provided by Autodesk. The LifecycleEventEditor is one of the many little secrets of Vault. This tool can be found in the Vault SDK (C:\Program Files (x86)\Autodesk\Autodesk Vault 2015 SDK\util\LifecycleEventEditor). The setup for the SDK can be found on the ADMS Server folder (C:\Program Files\Autodesk\ADMS Professional 2015\SDK) or in the Vault client (C:\Program Files\Autodesk\Vault Professional 2015\SDK). Run the setup and then start the LifecycleEventEditor. You will then select your preferred Lifecycle definition, lifecycle state and transition. Via the “Actions” menu you will be able to add the job to that transition and then commit the changes. The job name is simply the name of your PS1 file without the extension.

LifecycleEventEditor

As you now transition your file from one state to another, then this might be the email that will show up in your inbox:

powerJobs email

Doesn’t it look cool??? So, now that you have the technique, you can extend this job to any other scenario.

Bottom line, with powerJobs it’s super simple to create a new job and thanks to the new commandlets, it’s also very simple to deal with the Vault API, even for unskilled developers!!! Have fun!!

——

P.s.: if you like to test the script and don’t have an SMTP server at your hand, you may want to use your google account. In order to do that, you have to pass to the Send-MailMessage some more arguments, such as your credentials and the according SMTP port for Gmail.

Send-MailMessage ....... -SmtpServer "smtp.gmail.com" -UseSsl -Credential $cred -Port 587

You see that the last arguments are -UseSsl for secure connection, -Credential with the according variable containing you userID and password, and the -Port 587. Now, the $cred needs to contain you username and password and the command-let Get-Credential does this for you.

$cred = Get-Credential

It will ask you interactively for your username and password. This is great, however, you don’t want to enter such things every time the job gets executed and as the job gets executed silently you wouldn’t have the ability to enter such information. For this purpose, I’d suggest to execute the command one time within a running PowerShell and store such information into a XML file that can be reused within the job. Here is the code:

$cred = Get-Credential
$cred | Export-Clixml c:\temp\cred.xml

Now your credentials are stored into a local file. This file can be read at every job like this:

$cred = Import-Clixml c:\temp\cred.xml
Send-MailMessage ....... -SmtpServer "smtp.gmail.com" -UseSsl -Credential $cred -Port 587

Once this is set up, you still will get troubles from Gmail, as it does not allow to use the SMTP server from every application. In order to change such setting, login into your google account, then follow this link https://www.google.com/settings/security and finally set the “Access for less secure apps” in the “Account permissions” section to “Enabled”. Of course you should set it back once you’ve finished your testing/demo with this job.

So, now you should be able to use Gmail as your SMTP server.

This entry was posted in powerJobs, PowerShell, Vault API. Bookmark the permalink.

6 Responses to Job-creation made simple

  1. Jörg Weber says:

    Hi Marco,
    i found your post an try it out. But i don’t use the powerjops from cool orange. Can you tell me if the jobs work without the powerjobs from cool orange and where i must save the ps1 file

    thanks a lot

    Jörg

  2. Marco Mirandola says:

    Hi Jörg, sorry, this job works only in combination with JobProcessor+powerJobs. The reason is that only with powerJobs you can create jobs using the powerShell language. However, if you are familiar with .Net you can take the code above and translate it to C# and create a custom job with Visual Studio which can be loaded in the Vault JobProcessor. The purpose of powerJobs is to make JobProcessor extensions easy to write and maintain, so that the JobProcessor becomes even more productive. Btw., there is a trial version of powerJobs, so if you like you can have a look.
    ciao
    marco

  3. Donovan Cox says:

    Marco, at some point the job got corrupted can you repost the original code, or post the PS1 file as a download link?

    • Marco Mirandola says:

      Thanks for the hint. Yes, it seems that by copy pasting the code into the blog, some characters got replaced. I’ve cleaned up the the code and it should be fine now.

  4. Alex says:

    Hi Marco,

    I’m trying to create a job through your application that would send Email notification to selected users about the current Custom Entity but can not find an analog command “PrepareEnvironmentForFile” for Curent Custom Entity. Can I do this task ?

    Thanks,

    Alex

    • Marco Mirandola says:

      Hi Alex, sorry for late reply. Given powerJobs is a coolOrange application, i would suggest to reach out to our support (support@coolorange.com), that can take care about such questions in more depth. However, no, there is no PrepareEnvironmentForFile, but that is not relevant. That function is just for simplifying the debugging or coding of a job. In case you want to create jobs for Custom Entity, you’ll receive the entity ID as a parameter into the job, and from then on you can then do whatever you like. I think we will make a little post that will show how job might look like for items, change orders and custom objects. so, stay tuned…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s