C# Wrapper for Unmanaged DLL

Post questions here relative to DataStage Server Edition for such areas as Server job design, DS Basic, Routines, Job Sequences, etc.

Moderators: chulett, rschirm, roy

Post Reply
Rick
Participant
Posts: 3
Joined: Tue Aug 02, 2005 9:31 am
Location: Milwaukee, WI
Contact:

Post by Rick »

Just some follow up in case some else picks up this thread...

I did some more digging and see that there are some COM objects out there like 'DataStage Object Server' [vmdsobj.dll] which Interop can wrap around but I didn't see any methods to log into a server like DSSetServerParams().

Here's what I have so far. This will let you log into a server and get an ArrayList of Projects on that server. I got stuck at getting a list of jobs for the given project since the call to DSGetProjectInfo returns a DSPROJECTINFO C/C++ struct. Somehow there must be a way to wrap the struct which is viewable in 'dsapi.h' in the 'Ascential\DataStage\Dsdk\include' directory.

Code: Select all

using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;

namespace DataStageConsole
{
   /// <summary>
   /// Summary description for DataStageLibrary.
   /// </summary>
   /// <remarks>
   /// Abandoned this class after a few hour of testing.  Not sure how to represent C/C++ structures
   /// in .NET.  See the notes in GetJobList() - follow the link to google groups.
   /// </remarks>
   public class DataStageLibrary
   {
      private const string DLLPATH = "vmdsapi.dll";

      public DataStageLibrary()
      {
      }

      public void SetServerParams(string ServerName, string UserName, string Password)
      {
         DSSetServerParams(ServerName, UserName, Password);
      }

      public ArrayList GetProjectList()
      {
         IntPtr p = DSGetProjectList();
         return this.GetStringArrayFromApi(p);
      }

      [DllImport(DLLPATH)]
      private static extern void DSSetServerParams(string ServerName, string UserName, string Password);

      [DllImport(DLLPATH)]
      private static extern IntPtr DSGetProjectList();

//      public ArrayList GetJobList(string ProjectName)
//      {
//         // Open the project
//         IntPtr project = DSOpenProject(ProjectName);
//
//         // The data comes back as a struct... apparantly someone else also had trouble with this stuff:
//         //
//         // http://groups-beta.google.com/groups?hl=en&lr=&q=DSPROJECTINFO&qt_s=Search
//
//         // Close the project
//         DSCloseProject(project);
//      }

//      [DllImport(DLLPATH)]
//      private static extern IntPtr DSGetProjectInfo(IntPrt DSPROJECT, int InfoType, );

      [DllImport(DLLPATH)]
      private static extern IntPtr DSOpenProject(string ProjectName);

      [DllImport(DLLPATH)]
      private static extern int DSCloseProject(IntPtr DSPROJECT);

      private ArrayList GetStringArrayFromApi(IntPtr api)
      {
         ArrayList arr = new ArrayList();
         int idx = 0;
         bool endFound = false;
         StringBuilder curr = new StringBuilder();
         do
         {
            byte byt = Marshal.ReadByte(api,idx++);
            char c = (char)byt;
            if(byt!='\0')
            {
               curr.Append((char)byt);
            }
            else
            {
               arr.Add(curr.ToString());
               curr = new StringBuilder();
               byte end = Marshal.ReadByte(api,idx);
               if(end=='\0') endFound = true;
            }
         } while (!endFound);
         return arr;
      }

   }
}

roy
Participant
Posts: 2598
Joined: Wed Jul 30, 2003 2:05 am
Location: Israel

Post by roy »

Hi,
Last time I heard C# didn't have an API yet, worth rechecking.
I managed to build a com dll with visual studio 6 once, for interaction with DS using 3rd party programs (getting job status, running a job,...).
How ever this dll didn't work on every pc I tried it on and since I didn't have time/resources to find out why it only worked on some machines I never went public with it.

Do post any developments on this :)
Roy R.
Time is money but when you don't have money time is all you can afford.

Search before posting:)

Join the DataStagers team effort at:
http://www.worldcommunitygrid.org
Image
ray.wurlod
Participant
Posts: 54595
Joined: Wed Oct 23, 2002 10:52 pm
Location: Sydney, Australia
Contact:

Post by ray.wurlod »

The DSObjects control exposes a Session object that has properties including HostName, AccountPath, UserName and Password, and methods including Connect and Disconnect. Is this the kind of thing you seek? You need to read the UniObjects Developer's Guide for more information. This is for ActiveX/COM; there is also a UniObjects for Java Developer's Guide - same objects, but exposed as Java classes.
IBM Software Services Group
Any contribution to this forum is my own opinion and does not necessarily reflect any position that IBM may hold.
Rick
Participant
Posts: 3
Joined: Tue Aug 02, 2005 9:31 am
Location: Milwaukee, WI
Contact:

Post by Rick »

Thanks for the reply roy and ray. I took a look at the DBObjects.dll in the application install directory. "Is this the kind of thing you seek?" I'm not sure.

I was hoping to be able to traverse the DataStage objects using their properties and methods. i.e. you have a Server which has a collection of Projects (each Project being an object with properties e.g. Project.Name, Project.Description, Project.LastRunDate) which has a collection of Jobs which have a collection of Stages then Links and so on.

We were toying with gathering some processing information. i.e. How many jobs ran last week, how many rows were processed, what jobs haven't run in forever, etc. etc.

If I can walk the object model the possibilities are endless.

I see that the C API has all this. And I have even gone to the point of writing a wrapper around the Command Line Interface (CLI). But the CLI is slow - each time you run dsjob it has to connect/login/get the project/etc... so it's about .5 seconds each job. Add that up over 3000 jobs and you can see we're talking 25 minutes just to get a list of the last time X job ran - god knows how long if I want to find out how many rows were processed in a link for a given stage. From what I tested the API is alot faster. The Manual states you can do it 3 ways - via the C API, via the CLI or via BASIC. So I thought the C API gives the most flexibility.

BTW I did take a look at what Kim had for stats - looks great. Just don't think it's going to work for everything so I thought I'd explore this abit further before admitting defeat.

Now the dsobjects.dll appears promising. I can wrap Interop around it and make calls from C# or any other .net/managed code language for that matter. But I don't see the DataStage objects (Project, Stage, Link, etc) Is UniObjects what DataStage is built on top of?
ray.wurlod
Participant
Posts: 54595
Joined: Wed Oct 23, 2002 10:52 pm
Location: Sydney, Australia
Contact:

Post by ray.wurlod »

Yes, DataStage is built on UniObjects (which is now called DSObjects since the split, but Ascential never published a manual for it).
The AccountName property of a Session object is the project. After that, however, there are no sub-objects called job, stage, etc. Rather, you need to use File and SelectList objects (instantiated through the OpenFile method of a Session object) to access the Repository tables directly - much in the manner that Kim's code does. So, for example, you need to open DS_JOBS to get a list of job names and numbers (use the Next and LastRecordRead properties of the SelectList object and the Read property of the File object). Each job's number is use to construct the names of its run-time tables, such as RT_LOGnn. The DS_JOBOBJECTS table contains job, annotation, stage and link-end (pin) definitions. Enjoy.
IBM Software Services Group
Any contribution to this forum is my own opinion and does not necessarily reflect any position that IBM may hold.
Post Reply