Set Environment on new Folder using C#

 I need to set the environment on a new folder using C#, but I get an invalid parameter error.

I assume I have defined the _AADMSPROJITEM structure wrong, or confused variables with pointers or similar.

I hoped that Dave Brumbaugh had done this already, but it is not in his PWWrapper.

// define C style _AADMSPROJITEM structure
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public struct _AADMSPROJITEM
                public ulong ulFlags; //  This member is the bit mask specifying which of the structure members contains valid information.
                public long lProjectId; // Specifies the project Id.

                public long lEnvironmentId; //Specifies the environment the project belongs to.
                public long lParentId; // Specifies the parent project identifier.
                public long lStorageId; //  Specifies the default storage of the project.
                public long lManagerId; //Specifies the project manager's Id.
                public long lTypeId; //Specifies project's type.
                public long lWorkflowId; //Specifies the workflow identifier assigned to the project.
                public IntPtr lptstrName; //Pointer to a null-terminated string specifying the project name.  LPWSTR
                public IntPtr lptstrDesc; //Pointer to a null-terminated string specifying the project description. LPWSTR
                public long lManagerType; //Specifies the type of project manager.
                public long lWorkspaceProfileId; // Specifies the type of project workspace profile.
                public GUID guidVault; //Specifies the GUID of project.
                public long lComponentClassId; //Specifies the class id of the ODS instance holding rich project properties.
                public long lComponentInstanceId; // Specifies the instance id of the ODS instance holding rich project properties.
                public ulong projFlagMask; // Specifies the valid bits in the member projFlags.
                public ulong projFlags; //  Specifies the project flags to set or reset.

public static Boolean SetProjectEnvironment(int projectID, int environmentenvID)
                _AADMSPROJITEM pProject = new _AADMSPROJITEM();
                pProject.lProjectId = projectID;
                pProject.lEnvironmentId = environmentenvID;;

                return aaApi_ModifyProject2( pProject);

 [DllImport("c:\\Program Files\\Bentley\\ProjectWise\\bin\\dmscli.dll")]
public static extern Boolean aaApi_ModifyProject2(_AADMSPROJITEM lpProject);

  • Here's how AADMSPROJECTITEM is defined in a project that isn't available publicly:

            public struct AADMSPROJITEM 
                public uint ulFlags;
                public int lProjectId;
                public int lEnvironmentId;
                public int lParentId;
                public int lStorageId;
                public int lManagerId;
                public int lTypeId;
                public int lWorkflowId;
                [MarshalAs(UnmanagedType.LPWStr)] public string lptstrName;
                [MarshalAs(UnmanagedType.LPWStr)] public string lptstrDesc;
                public int lManagerType;
                public int lWorkspaceProfileId;
                public System.Guid guidVault;

    Elsewhere in the code, it is used like this:

                //Now create the project
                int outProjId = 0;
                Project.AADMSPROJITEM projParams = new Project.AADMSPROJITEM();
                projParams.lProjectId = 0;
                projParams.lParentId = tParam.parentId;
                projParams.lStorageId = projStorageId;
                projParams.lManagerId = tParam.managerId;
                projParams.lTypeId = tParam.type;
                projParams.lWorkflowId = tParam.workFlowId;
                projParams.lWorkspaceProfileId = tParam.workspaceProfileId;
                projParams.lptstrName =;
                projParams.lptstrDesc = tParam.desc;
                projParams.lEnvironmentId = tParam.lEnvironmentId;
                projParams.ulFlags = (uint)Project.CreationFlagEnum.AADMSPROJF_PROJECTID |
                                     (uint)Project.CreationFlagEnum.AADMSPROJF_PARENTID |
                                     (uint)Project.CreationFlagEnum.AADMSPROJF_STORAGEID |
                                     (uint)Project.CreationFlagEnum.AADMSPROJF_MANAGERID |
                                     (uint)Project.CreationFlagEnum.AADMSPROJF_TYPEID |
                                     (uint)Project.CreationFlagEnum.AADMSPROJF_WORKFLOW |
                                     (uint)Project.CreationFlagEnum.AADMSPROJF_WSPACEPROFID |
                                     (uint)Project.CreationFlagEnum.AADMSPROJF_NAME |
                                     (uint)Project.CreationFlagEnum.AADMSPROJF_DESC | 
                //HACK Note that environment is set to folders parent
                if ( projParams.lEnvironmentId < 1 )
                    projParams.lEnvironmentId = parentProjEnv;
                int iRes = Constants.FALSE;
                iRes = Project.aaApi_CreateProject2(ref projParams, tParam.accFromProject);
                outProjId = projParams.lProjectId;

    Hmm, I just noticed that this isn't what you were asking about, but I'll leave it in case it is helpful in some other way.

    In MostOfDavesClasses (perhaps an older, non public version), I see this:

        // dww 2013-10-02 matched SS4 documentation
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct VaultDescriptor
            public uint Flags;
            public int VaultID;
            public int EnvironmentID;
            public int ParentID;
            public int StorageID;
            public int ManagerID;
            public int TypeID;
            public int WorkflowID;
            public string Name;
            public string Description;
            public int ManagerType;
            public int WorkspaceProfileId;
            public Guid GuidVault;
            public int ComponentClassId;
            public int ComponentinstanceId;
            public uint projFlagMask;
            public uint projFlags;

    And then I find it used something like this:

    	VaultDescriptor vaultDescriptor = new VaultDescriptor();
    	vaultDescriptor.Flags = (uint)(
    		VaultDescriptorFlags.EnvironmentID |
    	vaultDescriptor.EnvironmentID = iEnvironmentId;
    	vaultDescriptor.VaultID = childVaultID;
    	success = aaApi_ModifyProject2(ref vaultDescriptor);

    You mention Dave's PWWrapper.  Are you aware of his MostOfDavesClasses?

    You can get MostOfDavesClasses from here: 

    You will need to distribute the included .dll's in order to use all of the methods.

    You can get DllExporterNet4 from


    Dan Williams
    Solution Consultant
    Bentley Systems, Incorporated
    Portland, OR, USA (Pacific Time UTC-08:00)

    Answer Verified By: Rene Lloyd 

  • The SDK  documentation lists _AADMSPROJITEM not AADMSPROJITEM and this has the 4 extra fields.

    However it seems that the shorter definition Dan gives works as follows:

    const int AADMSPROJF_PROJECTID = 0x00000001; // If set, lProjectId member contains valid information. 
    const int AADMSPROJF_ENVID = 0x00000002; // If set, lEnvironmentId member contains valid information. 
    pProject.lProjectId = projectID;  // Specifies the project Id. 
    pProject.lEnvironmentId = environmentenvID; ; // Specifies the environment the project belongs to. 
    pProject.ulFlags = AADMSPROJF_PROJECTID | AADMSPROJF_ENVID;  // Specifies the project flags to set or reset. 
    if( PW.aaAPI.aaApi_ModifyProject2(pProject) ) { ... it worked ....

    I didn't find the code in MostOfDavesClasses because I had forgotten that Vaults were the same as folders.