Aspose logic when opening external subprojects

We have a customer issue that we’ve been able to repeat with the attached data. Their sub projects paths are to their network location, which of course is not the same as our network.

The core of the issue is that when you open the Acumen Demo File_Master.mpp in Project, Project will open the subprojects without issue. The subprojects are not in the network path indicated but rather in the same directory as the master file. This leads me to believe that Project has logic to look for files in the same directory as the master if it can’t find them in their reported file path.

It appears that Aspose does not have this same logic, as when I open the master project the sub projects have no children. We have code in our logic that when we are importing with Aspose we have implemented the logic to check the same directory if we can’t find the path of the subproject in order to import those subs properly into our product. We open those subs ourselves as new Aspose.Projects

The issue there is that if you look as Sub 1 and Sub 2 you will see that a lot tasks have the same Uid
image.png (4.5 KB)
image.png (4.4 KB)

This leads to issues in our import when resolving relationships because we can no longer rely on Uid actually being unique.

When Project successfully opens the master and resolves the subs you will see the tasks now have different Uids.

image.png (4.4 KB)

Can you confirm the logic in Aspose, that it won’t try to find external sub project files in the same directory as the master? Is there some option I can turn on to make it behave that way?

As it stands with our home brewed solution there isn’t a way to tell a task from Sub1 from a task in Sub2.

Also is there a way to get the project file name or file path from a task? I don’t see any way to get that information. (854.5 KB)

@JamesPike, you can use SubprojectName for Subproject tasks and ExternalTaskProject property for External tasks:

var p = new Project("Acumen Demo File_Master.mpp");
foreach (var t in p.EnumerateAllChildTasks())
    if (t.IsExternalTask)
        Console.WriteLine("The task '{0}' is an external task", t.Name);

    if (t.IsSubproject)
        Console.WriteLine("The task '{0}' is a subproject", t.Name);

Aspose.Tasks doesn’t try to load external sub project files regardless of the directory and doesn’t have an option to turn on loading of external sub projects.

Let me clarify this:
Project applies suproject-specific “mask” or “offset” to ensure that Uids are unique.
For example, offset for Widget Program - Sub1 is 0x800000:

Uid 8390568 of task ‘Widget Program - Sub1’ is 0x800000 + 1960,
Uid 8390679 of task ‘Widget Program Milestones’ is 0x800000 + 2071

Could you use task.ParentProject to distinct between these tasks?
Or you merge all sub projects into one master Aspose.Project?

The subproject appear to be copies of each other that were then updated, so they all have the same project name and project Guid, making it impossible differentiate them. Is there no way, given a task, to get the file name of the project?

The subproject mask I think will give me what I need. Going off your information about 0x800000, it looks like Project starts with that offset and then adds 0x400000 for each subsequent subproject. I got this increment because the four subprojects have the following offsets:

Sub1 - 0x800000
Sub2 - 0xC00000
Sub3 - 0x1000000
Sub4 - 0x1400000

All of which differ by 0x400000. So when I hit an external sub and then open it I can add this mask to the Task.Uid to get it’s true Uid (in the scope of the master.

Can you confirm that offset logic?


If the task is external task or subproject reference then you can review the code snippet in my reply ?

If task is an ordinary task, there is no public API which allows to read full path to project file, you will have to track it on your own.

Yes, we observed the same logic in our investigations.

Thank you for your help.

The mask/offset logic gives me what I need to solve the issue.

1 Like