Unable to automate MS Project 2007 from C++

Hi, I am trying to automate MS Project 2007 using C++ (with or without MFC).  I have searched the web and found many examples of how to automate Excel and Word, but none for Project, so I am not sure if I am doing it right.  When I execute the code below, project opens and is visible, but when I query the tasks on the project, I get an exception.  This code doesn't show it, but I have also tried opening an existing file that has tasks and I get the same result.  Please let me know if you see anything wrong:

At the time of running this app, I have MS project open on my desktop with a project that has three tasks in it.

The code below imports the OLB, then tries to access the number of tasks, or it tries to retrieve one of the tasks.  Both operations result in an error.

I posted this on another message board (MSDN) and someone said that this was because I was using __cdecl calling convention and since MS Project automation uses COM, I need to use stdcall.  But I have switched my project to using stdcall and it has made no difference.  Besides, the actual code to call the COM interface is in a file called msprj.tli which is automatically generated by Visual Studio when I import the OLB, so I would think any calling convention requirements would be handled there.

Any ideas?  I am quite stuck on this.  Incidentally, I tried automating Excel and that works just fine, so I don't think it has to do with some problem with office on my machine.

#import "C:\Program Files\Common Files\Microsoft Shared\OFFICE12\mso.dll" rename("RGB", "MSRGB") 
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" raw_interfaces_only, rename("Reference", "ignorethis"), rename("VBE", "testVBE") 
#import "C:\Program Files\Microsoft Office\OFFICE12\MSPRJ.OLB" auto_search exclude("IFont", "IPicture") rename("RGB", "ignorethis"), rename("DialogBox", "ignorethis"), rename("VBE", "testVBE"), rename("ReplaceText", "EReplaceText"), rename("CopyFile","ECopyFile"), rename("FindText", "EFindText"), rename("NoPrompt", "ENoPrompt") 
//Here is the code to automate Project:
MSProject::_MSProjectPtr app(__uuidof(MSProject::Application));  //project opens when this line is called if it wasn't open already 
    MSProject::_IProjectDocPtr project; 
    MSProject::TasksPtr tasks; 
    MSProject::TaskPtr task; 
    app->PutVisible(-1);   //prj is already visible, but if I set this to 0, it hides, it so I am successfully talking to prj 
    project = app->GetActiveProject(); //project is nonzero after this call 
    long x = project->GetNumberOfTasks(); //this returns 3 which is correct!!  
    tasks = project->GetTasks(); //tasks is nonzero after this call 
    x = tasks->Count;  //exception is thrown here.  I have also tried tasks->GetCount() and tasks->get_Count(&x)  All of which result in the same error 
//Also, this produces an error as well:
//task = tasks->GetItem(0); //Error: Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call

Open in new window

Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

bobsegrestConnect With a Mentor Commented:
Hi Jeff,

Programming the previous generation of Microsoft Project (2003) was normally done using Visual Basic for Applications (VBA) or VB6.  Microsoft Project 2007 was rewritten using a .Net base.  VBA is part of Project and is primarily used for macros.  Most of the .Net code examples I see today are written in C#, nut VB is common as well.

Microsoft's Visual Studio Tools for Office (VSTO) have made several huge advancements over the last couple years.  In particular, templates are now available to support the development of C# and VB based "Add-Ins" for Project.  While VBA may still be attractive for home grown or one-off solutions, the Add-In model is clearly the way to go for anyone that that wants to secure their source code.  VSTO makes packaging the Add-In easy and produces a clean user or IT installable kit with all of the prerequisite tools.

For a more detailed VSTO overview, take look at the two part article written by Jack Dahlgren.


Having said all of this, I'm not aware of any reason why what you are trying to do can't work.  Its just not where most Project development is focused today and thus my "uncommon" reference.

I will offer the observation that Project was integrated into the "Office" suite late in the Project 2003 release cycle.  As such there are many internal details that push it's programming interface outside of the Office norm...

Bob Segrest, PMP
MCITP, Microsoft Project Blackbelt
Hello Jeff,

You have selected a rather uncommon approach to programming Microsoft Project.  It didn't work very well when I tried this several years ago and you are probably not going to find a lot of available support.

If you can elaborate a bit more on what you are trying to accomplish, I (or someone else in the group) might be able to suggest a more functional alternative.

Bob Segrest, PMP
MCITP, Microsoft Project Blackbelt
CheapBastardAuthor Commented:
Thank you for your response!  
What about it is uncommon, the fact that I am using C++ instead of VB, or is it the way I am approaching it in C++?  I have tried importing the OLB using the MFC class wizard to create wrapper classes, but that didn't work any better.

What I am trying to accomplish is this:
I have an application that is written in C and C++ which has timeline type data about projects and tasks.  I simply want an import/export to and from MS Project.  And it would be nice if the export to Project happened without any additional steps like exporting to a file format and then launching Project and importing that file.  That is why I wanted to use automation.  I want to be able to click a button in my app and have project launch and open a new document and have the task data appear in that document. We already do a similar thing with Excel and it works fine.  It looks like the automation api for Project is different than for Excel though.  

So, the requirements are:
Language is either C or C++.  MFC is ok, but .Net is not (no runtime on the clients).  I suppose it would be OK to write a COM object in VB to handle the automation and then access that COM from C++, if that was the easiest solution.
Export tasks from my application to Project and import tasks from Project.  
Preferable if this was done with automation rather than via file import/export to make it a one step process.

Thank you in advance for your help.
CheapBastardAuthor Commented:
Thanks for your insight.  With your help we have decided to add .Net support to our product to facilitate this.  I have tested calling a C# assembly from our application to automate Project and it worked just fine.  Our main application is primarily written in C.  So I have created a "mixed" C++ DLL that exposes an interface that can be called from C and in turn calls the methods that are exposed on the C# assembly.

I am not using the VSTO because we are still using VS 2005, but I don't think the VSTO is needed for what we are trying to do.  

Thanks for your help.
Hi Jeff,

Glad to be of assistance.

Given the difference in support, I would suggest that you seriously consider giving the VS 2008 / VSTO 3.5 solution a whirl.  As I recall, you can get a free trial for up to six months...

Bob Segrest, PMP
MCITP, Microsoft Project Blackbelt
All Courses

From novice to tech pro — start learning today.