Thursday, April 16, 2009
Portfolio server 2007 User Passwords expire quickly
Login in as that account and you will see the following under settings.
Under this you will have a setting for password expiration. This defaults to 1!
This can be reset to whatever value you require. Note the grace period as well. This defaults to 7. If the password is expired for more than 7 days, the account is locked. Before this, once authenticated, the user will be prompted to change password.
Wednesday, April 08, 2009
Automating Project Server 2007 timesheets with Powershell
I needed to import some ‘support’ time that was being tracked from outside of project server. We had reports that combined the two but that seemed messy. I don’t really program though so I needed to work it out in powershell. I believe I have all the major functionality done. Still to be determined are all the issues around data overwrites, timing etc but here is a short walkthough of connecting to Project Server 2007 PSI with powershell, querying users, querying timesheets, updating a line on a timesheet and queuing an update.
Lots of help from the SDK
http://msdn.microsoft.com/en-us/library/websvctimesheet.timesheet.queueupdatetimesheet.aspx
I also referenced some of the chrisfie, code from codeplex. It was in c# but it gave some good direction.
Still very rough, maybe I will post more as I polish it out. As I spent a good part of my day today on this, hopefully it will help somebody else.
On to the powershell:
#set up some env variables. this is largely to find wsdl and csc, maybe other libraries, i stole it from the web.
$env:VSINSTALLDIR="$env:ProgramFiles\Microsoft Visual Studio 9.0"
$env:VCINSTALLDIR="$env:ProgramFiles\Microsoft Visual Studio $obj\VC"
$env:DevEnvDir="$env:VSINSTALLDIR\Common7\IDE"
$env:FrameworkSDKDir="$env:VSINSTALLDIR\SDK\v2.0"
$FrameworkPath=$([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory())
$env:FrameworkDir=$(split-path $FrameworkPath -Parent)
$env:FrameworkVersion=$(split-path $FrameworkPath -Leaf)
$env:PATH="$env:VSINSTALLDIR\Common7\IDE;$env:VCINSTALLDIR\BIN;$env:VSINSTALLDIR\Common7\Tools;$env:VSINSTALLDIR\Common7\Tools\bin;$env:VCINSTALLDIR\PlatformSDK\bin;$env:FrameworkSDKDir\bin;$env:FrameworkDir\$env:FrameworkVersion;$env:VCINSTALLDIR\VCPackages;C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin;$env:PATH"
$env:INCLUDE="$env:VCINSTALLDIR\ATLMFC\INCLUDE;$env:VCINSTALLDIR\INCLUDE;$env:VCINSTALLDIR\PlatformSDK\include;$env:FrameworkSDKDir\include;$env:INCLUDE"
$env:LIB="$env:VCINSTALLDIR\ATLMFC\LIB;$env:VCINSTALLDIR\LIB;$env:VCINSTALLDIR\PlatformSDK\lib;$env:FrameworkSDKDir\lib;$env:LIB"
$env:LIBPATH="$FrameworkPath;$env:VCINSTALLDIR\ATLMFC\LIB"
#I tried to start w/ the connect-webservice from the orielly cookbook but it was giving me errors and this just worked.
# connect to the Proj Serv Interface (PSI) and create a timesheet object to manipulate timesheets
wsdl.exe http://<SNIP>/pwa/_vti_bin/psi/timesheet.asmx?WSDL
csc /t:library TimeSheet.cs
[Reflection.Assembly]::LoadFrom("$pwd\timesheet.dll")
$objTS = New-Object TimeSheet
$objTS.UseDefaultCredentials = $true
# connect to the Proj Serv Interface (PSI) and create a resource object to manipulate resources
wsdl.exe http://<SNIP>/pwa/_vti_bin/psi/resource.asmx?WSDL
csc /t:library Resource.cs
[Reflection.Assembly]::LoadFrom("$pwd\Resource.dll")
$objRes = New-Object Resource
$objRes.UseDefaultCredentials = $true
#we will need a date mathable datetime for calc in a bit so setup a date
$today = date
#get a list of all active users
$lstRes = $objRes.ReadUserList("Active")
#you could loop through the resource list but I will set it to just me for troubleshooting.
# the full list of users can obtained with: $lstRes = $objRes.ReadUserList("Active")
#method def:
#public TimesheetListDataSet ReadTimesheetList (Guid resUID,DateTime startDate,DateTime finishDate,int select))
# the “int select” is from this table, values are added together if you need multiples.
# Acceptable Value=4. Select timesheets with Acceptable status.
# AllExisting Value=31. Select all timesheets.
# AllPeriods Value=32. Select all timesheets plus an empty record for each period with no timesheet.
# Approved Value=8. Select timesheets with Approved status.
# CreatedByMe Value=64. Select timesheets you created.
# InProgress Value=1. Select timesheets with InProgress status.
# Rejected Value=16. Select timesheets with Rejected status.
# Submitted Value=2. Select timesheets with Submitted status.
$lstTS = $objTS.ReadTimesheetList($objRes.GetCurrentUserUid(), $today.addDays(-50), $today, 31)
#we now have all the timesheets in our date range.
$lstTS.TimeSheets
#you can get a specific timesheet
$ts = $objTS.ReadTimeSheet($lstTS.Timesheets.Item(2).TS_UID)
$ts
#there are two main items here. Lines are the rows you see in your timesheet view. actuals are the items in the columns
#check your lines with
$ts.Lines
#get a specific line. NOTE: Do Not use $line variable here. That is a PS variable and it will be reset every time you hit tab.
$tsLine = $ts.Lines.Item(2)
#you will use this in a bit to get your line UID. this is what you attach your actual to.
#now check your actuals
$ts.actuals
#create a new actual to attach
$myActual = $ts.Actuals.NewActualsRow()
#note I am working on GMT and my server is on EST so it is likely the reason why the times are 5 hours off, i didn't bother to check into it too much
$myActual.TS_ACT_START_DATE = [datetime]"4/7/2009 5:00:00 AM"
$myActual.TS_ACT_FINISH_DATE = [datetime]"4/8/2009 4:59:59 AM"
$myActual.TS_ACT_VALUE = 90000 # this looks like a lot of time but for some reason PS stores data as 1000 units/min so 90,000 = 1.5 hours.
$myActual.TS_LINE_UID = $tsLine.TS_LINE_UID
#add my actual to the actuals list
$ts.Actuals.AddActualsRow($myActual)
#add my ts to the update queue
$objTS.QueueUpdateTimesheet([Guid]::NewGuid(), $ts.Headers.Item(0).TS_UID, $ts)
#check your timesheet, man, it's updated.
Friday, April 03, 2009
Portfolio server 2007 Wish List
Setup
- Give me some defaults
General
- Show me who I am logged on as
- give me a real group structure so users can be part of multiple groups
- sync users/groups w/ AD
- poor button names. In project import, does 'Finish' mean 'import', several other instances.
- tab order on pages is not always what I would expect, especially tabbing from a form field to the 'update' button.
Optimizer
- turn of the damn graph unless I ask for it. Stepping through the optimizer opens an excel graph on each page which is unnecessary and just slows things down.
Portfolio server 2007 Attribute Calculation
I wanted to add a few new attributes calculated from other attributes. I added the attribute under settings -> Attrib and indicator management -> attribute definition. I set up my automatic calculation and saved the attribute. I even went back in to verify everything saved correctly. B)
But when I added the new attribute to my dashboard, I only got a bunch of 'NA's when viewing the dashboard. meh, ok, eventually I realize I forgot to associate it. But once i associated, now they were all blank. awesome.
Long story short, the new attributes don't seem to be calculated until you load the project. Even just selecting 'edit' on a project and going back to the dash board was enough to trigger a recalc of the fields.
Update: Even just viewing the project will calculate the attributes.
Once everything is associated and you get your initial calculation, it seems to be more automatic. If I update my formulas, the updated values show up when I reload the dashboard. ie, I don't have to open the projects again.
on a side note. I would have really preferred some basic attributes to be defined. There must be a common set that most companies would use. I am thinking about optomizer attributes for budget and resource usage, for example. The tools seem pretty powerful but an option to load a basic configuration (or even the config defined in the docs, workflow, I am looking in your direction) would have been a big plus. I will get around to a real wish list someday.
Thursday, April 02, 2009
100 characters for a project scope?
I know we are living in a world of outrageous disk costs and even 100 characters of text should be a luxury. Err wait, that was 1980, when was this thing designed? Do I really want my project managers trying to plan in txt speak? "PJT gr8 OMG bnfts"
Given the small size of the portfolio server database, I am maxing these fields out. According to a post on the project server newsgroup (http://www.microsoft.com/communities/newsgroups/list/en-us/default.aspx?dg=microsoft.public.project.server&tid=f1e4971d-7390-4aba-bf1e-701de1f87df1&cat=&lang=&cr=&sloc=&p=1), we max out at 3950. I see that the application objective field is set to 3900 by default so I am going with that.
To implement, navigate to - settings -> Attribute and Indicator Management -> Attributes Definition. Click the Show Default Attributes button. Now search for your fields. Check the attribute in question and click edit. Update Maximum Text Length from 100 to what ever you want it to be. I didn't test w/ values larger than 3900.
I had to change:
PORTFOLIO_OBJECTIVES
OBJECTIVE
PROGRAM_OBJECTIVES
PROGRAM_IN_SCOPE
INSCOPE
PROGRAM_OUT_OF_SCOPE
OUT_OF_SCOPE
PROGRAM_BUSINESS_NEED
BUSINESS_NEED
PORTFOLIO_ASSUMPTIONS
PROGRAM_ASSUMPTIONS
ASSUMPTIONS
DEPENDENCIES
PROGRAM_DEPENDENCIES
With, as far as I could see, absolutely no rhyme nor reason, these were already set to 3900.
APPLICATION_OBJECTIVE
PORTFOLIO_IN_SCOPE
PORTFOLIO_OUT_OF_SCOPE
PORTFOLIO_BUSINESS_NEED
PORTFOLIO_DEPENDENCIES
I would guess there will be more. I will update this post with further details if I find them.