Description
Key Learnings
- Understand the details of the Vault API, and learn how to create your own functionality and extend existing Vault features
- Learn how to create and debug own Vault Explorer extensions, jobs, and event handlers
- Learn how to create your own Vault Explorer extensions, your own jobs, and your own event handlers to automate workflows and repetitive tasks
- Learn how to use Vault functionalities from within own applications or from within custom Inventor add-ins
Speakers
- Christian GessnerChristian Gessner is a co-founder and Head of Research & Innovation at COOLORANGE. In this role, he drives research into cutting-edge technologies that enable customers to effectively automate, implement, and customize Autodesk CAD, PDM, and PLM solutions, ensuring seamless integration with enterprise systems. With over 25 years of experience in full-stack software development, Christian specializes in Autodesk product data and lifecycle management and Microsoft development technologies. Before founding COOLORANGE, he was a member of the data management software engineering team at Autodesk.
- Markus KoechlMarkus Koechl studied mechanical engineering and the science of work. Since starting at Autodesk in 1999, he has continuously contributed to customers’ success in implementing 3D CAD and PDM solutions for over 20 years. In his current role as a solutions engineer for PDM/PLM, Markus covers Vault plm software and all of its interfaces and extensions. He helps Autodesk resellers, prospects, and customers analyze and optimize workflows and practical approaches in managing engineering data and downstream processes. Markus is frequently seen in the Vault Customization Forum and is always eager to share any best practice or solution through the Autodesk Knowledge Network AKN.
CHRISTIAN GESSNER: All right. Let's begin. So, hello. Good morning. A very warm welcome. I'm really excited. So many of you guys made it. So yesterday's party may have been long.
So anyways, I'm very happy you made it. And we have so many people here. I never expected so many attendees here in this class, because today, we jump into the water and deep dive and have a look at the Vault API and what can we do, and how can we extend Vault and how can we automate programming.
So my name is Christian Gessner. I'm a co-founder of coolOrange. Mainly, the purpose of our company is making Autodesk data management successful. So therefore, we create software for data management products. We provide services to Autodesk resellers.
And in my role as a software engineer, I have to deal with the Vault API more or less each and every day, and this for almost 10 years now. So I thought it would be nice to share some of my experiences with you guys. And here with me is Markus Koechl.
MARKUS KOECHL: Good morning.
CHRISTIAN GESSNER: He's a solution engineer at the Central European Autodesk Sales team. So he has collected some of the use cases we go over today. And he provides the use cases to this class.
MARKUS KOECHL: I advocate that we can sell this whilst we propose to extend in Vault.
CHRISTIAN GESSNER: That's a good description. Thank you. All right. So this class, as I already said, is about extending the Vault, automating the Vault, having a look at some sophisticated API details.
And so it would be good if you have a basic understanding of the Vault API already. It would be good if you understand custom objects, and since we are debugging through C# code, it would be great if you understand a little bit of C# code.
So you obviously get most out of this class if you have already created your own Vault extensions. If not, it's not a problem at all. At least you can see what's possible by using the Vault API, the vault SDK to extend Vault.
We don't expect you to be an expert when it comes to Vault API. And also we do not cover the topic Data Standard at all.
To cover all the learning objectives, I won't go through that list we prepared. Let me go to the agenda. And we prepared a short overview of the extensions, of the mechanisms. You can extend Vault. You can automate Vault. We talk a little bit about licenses. We will see how standalone applications can communicate with Vault. And after all that, Markus provides us use cases and challenges me with those use cases. And I will try to develop solutions to the scenarios.
Before we do that, I have a quiz prepared for you guys. Why did I do that? I think mainly to wake you up this morning. But, no. It's because I want to give you an idea about the extent of the Vault API.
So please raise your hands. I will ask questions. And if you think the answer is the right one, please raise your hands. This is just five simple questions.
So, Web Services. How many Web Services do you think are available in Vault? Is it between 5 and 10? Raise your hands. Is it between 10 and 20? Hands up. Or is it between 20 and 30?
You're a good man. It's 26 different Web Services available in Vault. So, next question. All these Web Services, what do you think? How many methods are provided by these Web Services?
Is it between 75 and 100? Raise your hands. Obviously, right? Is between 100 and 500? Or 500 and 750?
Yeah. Guys, you're right. It's over 600 different service methods. And obviously, we won't cover that today.
[LAUGHTER]
How many classes do you think are available in the Vault API? And this is only limited to the Web Services assemblies. Is it between 100 and 200? Raise your hands, please. Between 200 and 300? Or is it between 300 and 400?
It's not that much. It's 230 different classes. And what about the Enumerations? What do you think? Is it between 10 and 100? Between 100 and 200? 200 and 300? Interesting. Don't raise your hands twice.
[LAUGHTER]
I seen it. So it's 38 different Enumerations. So, it's a lot.
Last question. Interesting one. What do you think-- how many custom objects are available in Vault? Is it between 0 and 100? Interesting. Is it between 100 and 500? Between 500 and 1,000? None of them?
MARKUS KOECHL: Be cautious. This question is a trap. This is a real trap.
[LAUGHTER]
My first answer was zero. But I was thinking about configured custom objects. So [INAUDIBLE] is right. But it's correct, available. Good job.
CHRISTIAN GESSNER: All right. So if you want to learn more about custom objects, there were classes two days ago, What the heck is a custom object? You can watch recordings, or you can watch the online documentation if you want to learn more about custom objects. We will use them today in our examples.
All right. Let's go and do some theory. Let's have a look at the architecture of the Vault client server infrastructure.
So first of all, each and every single client communicates with the Vault service, with the ADMS and the filestore servers, through the Web Services API. So even the actions performed by the Vault Explorer, all this goes through the Web Services API. So that means, everything Vault Explorer can do, you can do by automating or programming.
On top of these Web Services, there is this Vault Developer Framework, which actually tries to provide simple methods and more object oriented programming to the Web Services API.
And finally, don't forget. You can always program your own proxy assemblies. I think you cannot see that very good because of the color here. But if you have several projects, try to minimize your code and try to use your own proxy assemblies to don't do things twice.
When we talk about the Software Development Kit of Vault, we always talk about Web Services and the VDF, both.
So how can we extend Vault? There are many different approaches and many different methods, let me say it this way.
First, we can extend the Vault Explorer. So we can add buttons to it. We can add our own tabs to it.
Also, we can create our custom jobs. So if you're thinking of automating stuff and you don't want to only have a job that is shipped by default, and that is creating PDFs or so, but you want to do your own stuff, when a lifecycle change occurs, for example, you can create your own job.
Also, you can create your own standalone application. And with standalone applications, I not only mean an EXE file, but it also can be a custom Inventor add-in, a custom AutoCAD add-in. Whatever. It can be both. So we will see all of these examples during this class today.
And I just want to mention it here-- we do not cover it in this class. One Vault Explorer extension is Vault Data Standard. And Vault Data Standard is an extension that allows you to create windows and tabs and buttons and so on, as well. But it's not through C# code or .NET code, But it's through Powershell code and through Windows Presentation Foundation dialogs in Windows.
And it's configurable and not programmable, so that's why we do not cover it today. In case you want to read more about it, Markus held a very interesting session about that two days ago. Feel free to watch the recordings.
So we spoke about the different ways of how to extend Vault. Either way, remember, this was the first architectural slide-- all the different client applications are communicating through the Web Services API. And this Web Services API, this provides also the last extensibility option, which is Custom Events. So you can subscribe to events. And you can handle those events in your code. We'll also see that during this class.
So let's have a look at the different extensions. And remember, as extensions, we consider the Explorer extensions, the custom jobs, as well as the event handlers. And all these three have something in common. We'll have a look at what these have in common.
First is, they have to implement an interface. So a Vault Explorer extension, for instance, has to implement the IExplorer extension, which is part of a specific DLL that is part of the Vault SDK.
The same is true for event handlers and custom objects also. You have to deploy a file with the extension reset config. That is basically an XML file describing the interface, the namespace, your assembly name and so on.
Also, there are a couple of mandatory attributes you have to fill out. I want to only mentioned one, which is the API version. You have to implement this to your assembly. And for Vault 2018, for instance, it has to have the value 11.
One other thing all these extensions have in common is that they have to be deployed to a specific location. So there is this C: ProgramData Autodesk Vault version extensions directory. And in there, you have to place your folder where your extension lives. And this is true for all these three different extensions.
In there also, the vcet config has to be. Also, all the assemblies you're referencing within your code have to live there, except they're in the Global Assembly Cache, of course. And you don't have to deploy assemblies that are already loaded by the host application. And with host application, I mean the Vault Explorer. If you have an Explorer extension, I mean the job processor, if you have a custom job, and so on.
So to find out which assemblies are already loaded by the host application, you can use tools like the Sysinternals Process Explorer, for instance. That shows you on startup of the application which assemblies are already loaded.
So finally, if you have all these things and your extension for some reason is not loaded by the host application, you can activate error handling. And you can do this by simply creating a new file, place it to the extensions directory, give it this name, and feed it with some basic information like the filename, date formats and so on. And you can then get debug information into that file and explore your mistakes you've probably made.
So let's talk about standalone applications very quickly. Standalone applications have to deploy all the assemblies you have referenced. And there is one special DLL you have to be careful about, which is the clmloader, which is not a managed assembly. So you cannot simply reference it in your code and say, like, copy to the output folder.
And the other special thing about this DLL is, there is two different versions available-- a 64-bit and a 32-bit version. And the easiest way to deploy this file is to use a post-build event command and use xcpoy and use the variable platform name to get either the one or the other version of this assembly with the same name.
MARKUS KOECHL: May I add one input to that?
CHRISTIAN GESSNER: Yes, please.
MARKUS KOECHL: It applies to 2017 and beyond. So if you evaluate the source code 2016 or before, it was not required. But you know, our licensing mechanism with 2017 started to have single machine license plus network licensing. And due to this new licensing mechanism, the change needs to be reflected. Just to add, because in the forum, this is a quite frequently asked question, or people are running into trouble with this clmloader DLL.
AUDIENCE: Does that mean that your own API from 2016 won't work in [INAUDIBLE]?
MARKUS KOECHL: Exactly. You need to adopt this for existing legacy code.
AUDIENCE: I'd like to mention that I've had multiple issues with that in every scenario-- not just [INAUDIBLE] but all licensing detail. Every scenario I've come across gives me the answer somewhere [INAUDIBLE]. It's just a matter of finding it. So yeah, the information's all there, if you can find them.
MARKUS KOECHL: Yeah, but I also figured out that most people didn't recognize that there is a detailed description in the help file about this change in the 2017 API.
AUDIENCE: There are supposed to be [INAUDIBLE].
MARKUS KOECHL: Yeah. OK.
CHRISTIAN GESSNER: All right. Thank you for this addition.
So that brings me directly to licensing. And the reason that we have the clmloader DLL is that, since as Markus said, Vault 2017, a component called CLiC Framework is used for licensing-- and this is embedded to the SDK-- and therefore you need all these components.
Because we talked about standalone applications, you can use your app config file for your standalone application to control the kind of licensing that is used. For instance, if you have a standalone application that wants to have read only access to Vault, you can specify it in the app config. And so no license is grepped.
I mean, it's checked whether it's available, but it's not grepped. So you can do this by configuring it in the app config file of your application.
And as we have already seen, there is two different versions of all the assemblies. And this is due to the licensing component that came in. And please make sure you deploy, or you reference to the right ones.
For instance, our Vault office client is only available in x86, whereas Workgroup and Professional, as well as Inventor Add-Ins, have to be created in 64-bit. With standalone applications or AutoCAD Add-Ins, you can choose between both of them. So make sure your configuration matches to the version you address.
All right. That was the theory part. Let me hand over to Markus to get the first challenge.
MARKUS KOECHL: Yeah. Let's start with the first use case I brought with.
So CopyDesign is so powerful that we see the most new files created of designers are through copy. And the downside is that it's hard to capture later on which file got copied from the same source.
CopyDesign has a smart rule in built. You can store the source file in a property. That's fine for all files created with the new copy design. But what about the 100,000s of legacy files? How can we detect the relationship created by copies?
So there is an ID. Inventor has an internal ID that never changes. And with that, I assume we could build a solution. And if you could help us this morning to extract this ID, I guess I can build on that.
CHRISTIAN GESSNER: Yeah. What do you think about building a custom job that is like searching all the files in Vault which doesn't have this internal ID?
MARKUS KOECHL: Sounds good, because this could be applied to all existing legacy data.
CHRISTIAN GESSNER: Yeah. What if we used a job to, like, download the Inventor file, extract the InternalID and write it back to this property in this one job? Should I do that for you?
MARKUS KOECHL: Yep. Great. Then I can search for that.
CHRISTIAN GESSNER: All right. So in this example, we will see how to create a custom job. We will see how to debug through it. We will see some off topic things like, I want to introduce you to Fiddler in order to find out the Web Services communication that happens, and details about it.
We will see how paging is used in Vault and used by the API. We also are going to see an interesting off topic, which is conditional breakpoints. This may be new to you, but it's quite helpful, especially if you have a lot of loops and things like that. And finally, we will see how we can utilize the Vault API to download that file. So a lot of great examples that we can show here, using this one use case. So let me switch over to my VisualStudio very quickly.
So I have already prepared a job. And let me show you how I did that. So I did all the things that I mentioned before. I implement the IJobHandler interface. I set the API version and the extension ID and the other mandatory attributes.
And I provided a recent config file. And this recent config file has a specific type and interface, everything like I explained in the slides before. So let's have a look at the job and how it's executed.
But before we do that, I want to introduce Fiddler to you guys, because this is quite powerful. And what if we do not know how to find files? And I've prepared a small search folder for that.
I've prepared all the Inventor files without internal ID. And if I go to that search folder, we will see, we have like 500 different Inventor files here in this Vault, which do not contain an internal ID. Let me show you how these searches are configured.
It says, the internal ID is empty, and the provider is Inventor. So how the heck do we know what to do using the Vault API?
We can use Fiddler and listen to what the Vault Explorer is communicating with the server. Let me open Fiddler very quickly.
So basically, it traces all the web communication. So if I redo that search again, find now, and go back to Fiddler, I see the Vault Explorer called quite a lot of methods. And the first is, find files by search conditions. And this is actually very interesting.
And I have a funny story about that. So you can see there is the raw data that we can see here on the right hand side. And this contains the data I've sent. But it's kind of messy. It's XML structure and you cannot read it very good.
That's why we came up with a tool that is called [INAUDIBLE] It's an extension to Fiddler. It's an add-in. And it extracts the data that has been sent to the server, and also, the data that came back from the server. And our CEO wrote that, I think, in a hotel room very quickly. And it's so powerful, and I love to use it, because you can use it and see all the communication in a very clean and simple structure here.
So as we can see, as we remember, we got back like 500 results. Find files per search condition only returned-- and this is part of the property here that came back from the server-- it returned 499 different files that has been found. And why not 500? Because there was another call sent to the server, which queried for the links. And there was one link. So this is why the bullet shows 500 results to that search.
So we can use that. And now that we know that we can use find files by search conditions, we can implement that to our job.
So let me go back to the job. And this is what I've extracted from the Fiddler. So I've created two search conditions.
One is that the internal ID must not be empty. And the other is that the provider has to be Inventor. And let me quickly submit that job for you. And let's have a look at the job queue.
So there is now one job in here. So now we can have a look at how debugging looks like.
Debugging is pretty simple also. All you have to do is, you have to start an external program, which is the Connectivity Job Processor Delegate Host. And let me do that for you.
And this actually hosts the Job Processor. So, this just basically runs in the background. And while your job is running, you don't have to care about that. But this enables your debugging through your job. So when you now open your Job Processor-- and I hope I said a breakpoint. Yep. I expect to hit that breakpoint.
So we can debug through the code now. So we gather a couple of property definitions. I don't go into detail about that. As I said before, I set my search conditions.
I can search that. So I can call find files by search conditions. So there is one special thing here, and this is paging.
Let me execute that single line. And let me show you what came back.
We only got back 100 files. How come? There were 499 files found. Let me show you the status that came out of that call.
It says 499. But because there is a paging, you will only get back the amount of what you have said with the paging. So the paging is set using the ADMS console. If you go to Advanced, I don't show you that. You will find that. But you can set the paging. And depending on the size of the paging, this is the result you get back, which means to get all the results back, you have to call this in a loop.
So in here, my code runs and knows that it's not finished yet because of the status that is coming back. And because of the amount of files that I totally gathered.
So only if I have received all the files I'm interested in, I can go out of the while loop. Does that make sense?
AUDIENCE: So the method is aware that you recalled it once before and it had results?
CHRISTIAN GESSNER: Exactly. Because there is a bookmark that comes out and the command knows about that.
AUDIENCE: Is that the same way the UI handles it?
CHRISTIAN GESSNER: Exactly.
AUDIENCE: [INAUDIBLE].
CHRISTIAN GESSNER: Exactly. Right. So let me open that very quickly again. If I go to that result, I have 100 of that here. And I have to hit More to get the next 100.
All right. So we want to update our 499 files. What if one is like checked out, and we cannot update that file? I've prepared that scenario for you. Let me go through that. Where is it? Here.
I have one part that is checked out. And I'm wondering whether I want to get some information. I want to see that object in my code while debugging.
And this is where I want to show you conditional breakpoints. You see this for each loop here? And I'm only interested in that one single part out of the 500 parts I have in my files array.
And [INAUDIBLE] provides a method or mechanism called conditional breakpoints. And you can set a breakpoint, right click on it, and say conditions. And I can say, like, file .name equals my filename.
So when I click Continue-- oops. I have another breakpoint here. Let me continue again. It goes through that for each loop until it reaches this one single file. Let me show that to you.
So now I can see what are the property values of that. And I can analyze that object now. This is quite helpful. Yes, please.
AUDIENCE: So instead of hard coding the number, can't you just check to see if it's checked out?
CHRISTIAN GESSNER: Yeah. You can use any property. Sure.
All right. So I will quit that job, because I don't want to update 500 different files here. But I want to update a couple. So I thought about limiting that the files that have been checked in or created in the last month.
So I'm going to introduce a new search condition, which is currently not part of my search folder. But I want to introduce it in the code here, just to show you how to deal with searching date time values.
So in order to do that, you have to create a new search condition. You have to add the date time. And here you can see, I added minus 30 days. And in order to understand that this is a date, you have to convert it to a string. But before, you have to convert it to universal time, and then to a string, but in a different format, in order to let the Vault API know that you want to search for a date value. So this is also something that is not happening every day. But now you know that this way is possible.
AUDIENCE: But is this this happening with the final release version of [INAUDIBLE] version [INAUDIBLE]? Is this just the one file that it's going to react on?
CHRISTIAN GESSNER: So the search always returns the last version. Is this the question? Yeah. So, actually, there is, let me--
AUDIENCE: Like if I wanted to save my history.
CHRISTIAN GESSNER: Yeah. Say that again, sorry?
AUDIENCE: Like if I wanted to save my history.
CHRISTIAN GESSNER: OK. All right. So let me comment out the property updating. I'm using the extensibility tools to update my files. And I will start it again and resubmit my job. Remember, I canceled it.
Whoops. Oh, I, cannot because the applications are open. Anyways. So the job would now get back all these files we have seen, but only the ones that have been checked in or created in the last 30 days.
I'll quickly go through that. Still not. Something's still open.
AUDIENCE: No choice, is there?
CHRISTIAN GESSNER: Sure. Here it is. Thank you. That's a [INAUDIBLE].
Here we go. And if we restart that now this should process the files. Here we go. And I quickly go over that.
As we can see, we have 11 files left. And I can proceed then.
So, Markus, I guess this is what you were looking for, right?
MARKUS KOECHL: Yep. But I'm not 100% satisfied.
CHRISTIAN GESSNER: How come?
MARKUS KOECHL: Now we have the job, but can we trigger this job? Shall I select all these files manually and submit chops to update? You built in the search, so in theory, the job could do this on its own.
CHRISTIAN GESSNER: Yeah. So what about creating a standalone application that submits that job to the queue? Instead of you walking into the office at midnight and submitting it manually?
MARKUS KOECHL: I would appreciate that the job does his task without me at midnight.
CHRISTIAN GESSNER: Challenge accepted I would say, yeah.
All right. So I prepared a standalone application that triggers a job, just to show you a couple of things. One is that I want to show you how you have to deploy your assemblies. I'm going to show you how to debug standalone application. And we will have a short look about the licensing.
So as I mentioned before, and let me start with the license, because I can finish that very quickly-- I have here a licensing. And this is set to none. I don't want to consume. I don't want to grab a license, because submitting a job doesn't require a license. This is something you might not have known before.
So therefore, I have created a very simple standalone application that is getting three arguments. We have to pas the job type. We have to pass the description and the priority of the job, both as strings. And then we read out the app config file. I read out the server name, Vault name, username and so on. And finally, you create a connection to Vault using the Web Services. So I pass a user password credential to that. And finally, I add a job to that.
And once again, this doesn't require a license to be grepped from the license server. And finally, please don't forget to sign out. Even though if you didn't grab a license with that, you have to sign out anyways.
So I will change the startup project. I will recheck that the job queue is empty. Now I can simply-- so when it comes to debugging, I set some start options.
So I pass the job type. I pass the description and priority as I said before. And so this way, I can simply start that application. This hits the breakpoint for me. And we can go through that.
I get information out of the app config file, log into Vault, add the job. Sign out again. And that is saved. And if we have a look at the job queue now, this standalone application submitted the job to the queue. Very simple.
But since it's a standalone application, we can use Windows Task Scheduler to run it whenever we want. So we can configure it. And you probably know better than I do how to configure that Task Scheduler. I use the run button that is available in here. And this sends me also a job to the queue.
Here you go. What do you say now, Markus?
MARKUS KOECHL: Great. Perfect. Let's see how this works out in my environment.
So here we go. And I prepared a saved search internal ID, not empty. So I got several ones. But I just said, it's great. But how to find the same IDs?
So for instance, I copied one and put that into the search. I get one back. So should I query and type into this internal ID? I want to find the siblings.
And to do that, I use Data Standard. He already introduced me. Christian said I am the Data Standard guy. Yeah. So I leveraged this and simply built a dialogue showing all the siblings.
So this currently doesn't have one. If I start to copy that, I copy. Good to know. Then I take one that has existing copies. And you see, left hand, this is the source file number 272. And I'm getting several files that are identical in terms of the internal ID. And I can select one and navigate to this.
So I simply used what I learned from this search, and applied it to an edit dialog in the Data Standard. I am searching for the internal ID of the selected file, and it returns all the others having the same internal ID.
Good. But now my colleagues are going to copy hundreds of files this afternoon. Shall I wait for the job the next night to get the correct result? I think there is some room for improvement again.
CHRISTIAN GESSNER: You're right, as always, Markus. What about having an event handler that automatically, when we first check in a file, gathers that information and writes it to the property? What do you think about that?
MARKUS KOECHL: Sounds good for all new device. So I am 100% satisfied to keep with the work you did before for all the legacy files. But I think we should follow this path to stay current, to keep all the new created copies as well up to date.
CHRISTIAN GESSNER: And you're absolutely right. And this gives me a chance to compare the Web Services a little bit with the VDF, the Vault Development Framework.
So in our previous version, in our job, we used the Web Services to download the file. In this example here, I want to show you how to use the VDF to download the file and compare it to each other a little bit.
So before we do that, before I show you that, again, let me show you how to create an event handler that can subscribe to events that happen in Vault communication.
So again, I implemented the IWeb service. This one single interface, in this case the IWeb service extension. I again have my API version extension ID. I do have my reset config file with the appropriate settings. And I have my references in here again. So I'm good to go and have an event handler.
So in order to debug that, this time, I will start up Inventor instead of the job processor, because I'm using Inventor to check in this file. So let me go back to the code. And let me explain it a little bit before I start up Inventor, or let me start up Inventor at the same time.
So I have a-- that's not what I wanted. Sorry. I have to set my startup project accordingly. Let me try it again. So Inventor takes a while to come up. I want to use the time to explain the code a little bit.
So actually, steps, except the search. So we only have one file now. But this time, we have to take care about whether it's a real Inventor file, or it's a DWF for instance, that also gets checked in by Inventor.
So I have a filter that only allows a couple of file extensions. And I want to show you in this example how we can distinguish between the application that checked in the file.
So Inventor can check in files. You can check in files using Vault Explorer by drag and drop. And you may want to have different behaviors of your event handler depending on the application. So with this example, I want to show you how to differentiate between the application, how to know within your event handler which application has raised this event.
So I want to show you how to do that by debugging it. So I can put a motor. And I want to check that in. Give me a second.
All right. So let's check in that one. Let me first make sure I set a breakpoint. I did.
And I'm expecting my VisualStudio to recognize that and to debug it. So instead of using only the Web Service Manager, which I did before, I have to create a connection object because remember, I want to use VDF to download my file later on.
That's why in the very beginning I create a new connection object. And then I go and handle my extension. And before Inventor checks in, the model here in this case, it checks in the DWF file. So I return that, continue.
And then the second time, my IPD gets checked. So how can we distinguish between the different applications now that are communicating?
So first, I try to get the entry assembly. This is what I always do first, because this is a part of the net functionality. Well, it gives me back the assembly. I double click and start it up-- the entry one.
Since Inventor is not a managed application, Inventor gives me back-- no. But Vault would give me back the Vault Professional EXE assembly. And for instance, a copy design would give me back the copy design EXE.
So this way, I can distinguish this. If I don't get back the entry assembly, I can check the calling assembly. And the calling assembly in case of event handlers, is always the Web Services DLL that is used.
And Inventor uses its own instance of the Web Services DLL, so its own copy. And get calling assembly gives me back right that assembly. So in this way, I know, OK. It was Inventor that raised this event. Is that new to you guys? Do you know that? You can use it?
AUDIENCE: Yes.
CHRISTIAN GESSNER: Great. All right. So let's continue with the next example. So I already said I don't want to use the Web Services. But I want to use the VDF to download a file. And the approach is a little bit different now.
Who in this room already worked with VDF? Raise your hands. All right. So this is more object oriented.
So with the Web Services, we only have these methods. We can only communicate to the Vault server using these methods. We only have add file, find files for search conditions, and so on. And the object we get back is never like Save, or so. It's always a very thin kind of object that comes back, which only has properties and fields, but no methods.
The approach with the VDF is a little bit different. It's a little bit more object oriented, as I said before.
So to download a file, you have to specify a folder using a special object. And you have to introduce a settings object. And this settings object can be feeded with whether you want to check out or download, or things like that, or both.
And you have to pass your path object to that settings object. And finally, you have to pass your entity. So which file you want to download. And you can pass more than one entity. So you can pass like a couple different files, which then get downloaded all at one time.
And once you have you have set up that settings file, you can send it to the method acquire files, and this downloads the file for you.
AUDIENCE: Is there an object to download files with respect to [INAUDIBLE]?
CHRISTIAN GESSNER: I think so. You can download structures as well.
AUDIENCE: Pardon me?
CHRISTIAN GESSNER: You can download structures as well, including all the necessary files to open it, yeah.
AUDIENCE: The folder manager has access to the working folder [INAUDIBLE]?
CHRISTIAN GESSNER: Can you repeat the question?
AUDIENCE: The folder manager has access to the working folder?
CHRISTIAN GESSNER: Yes.
AUDIENCE: With the rights which would be appropriate for the [INAUDIBLE].
CHRISTIAN GESSNER: Yeah. Yeah. Right. Exactly.
All right. So, and then finally, we use apprentice again to get out the internal ID like here. And we update our properties once again using the Explorer Loader utility. And this way we get this file. And it has already the internal ID set. I will show it that very quickly in Vault once it starts.
Here we go. And as you can see in the previous version, the first version that has been checked in, the internal ID is empty. And because of our event handler, the internal ID is set now. It's that easy, isn't it? So what do you say?
MARKUS KOECHL: I'm very pleased, especially because you also said not only Inventor could be handled as a sender, also Copy Design. And this makes me more relaxed, because even if in future, my colleagues copy thousands of files, we also can leverage the Copy Design check in event to do the same. And with that, I no longer rely on my rule-- is the rule set, is the rule applied? So, whatever. So it's 100% secured workflow. I'm very satisfied. Thanks.
CHRISTIAN GESSNER: You're welcome. So I think we have to switch screens again.
Instead of going through the summary, I really want to let you know that we also have spent a couple of work in our handouts. And all the things that you see today, you can get it. You can read it in more detail in the handout.
So there is an index. If you will search for things that you have learned today, download the handout, go through that.
MARKUS KOECHL: Great. With that, I would like to bring up the next task for you, Christian.
CHRISTIAN GESSNER: Interesting.
MARKUS KOECHL: In the sample Vault, we implemented a custom object called Classes. And each class reflects additional properties. And I would like to assign these classes with each individual properties to make components.
So staying on default level, default capabilities of Vault Explorer, the assignment is fine. So I have here my classes. Look-- nuts, motors, frames, bolts. Just a few samples. And each of these classes has individual properties.
So the motors, for instance, I am interested in the nominal power of each motor. How to assign a motor to this class? This is an easy thing. I take it and drag it to this class.
Now I got the link. The gray motor is linked to this class. But this is the end of the default capability. And with that, I am not really satisfied.
First, it's a tedious process, to drag and drop each file that I would like to classify to the right class. And second, I added this to this class, but nothing happened. How does the motor itself know that it belongs to this class? I need to search the link.
Did I get the property, the nominal power? No. So my wish list has at least two bullets for you. I would like to do this first in Inventor, creating a new motor, or any other component. As a designer, I know what I am creating, and I would like to assign the class immediately. And not only assign the class-- I would like to get the properties also written into the file immediately that I need for this class.
CHRISTIAN GESSNER: I see. So what do you think about in Inventor add-in that gets all these classes out of Vault? You can choose it. The class name is written to your IProperty. And once you check in your file, we can handle that through an event handler. What do you think?
MARKUS KOECHL: Sounds good, but I don't know how you solve that. Because VDF, within Inventor? And VDF shares to select files and browser folders? How can you select the custom object? You're nodding, so.
CHRISTIAN GESSNER: I am. I am, OK.
MARKUS KOECHL: I leave the stage to you.
CHRISTIAN GESSNER: Thank you, Markus. Thank you. Once again, I'm accepting your challenge.
So who in his room already created an Inventor add-in? Raise your hands, please. All right. A lot.
So who did this with communicating with Vault? Right. And did you bring up a dialogue to log into Vault?
AUDIENCE: Right. After you've logged in, [INAUDIBLE]?
CHRISTIAN GESSNER: Let me show you guys how to steal the connection from the existing EDM add-in. As a first thing that we obviously have to do.
So here in this Inventor add-in-- so if you guys want to learn more about Inventor add-ins, just consult the online help in there. It's very good examples, how to create Inventor add-ins. I don't go in detail to that.
But I really don't want to bring up a login dialogue where my user has to pass username and password and Vault information, because he already did. So he already logged into Vault using the Inventor Vault add-in.
So as I said, I want to steal this connection. How can I do that? So I have prepared a little class Vault connection. Let me open that up for you.
And what I do there is, I'm using a reflection to load the EDM add-in that is already loaded by Inventor.
So if the connection is not already established, I send a small comment to this add-in, like, bring me up the dialog now. So I don't have to implement that dialog within my code. Even though the Inventor Vault add-in doesn't provide any APIs, this can be realized.
So let me go and debug that again, just to show you how this works.
AUDIENCE: Is that [INAUDIBLE]?
CHRISTIAN GESSNER: It is.
MARKUS KOECHL: And we also need to mention that all this source code-- the complete project that Christian is using is part of the additional material. So don't worry. The additional material shows up as a PDF for download. But within the PDF, we only save links to the download location of the Vault backup, the classes, et cetera, all that we use here, as well as the source code.
AUDIENCE: Any information on Fiddler or the extension as well?
CHRISTIAN GESSNER: Yep.
AUDIENCE: Very good.
CHRISTIAN GESSNER: All right. So I created an Inventor add-in that brings one new button, Assign Class, to the Tools menu. I'm a developer. I'm kind of lazy. I just use the tools. I can create my own ribbon, but I didn't want to. Tools is fine for me for this example.
So if I click it, I'm expecting to reach my breakpoint. So let me go into that function and let me show how this works.
So basically, we get the current process and the directory name, because in there, the connectivity Inventor add-in EDM add-in resides. And I check whether it exists or not. And if it exists, I load it, and using reflection, I get some types of it. And I load it. I get the properties.
I do see that I'm not signed in. So because I'm not signed in, I execute the login CMD impName, which then brings me up this dialog. I didn't implemented that VDF, so it just used the existing add-in to do that.
And once I click OK and sign in to Vault, it takes a while. Here we go. I can get, again using reflection, use the Vault connection, which is a connection object. And finally in here, I have my Vault connection object, with all the managers and Web Service manager and my ticket and server and so on. So everything a connection holds is in here.
I pass it out as an object, not as a connection, because if I would use the connection, I would have to use a reference to that one single Vault version. But Inventor can be used for different versions.
So I only return an object. And with that, I can bring up my dialog.
So let me show you a little bit more about this dialog. Basically, the VDF provides file browser dialogs, folder browser dialogs, entities. But I wasn't very happy with how custom objects can be selected.
So I created a new form that holds the Vault browser control. And this Vault browser control can show any entity. And this is part of VDF.
But I do not use it in my Vault add-in. I have a second DLL that holds this functionality. So why do I do that? Because I don't want to marry a Vault version with Inventor add-in.
My Inventor add-in should be able to connect different versions of Vault, like 2017, 2018, 2019 and so on. So to do that, I have to have a third assembly that only has an interface. And this interface only tells me about, or only defines, two functionalities, two methods.
It's initialize, where I send my connection object to, and the other one is Get Custom Entity Value. And this actually shows up the dialog where you can select your custom object and returns back the name of the selected custom object. And I have to reference that in my Inventor add-in. And I have to reference only this interface, but not the assembly that actually holds the real functionality.
And let me quickly go over the functionality of this one. So it implements that Get Custom Entity Value and initialize. And this calls another method that is like getting the icon and doing all that stuff and just getting me this list of custom objects.
But how I can it bring that third, or this version related assembly, into my Inventor add-in? I'm using late binding to do that. And let me quickly show you how to do that.
I have developed an assembly loader that is contacting my application config file and reads out a specific value. And I put it in the value of the DLL that I want to load.
So this assembly loader gets that information. And using reflection again to load this on runtime.
So I have two versions of that. Like, one is the simple one. It's not many steps. It's pretty forward. And the other one handles errors.
So by doing that, I can easily debug through that as well. So let me go through both functions-- set a breakpoint here and call that continue again. So I can-- this is also-- I have too many breakpoints. And here you go. So I can also debug through those different assemblies.
But this way, I can have only one Inventor add-in but for many different Vault versions. So this saves you probably a lot of time, because you don't have to recompile after each and every version. And so on maybe this is interesting for you. I don't know.
So this way we can use it. And let me finish that very quickly. Let me select one. Let me select motor, for instance. And if I click on OK, I can write that to the IProperty.
Here you go. And using that information, I can extend my custom event handler to not only get the internal ID, but also get this class IProperty. It automatically creates a link when it's checked in.
MARKUS KOECHL: Great. So I have a question. The dialogs you just showed us, does this allow as any other VDF grid to select additional properties? I would like to see the description of each class, for instance.
CHRISTIAN GESSNER: OK. Sure. Again, too many breakpoints. Sorry.
MARKUS KOECHL: I see.
CHRISTIAN GESSNER: It provides everything you need.
MARKUS KOECHL: Great. Great job. I'm very pleased. And did you already create the link as well, or just add the property?
CHRISTIAN GESSNER: In this Inventor, I just add the property. So I just add the IProperty class with the appropriate name. And this is basically exactly the same event handler we used before, but I extended it to not only get the internal ID, but also get, out of the property sets, the class. It passes it to the extension while it's processing, and not only updates the properties here, but also creates a link between the class and the file.
MARKUS KOECHL: So you're already done.
CHRISTIAN GESSNER: Yeah. Because I want to save time, you know?
[LAUGHTER]
[APPLAUSE]
CHRISTIAN GESSNER: Thank you. Thank you, Markus.
MARKUS KOECHL: We have some minutes left. So we can jump into another case I brought with me.
CHRISTIAN GESSNER: Oh, really?
MARKUS KOECHL: Yeah.
CHRISTIAN GESSNER: OK.
MARKUS KOECHL: I have a scenario. And imagine you have different assemblies across the history. And I would like to reflect across the history that the customer, in the year 2015, got the machine built on revision A. And this year, he ordered another one, revision B. So I would like to see that revision A is linked to an order, plus to the customer.
And I tried to do this in Vault. So here is my machine.
CHRISTIAN GESSNER: There's still a slide.
MARKUS KOECHL: Oh, thank you. I need to end the applicat--
Here we go. Here's my machine. And if I try to drag from the history to [INAUDIBLE] or to custom object to my company, to the customer, there is no way. No way to link that. The only way is, I can link using the latest version.
So if I do this, I link to Autodesk. Then the assembly shows up. If I do this twice, again, it's revision B. So that's not really what I would like to have. This left screenshot is exactly what we see in my environment. And I tweaked the screenshot using Paint. This is what I would like to get.
I would like to get, for each customer, a tab that reflects the orders and exactly the machine with its particular revision linked to this order. He's nodding, so. Easy task, isn't it?
CHRISTIAN GESSNER: You're kidding. Funny, though. Interesting.
We can use that example to create an Explorer extension. We haven't done that today. So let's create an Explorer extension that actually provides that kind of functionality. What do you think about that?
So we can learn how to use the new link properties. So we can add properties to relations instead of to pure objects.
We can see how to add a new tab, but not only to add a new tab, but to add a new tab in the context of a custom object, which is not that easy, by the way. Let me just see how we can introduce a new column that shows your order number to this VDF grid.
So we can see how to add a column to that very quickly.
MARKUS KOECHL: Sounds exciting.
CHRISTIAN GESSNER: And guess what? I've prepared a little bit.
MARKUS KOECHL: So I hand over to you again. By the way, who in the audience is aware of the link properties introduced with 2017? This is a very powerful capability. And the reason behind the implementation is that Autodesk, we had a need on that for the factory integration.
And this is powerful. But it's not visible, or directly usable, to the user. There is no UI for that. But for us as programmers, it's very powerful. And so I am very interested in how Christian solved this to leverage.
AUDIENCE: So the scenario that you're giving right now is like, I have a client that has 20 of the same machines. They've been retrofitted at different stages and different modifications that are not synonymous across the machines. So machine one may have different retrofitting. Machine two is stuck on [INAUDIBLE] machine three. But they all started from the same thing. Then these order numbers, what are we calling to be able to track each machine as a master, independent of itself? Is that correct?
CHRISTIAN GESSNER: Yes.
AUDIENCE: This is extremely powerful.
CHRISTIAN GESSNER: All right. Since we are running a little bit out of time, I really want to quickly go over how to create Explorer extensions, since many of you guys already probably already know that.
So as I have done with my other extensions, I implement an interface API versions and so on. I provide a recent config file. I don't want to go into too much detail about that.
Once I have my IExplorer extension created, I can have common sites. And instead of showing you the code, I will start that. And I've configured my debugging configuration to start Vault Explorer.
Let me find the file.
So what I have done here, using this Explorer extension, I've introduced a new command that is activated in the context of the history of the files. So the script here, if you right click on that, you get the Create an Order command.
Whereas, if you right click on this file in the main list, the Create an Order is disabled. Because only this way I can select the version that I want to actually link.
And when I click on that, it is my breakpoint. And what I've done is, I again have created a new dialog, same with what I've done in Inventor in the example before. But let me show you that dialog very quickly.
I not only added this grid, I also added a text box where I can enter my order number, my property that I use to have a property on the link.
So let me go over that. So I can enter now my order number-- I do 2017001 or whatever, and choose a company. So what this does is, it creates the link and it adds a property to that link.
So if we go now to the organization that I've chosen, it's here. And the grid not only shows the entity, but it also shows this property.
So if I use the same file, let me show it to you. If I use the same file, but with a different version of that file, and once again select [INAUDIBLE] because I have now two relations.
And you can see, both are in there. You can see the version number. And you can see the different order numbers. So it's one object, many different versions, and still a relation description. Please.
AUDIENCE: The file link will be linked back to the latest version of that, right? [INAUDIBLE]?
CHRISTIAN GESSNER: Right. You're absolutely right. In the code, you will see that when you study that at home, I have not only one property that shows the order number, but a second that shows the version of the file. It doesn't show it, but it holds it. Very good. Very good catch.
All right. Since we're running out of time, I don't show details about the code as I said. If you're interested, download the additional material. Study your code and feel free to ask questions.
[APPLAUSE]
MARKUS KOECHL: I hope you are as satisfied as me.
[LAUGHTER]
Some additional hints?
CHRISTIAN GESSNER: Oh, hold on. We have a question.
MARKUS KOECHL: Excuse me.
AUDIENCE: First of all, great class. It was good. I apologize firstly if [INAUDIBLE], but I'm hoping you might have the insight to help me with an argument I'm having back home. I have, just very briefly, a customer that has installed Vault and now their ERP system won't run, which is their interactive ledger. It all comes down to the DevExpress DLLs, and the developer of the other tool is blaming Autodesk and saying Autodesk should not be installing DLLs into the global [INAUDIBLE]. And my experience and knowledge is not sufficient to be able to say they're correct or not and say, you're wrong. [LAUGHS] Do you have any insight on--
CHRISTIAN GESSNER: Recommendation?
AUDIENCE: --like, when it's OK [INAUDIBLE] and when it's not?
CHRISTIAN GESSNER: I am not able to give a recommendation on that. So, no. I cannot answer that question. But I can do some research if you want. We can exchange business cards and--
AUDIENCE: Thanks.
MARKUS KOECHL: OK. Some additional hints and remarks. We already said, review the handout, as well as the PDF sharing the links to download everything.
But also, I recommend, don't miss to research the legacy classes of AU. So this is a powerful repository of training materials in regards to Job Processor as well as VDF. There have been classes held the past few years as well.
And don't miss to stay in touch with us through the forums. The Customization Forum is the forum we discuss API as well as Data Standards questions.
Also, my experience is, the second manufacturing dev block is not as well-known, but the ADN consultants on a regular basis are posting their tips, not only to the most current Fusion platform, but also to AutoCAD, AutoCAD Mechanical, Vault, and Inventor.
And my favorite is also the coolOrange blog, because we already see. Yeah, to be honest, on a day to day basis, they deal with our products and APIs. And they are not only consuming that, they are open and sharing their knowledge and experiences in the Wiki and the blog. So you really should reach out to that.
And not only that-- I also recommend, review all the tools and software that coolOrange is offering. There are free ones and very powerful, that are really worth its price I believe, in what customers offer feedback.
Last not least, for all in the room interested in more starting information, the class we conducted on Tuesday together-- you can leverage many templates from that for custom jobs, for extensions, for event handlers. But also, there are documented tips and tricks and use cases in the link collection that is listed here. Most of them are three, four, five years old, but they are still valid. So leverage these.
So if you are satisfied with this class, please rate in the survey. This could allow us to come back next year with another class.
[LAUGHTER]
And it's the last day. But the Answer Bar still has opening times over lunchtime to the early afternoon. And with that, we wish fun for their resting hours of AU. And again, many thanks to Christian for preparing all this stuff.
[APPLAUSE]
CHRISTIAN GESSNER: Thanks again.