Sometimes you have to split your code into different assemblies. For example when I created a custom Admin Page which inherits from WebAdminPageBase (Microsoft.SharePoint.ApplicationPages). The problem with Microsoft.SharePoint.ApplicationPages is that it’s not deployed to the GAC.
Putting a reference to this assembly from my assembly, also containing custom webparts and other controls which have to be registered as SafeControls in the web.config, will result in deployment troubles when you use a WSP file. The problem is when SharePoint is going to register the safecontrols it will reflect your assemby and won’t be able to access the Microsoft.SharePoint.ApplicationPages assembly because it’s not available in the GAC. The same problem can be found using the Content Deployment option.
So you split your code in 2 assemblies, for example foo.bar and foo.bar.ApplicationPages. But when your custom application page is depending on an internal type declared in foo.bar you are in trouble. When compiling you will get the following message:
"CS0122: 'foo.bar.x' is inaccessible due to its protection level"
No you have only one choice: make x public. Or not?
It’s also possible to make your assembly share it’s internals with other assemblies. Add the following to you code (in foo.bar):
[assembly: InternalsVisibleTo("foo.bar.ApplicationPages, PublicKey=0a240a ... c2f34c7")]
But the public key is not your public key token. Thanks to Burt Harris’s comment at the InternalsVisibleToAttribute Class you can find your real public key using the following command:
sn.exe -Tp foo.bar.dll
Now compile your project and there you go!
It’s been a while having time and content to post on this blog but I’m back again.
I’m currently at the Project Conference 2007 in Seattle and by visiting the sessions and talking to the guys at Microsoft developing the solution I got a lot of answers for things I couldn’t find on the web or in the SDK.
The next couple of weeks I will try to post the things I found out.
Also Prometric was present so you could do the official Project exams. Being bold I just entered the “Managing Projects with Microsoft Office Project Server” exam and guess what, I’m now a Microsoft Certified Technology Specialist!
When you want to use the PSI interface you need to have a PSContextInfo object. Inside a Project Server event this will be provided so you don’t need to worry about it’s contents (except when you want to impersonate as a different user). But outside the event you will need to create one from scratch.
One of the properties you need is the SiteGuid. According to the SDK you can get this value in your code using three different methods:
- Hard-code the Guid (Not very flexible)
- Use the Windows SharePoint Services SPSite.ID property in the Windows SharePoint Services (Very heavy on resources)
- Call the sitedata web service with the PWA URL (The best solution if you ask me)
I use the third option in my application, but it returned the wrong Guid. After some debugging I finally found the problem, I requested the URL “http://localhost/PWA/” and there I made my mistake. The trailing / results in getting the Guid of the root site, not the PWA site!
I’m sure I’m not the first one falling in this pitfall, but I’m writting this to prevent you from doing the same.
I was browsing through the TimePeriodDataSet.TimePeriodsRow Members and found the following empty entries I could fill:
|
Name |
Description |
Enumeration |
|
RES_TIMESHEET_MGR_UID |
Specifies the resource unique identifier of the (next) enterprise resource reviewing on this timesheet. |
|
|
TS_WEEK_STARTS_ON |
Specifies the first day of the week for this timesheet. |
0 = Sunday 1 = Monday 2 = Tuesday 3 = Wednesday 4 = Thursday 5 = Friday 6 = Saturday |
|
WPRD_UID |
Specifies the period unique identifier of the timeperiod. |
To deploy our code we create MSI installers using Visual Studio. One problem I encountered is that there is no property available in code to know where the user has chosen to install the application.
After some searching and testing I now use the following code to get the installation path:
// Installer Application Folderstring installPath = Context.Parameters["assemblypath"];installPath = installPath.Substring(0, installPath.LastIndexOf("\\")); if (!installPath.EndsWith("\\")){ installPath += "\\";}
That’s all.
When building custom Project Server Event Receivers the result is a dll file. Using app.config and the ConfigurationManagement class will not work.
Well actually it’s possible!
The “Microsoft Office Project Server Events Service” executable has it’s own app.config where you can add entries. If you go to the Project Server bin directory (default: C:\Program Files\Microsoft Office Servers\12.0\Bin) you will find the config file named “Microsoft.Office.Project.Server.Eventing.exe.config”.
Add the appSettings section like this:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="ProjectServerEventHandlers"/> </assemblyBinding> </runtime> <appSettings> <add key="SSP Location" value="http://localhost:56737/SharedServices1" /> </appSettings></configuration>
and your application can happily use the following syntax:
ConfigurationManager.AppSettings["SSP Location"]
This can make your event just a bit easier to deploy in different configurations without the recompiling or use of extra configuration libraries.
I had a lot of trouble using impersonation with the PSI webservices in Project Server 2007. I found some posts on the web suggesting that you need to add the account to the “Process Accounts with Access to the SSP” textbox, but guess what? That box was nowhere to find!
I found one post in the “Setup/Installation Related FAQ’s” of the “Project Server 2007 VSTS Connector” on codeplex. It says:
Sometimes the textbox for “Process Accounts with Access to the SSP” will not exist on the web page. To add the account in this circumstance, go to the command line, navigate to Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN and run:
stsadm.exe -o editssp -title <sspname> -setaccounts <accounts>
So since my SSP is called “SharedServices1″ to following line did miracles:
stsadm.exe -o editssp -title SharedServices1 -setaccounts domain\user
Reading the documentation of the stsadm application, it mentiones that “New process accounts should be appended to the existing list”. So if you execute the above line any existing configuration of accounts will be gone.
To view a list of current configured account you can use the -enumssp option:
stsadm.exe -o enumssp -title SharedServices1
This will return the details of the SSP (in XML):
<ssps> <ssp name="SharedServices1" default="true" ssl="False" status="Online"> <account username="NT AUTHORITY\NETWORK SERVICE" /> <site type="Administration" url="http://server:4389/ssp/admin" /> <database type="ServiceDatabase" server="server\OfficeServers" name="SharedServices1_DB_2b6d2c6a-2374-4f0f-8d1e-e4577988aa80" authentication="Windows"> <processaccounts> <account username="domain\user"> </processaccounts> <associatedwebapplications> <webapplication name="SharePoint - 4389" url="http://server:4389/" /> <webapplication name="SharePoint - 80" url="http://server/" /> </associatedwebapplications> </ssp></ssps>
Currently I’m working on a project which uses Microsoft Project Server 2007. However the SDK is poorly documented. Today I was looking at the Admin web service which can be used to configure settings on the server. In this post I’m not going in to detail how to do this, but I’ll share with you what I’ve discovered.
I’ve researched the connection between PWA’s “Task Settings and Display” page and the properties on the StatusingSettingsRow class which were not described. See the following image:
|
Name |
Description |
Enumeration |
|
WADMIN_DEFAULT_TRACKING_METHOD |
Specify the default method for reporting progress or tasks, and whether the tracking mode should be enforced on all projects. |
1 = Hours of work done per period. 2 = Percent of work complete. 3 = Actual work done and work remaining. |
|
WADMIN_IS_TRACKING_METHOD_LOCKED |
Force project managers to use the progress reporting method specified above for all projects. |
|
|
WADMIN_PROTECT_ACTUALS |
Restrict updates to Project Web Access. |
|
|
WADMIN_STAT_ENABLE_DOWNLOAD |
Enable ActiveX Gantt view for all users. |
|
|
WADMIN_STAT_LOOK_AHEAD |
Current tasks are those tasks which are not older than or further in the future more than this amount of days. |
|
|
WADMIN_STAT_TIMESHEET_TIED |
Time entry by Timesheet only. Users will sync to update tasks. |
|
|
WADMIN_TS_DEF_ENTRY_MODE_ENUM |
Specify how you want resources to report their hours. |
0 = Resources should report their hours worked every day. 1 = Resources should report their total hours worked for a week. |
|
WADMIN_WEEK_START_ON_ENUM |
Week starts on this day. |
0 = Sunday 1 = Monday 2 = Tuesday 3 = Wednesday 4 = Thursday 5 = Friday 6 = Saturday |




