Connecting To TM1 Using VB.Net and the *CLASSIC* API
Posted: Sun Sep 01, 2013 9:41 am
Part 1: Introduction
In this article I wrote about using the TM1 .Net API to connect to TM1. At the end of that I said that I may get around to doing one on using the classic (VB6/VBA/C) TM1 API within the .Net environment.
That time has come. I do however warn you that this is not "An Introduction To The Classic API"; that's a vastly bigger subject, too big for a single post or even thread. If you're reading this article I expect that you already know the ropes (or at least what the ropes look like) when it comes to value capsules and value pools and user handles and the like, and just want some guidance on how to translate your existing VB6 / VBA API code into a VB.Net environment. No, I am not going to do another article on C. I haven't written a line of C code for a couple of decades and don't plan to start again now, aside from which .Net does not have plain ol' C as a native language (as opposed to C#).
The one down side to my C aversion is in relation to the callback functions which report the progress of longer running TM1 API calls. The method of using these in C is described in the documentation, but there's an embarrassed silence with regard to VB6/VBA. I've used callback functions in VB6 / VBA in relation to the Windows API, but have never had a need to use them in the TM1 API so I'm (a) not certain how well / whether they work there and consequently (b) how (or whether) they would translate to the .Net environment even if they worked in VB6/VBA. If I ever feel a moment of boredom I may explore this and report back to the three readers that this thread is likely to have. (Hi Mike Cowie and whoever else is out there!)
I'll work on the assumption that your exposure to VB.Net is basic and explain pretty much all that you need to know on that subject as we go though again, it's not "An Introduction To VB.Net".
A Slight Off Topic Diversion
Please don't ask me to put up any of the source code for download (other than that given in the body of the text) as refusal may offend. I (and I think that this also applies to the other admins, MVPs and senior members) have no issue giving other people a hand with problems that they face, or lighting the right pathway for them. If we did we wouldn't be here. However we've all invested a lot of effort to get the skills that we have, we all have roofs to put over our head and tables to put food on, and in the majority of cases other people to keep fed, clothed, sheltered and cared for as well.
Giving someone else a helping hand is one thing, but when they want us to start supplying end to end solutions, or even the skeletons of such solutions, that's when it's time to start crossing our palms with silver for our work as Harlan Ellison expressed rather forcefully here. While it's not unknown for members of the TM1 community to do that in a spirit of generosity (TM1 Tools being one example, some freeware TM1 Top-based apps being others), one problem is that in some quarters this generosity has become an expectation of entitlement. (The chestnut chant of "Information wants to be free", which is in fact a euphemism for "I want to be paid for what I do, I just don't want to have to pay for what anybody else does", encapsulating this quite well.)
The other problem is the recent trend of certain businesses in certain parts of the world employing TM1 "specialists" who wouldn't know a TI loop from a hole in their head. These businesses then undercut consultants who really do have the required skills. Their "specialists" then have the barefaced gall to try to get, through forums such as this one, those same skilled and undercut professionals to help them do the work that they don't know how to do themselves... which seems to be most of it. (Which is even more choice when they then complain that they aren't getting sufficient support from the Forum.) This hurts our livelihoods in two ways; one by debasing the value of the market for real TM1 specialists, and second by damaging the reputation of TM1 in the business community. The aforementioned "specialists" will often deliver woeful "solutions" which those who employ them may well blame on TM1 rather than on the principle of "You sometimes get what you pay for... which in this case ain't much".
That doesn't mean that I (or most likely anyone else) will stop giving a hand when a hand is needed, or from releasing the occasional goodies as a freebie, but personally I'm finding it time to wind it back just a little bit. If I had made the decision to release a complete body of source code on this or any other thread... it would already be posted here.
And now back to the subject at hand.
The Background
VB6 was released in 1998, some 15 years ago when the computing world (and to some extent the world in general) was a very different place. It may still be used to maintain some legacy applications but it's unlikely to be used to develop new ones since it's been out of support for quite a while now.
PC application development has moved into more "managed" environments such as the Java Runtime Virus, er, I mean, Engine ("Write Once, Debug Everywhere") and the .Net Framework.
Unfortunately the TM1 APIs have been less than assiduous about keeping up with this trend. I don't know what if anything Iboglix has done with the Java API over the last few versions. And if the Java-based 10.1 applications (no, the other type of "applications") like Performance Muddler are any guide, I don't want to know. However I do know that they have left those of us who are from a VB background (which would probably be most TM1 developers via Excel) swinging in the wind. The TM1 .Net API is of course the Forrest Gump of APIs in that it can perform certain simple tasks well enough, but don't ask it to perform any administrative tasks. (In fact even retrieving a set of values from a view is more painful than I expected it to be.) It has seen pretty much no development since it was released, and is not showing any signs of that changing in the future.
Which brings us back to the only relatively full featured API (if you ignore the odd gaping hole), the classic one which was designed for VB6. The problem being, of course, that VB.Net is about as similar to VB6 as Jessica Alba is to Granny from the Beverly Hillbillies.
So let us begin our journey and find a way to shoehorn the old API into a new language.
Configuring The Client: The Path Pain Remains
Whichever way you create the project, you do still need to change the Path environment variable on the client computer to ensure that the application knows the way to the API libraries. (The manual approach: Right click on Computer, select Properties, then Advanced System Settings, then Environment Variables.) That's because IBM still can't be bothered doing this as part of the TM1 client installation process, despite having a shiny, bloaty new install package in 10.1. And yes, you should have the TM1 client software installed on the machine where your application will run. Without those libraries, it won't.
Yes, yes, I know, there are a couple of sneaky ways that you can avoid doing that. Don't do it. Remember that the TM1 client software is likely to change over the life of your application, and that IBM seems to move the default install path between versions almost on a whim; 3 times in the last 4 or 5 versions. Not to mention the fact that not all workplaces will install to the default path anyway. It's far better and safer to just point the thing to this week's correct library path using the Path variable.
You can of course include code to do this in your VB.Net app via the Environment.SetEnvironmentVariable method. However this presupposes that you actually know where the installation was done to, and as we shall see, you may not. (Which is why Iboglix should have included this in their own install package.)
The process for setting the path is almost on page 1 of the TM1 API manual, and I'd advise you to refer to that for guidance. I say "almost" given the claim (even in the 10.1 manual) that:
On a 32 bit Win 7 notebook using TM1 10.1 the libraries are really found in:
Under 9.5.2 the path would have been the same except that there was no "ibm" folder above the "cognos" one. (Which means that any API applications that were written for 9.5.2 automatically broke on machines which were upgraded to 10.1 unless the path variable was also updated. Thanks for that one, IBM.)
On a 64 bit machine they're likely to be in a similar path to the one specified above but in the Program Files (x86) folder instead of the Program Files one.
Given the variability of the install location these days, you do need to plan for how you're going to update the Path when the user does an upgrade, including moving from 32 bit to 64 bit Windows. However this is no different to the situation that you'd face with a VB6 TM1 API application.
Update the Path on your machine (if you need to) before you go any further.
In this article I wrote about using the TM1 .Net API to connect to TM1. At the end of that I said that I may get around to doing one on using the classic (VB6/VBA/C) TM1 API within the .Net environment.
That time has come. I do however warn you that this is not "An Introduction To The Classic API"; that's a vastly bigger subject, too big for a single post or even thread. If you're reading this article I expect that you already know the ropes (or at least what the ropes look like) when it comes to value capsules and value pools and user handles and the like, and just want some guidance on how to translate your existing VB6 / VBA API code into a VB.Net environment. No, I am not going to do another article on C. I haven't written a line of C code for a couple of decades and don't plan to start again now, aside from which .Net does not have plain ol' C as a native language (as opposed to C#).
The one down side to my C aversion is in relation to the callback functions which report the progress of longer running TM1 API calls. The method of using these in C is described in the documentation, but there's an embarrassed silence with regard to VB6/VBA. I've used callback functions in VB6 / VBA in relation to the Windows API, but have never had a need to use them in the TM1 API so I'm (a) not certain how well / whether they work there and consequently (b) how (or whether) they would translate to the .Net environment even if they worked in VB6/VBA. If I ever feel a moment of boredom I may explore this and report back to the three readers that this thread is likely to have. (Hi Mike Cowie and whoever else is out there!)
I'll work on the assumption that your exposure to VB.Net is basic and explain pretty much all that you need to know on that subject as we go though again, it's not "An Introduction To VB.Net".
A Slight Off Topic Diversion
Please don't ask me to put up any of the source code for download (other than that given in the body of the text) as refusal may offend. I (and I think that this also applies to the other admins, MVPs and senior members) have no issue giving other people a hand with problems that they face, or lighting the right pathway for them. If we did we wouldn't be here. However we've all invested a lot of effort to get the skills that we have, we all have roofs to put over our head and tables to put food on, and in the majority of cases other people to keep fed, clothed, sheltered and cared for as well.
Giving someone else a helping hand is one thing, but when they want us to start supplying end to end solutions, or even the skeletons of such solutions, that's when it's time to start crossing our palms with silver for our work as Harlan Ellison expressed rather forcefully here. While it's not unknown for members of the TM1 community to do that in a spirit of generosity (TM1 Tools being one example, some freeware TM1 Top-based apps being others), one problem is that in some quarters this generosity has become an expectation of entitlement. (The chestnut chant of "Information wants to be free", which is in fact a euphemism for "I want to be paid for what I do, I just don't want to have to pay for what anybody else does", encapsulating this quite well.)
The other problem is the recent trend of certain businesses in certain parts of the world employing TM1 "specialists" who wouldn't know a TI loop from a hole in their head. These businesses then undercut consultants who really do have the required skills. Their "specialists" then have the barefaced gall to try to get, through forums such as this one, those same skilled and undercut professionals to help them do the work that they don't know how to do themselves... which seems to be most of it. (Which is even more choice when they then complain that they aren't getting sufficient support from the Forum.) This hurts our livelihoods in two ways; one by debasing the value of the market for real TM1 specialists, and second by damaging the reputation of TM1 in the business community. The aforementioned "specialists" will often deliver woeful "solutions" which those who employ them may well blame on TM1 rather than on the principle of "You sometimes get what you pay for... which in this case ain't much".
That doesn't mean that I (or most likely anyone else) will stop giving a hand when a hand is needed, or from releasing the occasional goodies as a freebie, but personally I'm finding it time to wind it back just a little bit. If I had made the decision to release a complete body of source code on this or any other thread... it would already be posted here.
And now back to the subject at hand.
The Background
VB6 was released in 1998, some 15 years ago when the computing world (and to some extent the world in general) was a very different place. It may still be used to maintain some legacy applications but it's unlikely to be used to develop new ones since it's been out of support for quite a while now.
PC application development has moved into more "managed" environments such as the Java Runtime Virus, er, I mean, Engine ("Write Once, Debug Everywhere") and the .Net Framework.
Unfortunately the TM1 APIs have been less than assiduous about keeping up with this trend. I don't know what if anything Iboglix has done with the Java API over the last few versions. And if the Java-based 10.1 applications (no, the other type of "applications") like Performance Muddler are any guide, I don't want to know. However I do know that they have left those of us who are from a VB background (which would probably be most TM1 developers via Excel) swinging in the wind. The TM1 .Net API is of course the Forrest Gump of APIs in that it can perform certain simple tasks well enough, but don't ask it to perform any administrative tasks. (In fact even retrieving a set of values from a view is more painful than I expected it to be.) It has seen pretty much no development since it was released, and is not showing any signs of that changing in the future.
Which brings us back to the only relatively full featured API (if you ignore the odd gaping hole), the classic one which was designed for VB6. The problem being, of course, that VB.Net is about as similar to VB6 as Jessica Alba is to Granny from the Beverly Hillbillies.
So let us begin our journey and find a way to shoehorn the old API into a new language.
Configuring The Client: The Path Pain Remains
Whichever way you create the project, you do still need to change the Path environment variable on the client computer to ensure that the application knows the way to the API libraries. (The manual approach: Right click on Computer, select Properties, then Advanced System Settings, then Environment Variables.) That's because IBM still can't be bothered doing this as part of the TM1 client installation process, despite having a shiny, bloaty new install package in 10.1. And yes, you should have the TM1 client software installed on the machine where your application will run. Without those libraries, it won't.
Yes, yes, I know, there are a couple of sneaky ways that you can avoid doing that. Don't do it. Remember that the TM1 client software is likely to change over the life of your application, and that IBM seems to move the default install path between versions almost on a whim; 3 times in the last 4 or 5 versions. Not to mention the fact that not all workplaces will install to the default path anyway. It's far better and safer to just point the thing to this week's correct library path using the Path variable.
You can of course include code to do this in your VB.Net app via the Environment.SetEnvironmentVariable method. However this presupposes that you actually know where the installation was done to, and as we shall see, you may not. (Which is why Iboglix should have included this in their own install package.)
The process for setting the path is almost on page 1 of the TM1 API manual, and I'd advise you to refer to that for guidance. I say "almost" given the claim (even in the 10.1 manual) that:
Yyyyeah. I suspect that someone just "search and replace"d "Applix" with "Cognos" in this document. Oh, certainly, the libraries probably were installed in C:\Applix\TM1\bin, some time back around version 7.1 in the grand old nostalgic days of Windows 98. Hey look, a new episode of Seinfeld is on! If you're reading this article and haven't already fallen asleep, I have confidence in you being bright enough to figure out what you need to do based on the information provided in the documentation.The following procedure assumes that you accepted the default settings during the installation, and that the IBM Cognos TM1 API .dll files are in C:\Cognos\TM1\bin.
On a 32 bit Win 7 notebook using TM1 10.1 the libraries are really found in:
Code: Select all
C:\Program Files\ibm\cognos\tm1\bin
On a 64 bit machine they're likely to be in a similar path to the one specified above but in the Program Files (x86) folder instead of the Program Files one.
Given the variability of the install location these days, you do need to plan for how you're going to update the Path when the user does an upgrade, including moving from 32 bit to 64 bit Windows. However this is no different to the situation that you'd face with a VB6 TM1 API application.
Update the Path on your machine (if you need to) before you go any further.