Archive for March, 2008
Project Server 2003 PWA Menu Customization
31 March 2008Microsoft Project Server 2003 Web Access provides a mechanism for developer to customize the menu. However, any menu added by “server configuration” in admin page will no security validation, that all user can view it, even if it is under admin submenu.
Solution
The reason is that the default global permission of a custom menu is 0, which means every user has permission to view it. Since the PWA does not provide an interface to change the permission setting, the custom menu cannot act like other menus. However, the custom menu uses the same data structure as the build-in menu. Therefore developers can directly modify the database to make menu secure.
The project server database uses two tables to store the menu information, MSP_WEB_SECURITY_MENUS and MSP_WEB_SECURITY_PAGES. MSP_WEB_SECURITY_MENUS saves the information of each menu, such as menu ID, menu name, indicator that menu is a top-menu or submenu, sequence of menu, the web page a menu link to, and etc. MSP_WEB_SECURITY_PAGES saves the information of each page, such as URL of page and etc. Among them, there is a property, WSEC_PAGE_ACT_ID, which is the feature action ID of the menu, defined in MSP_WEB_SECURITY_FEATURES_ACTIONS.
When a developer added a custom menu to PWA, the project server will add a record in MSP_WEB_SECURITY_MENUS table and a record in MSP_WEB_SECURITY_PAGES table. By default, the WSEC_PAGE_ACT_ID is set to 0 of custom page. To make the page secure, developer can modify the value with any valid feature action ID. For example, a developer adds a function page in admin menu. It can be set as the same permission as “Manage Views” menu in admin menu. To set so, developer can simply set the WSEC_PAGE_ACT_ID to 730. Then the new page will have the permission setting as manage views page, and only those user who can manage views, have permission to view the new custom page.
h=”0px” height=”0px” src=”http://c.live.com/c.gif?NC=31263&NA=1149&PI=73329&RF=&DI=3919&PS=85545&TP=netsleeper.spaces.live.com>1=NetSleeper”>
Popularity: 2% [?]
Synchronize All
31 March 2008Fortunately, PWA is an extendable framework, that we can extend PWA to support Synchronize multiple projects at a time. To extend the PWA for synchronizing all projects, we need to do:
a. Add a button in the toolbar.
b. Add a form with a hidden field in the page.
c. Add an event handler for the button.
2. Copy the SyncUpUsers.ASP page as SyncUpAllUsers.ASP, and modify it to send a request for all projects. The original page can send one request, we only need to add a loop in the code so it can send multiply requests.


Popularity: 1% [?]
Extend the OLAP cube for week in Time dimension
31 March 2008‘ Modify the time dimension to insert week of month.
Public Function ModifyTimeDimension(dsoDatabase As DSO.MDStore)
Dim dsoDimension As DSO.Dimension
Dim dsoLevelAll As DSO.DbLevel
Dim dsoLevel As DSO.Level
Dim strDimensionName As String
Dim strDimensionTableName As String
Dim dsoCube As DSO.MDStore
Dim DicCubes As Dictionary
Dim fSuccess As Boolean
Dim jcJoin As JoinClauseManager
Dim Condition As JoinClause
Dim nPos As Integer
fSuccess = False
On Error GoTo LblErrorHandler
strDimensionName = "Time"
strDimensionTableName = "MSP_CUBE_TIME_BY_DAY"
Set DicCubes = New Dictionary
Set jcJoin = New JoinClauseManager
If dsoDatabase.Dimensions.Find(strDimensionName) Then
For nPos = 1 To dsoDatabase.MDStores.Count
Set dsoCube = dsoDatabase.MDStores(nPos)
If dsoCube.Dimensions.Find(strDimensionName) And dsoCube.SubClassType = sbclsRegular Then
Call DicCubes.Add(dsoCube.Name, dsoCube.Name)
dsoCube.Dimensions.Remove (strDimensionName)
Call jcJoin.LoadJoinClause(dsoCube.JoinClause)
Call jcJoin.RemoveJoinCondition(TrimQuate(dsoCube.SourceTable), "TIME_ID", strDimensionTableName, "TIME_ID")
Call jcJoin.RemoveJoinCondition(TrimQuate(dsoCube.SourceTable), "TIME_DATE", strDimensionTableName, "TIME_DATE")
dsoCube.JoinClause = jcJoin.GetJoinClause
dsoCube.Update
dsoCube.Process processFull
End If
Next nPos
For nPos = 1 To dsoDatabase.MDStores.Count
Set dsoCube = dsoDatabase.MDStores(nPos)
If dsoCube.Dimensions.Find(strDimensionName) And dsoCube.SubClassType = sbclsVirtual Then
Call DicCubes.Add(dsoCube.Name, dsoCube.Name)
dsoCube.Dimensions.Remove (strDimensionName)
dsoCube.Update
dsoCube.Process processFull
End If
Next nPos
dsoDatabase.Dimensions.Remove (strDimensionName)
End If
Set dsoDimension = dsoDatabase.Dimensions.AddNew(strDimensionName, sbclsRegular)
Set dsoDimension.DataSource = dsoDatabase.DataSources(1)
dsoDimension.FromClause = """" & strDimensionTableName & """"
Set dsoLevelAll = dsoDimension.Parent.Parent.CreateObject(clsDatabaseLevel)
dsoLevelAll.Name = "All"
dsoLevelAll.IsAll = True
If dsoDimension.Levels.Count > 0 Then
Call dsoDimension.Levels.Add(dsoLevelAll, , 1)
Else
Call dsoDimension.Levels.Add(dsoLevelAll)
End If
dsoLevelAll.MemberKeyColumn = "All Years"
dsoLevelAll.LevelType = levAll
Set dsoLevel = dsoDimension.Levels.AddNew("Year", sbclsRegular)
dsoLevel.MemberKeyColumn = """" & strDimensionTableName & """.""" & "TIME_YEAR"""
dsoLevel.MemberNameColumn = """" & strDimensionTableName & """.""" & "TIME_YEAR"""
dsoLevel.LevelType = levTimeYears
dsoLevel.columnType = adSmallInt
Set dsoLevel = dsoDimension.Levels.AddNew("Quarter", sbclsRegular)
dsoLevel.MemberKeyColumn = """" & strDimensionTableName & """.""" & "TIME_QTR"""
dsoLevel.MemberNameColumn = """" & strDimensionTableName & """.""" & "TIME_QTR"""
dsoLevel.LevelType = levTimeQuarters
dsoLevel.columnType = adWChar
Set dsoLevel = dsoDimension.Levels.AddNew("Month", sbclsRegular)
dsoLevel.MemberKeyColumn = """" & strDimensionTableName & """.""" & "TIME_MONTH_OF_YEAR"""
dsoLevel.MemberNameColumn = """" & strDimensionTableName & """.""" & "TIME_MONTH"""
dsoLevel.LevelType = levTimeMonths
dsoLevel.columnType = adSmallInt
dsoLevel.Ordering = orderKey
Set dsoLevel = dsoDimension.Levels.AddNew("Week", sbclsRegular)
dsoLevel.MemberKeyColumn = """" & strDimensionTableName & """.""" & "TIME_WEEK_OF_YEAR"""
dsoLevel.MemberNameColumn = """" & strDimensionTableName & """.""" & "TIME_WEEK"""
dsoLevel.LevelType = levTimeWeeks
dsoLevel.columnType = adSmallInt
dsoLevel.Ordering = orderKey
Set dsoLevel = dsoDimension.Levels.AddNew("Days", sbclsRegular)
dsoLevel.MemberKeyColumn = """" & strDimensionTableName & """.""" & "TIME_DAY_OF_WEEK"""
dsoLevel.MemberNameColumn = """" & strDimensionTableName & """.""" & "TIME_DAY_OF_MONTH"""
dsoLevel.LevelType = levTimeDays
dsoLevel.columnType = adSmallInt
dsoLevel.Ordering = orderKey
‘Update and process the dimension.
dsoDimension.Update
dsoDimension.Process (processFull)
For Each dsoCube In dsoDatabase.MDStores
If DicCubes.Exists(dsoCube.Name) And dsoCube.SubClassType = sbclsRegular Then
dsoCube.Dimensions.AddNew (strDimensionName)
Call jcJoin.LoadJoinClause(dsoCube.JoinClause)
Call jcJoin.AddJoinCondition(TrimQuate(dsoCube.SourceTable), "TIME_ID", strDimensionTableName, "TIME_ID")
Call jcJoin.AddJoinCondition(TrimQuate(dsoCube.SourceTable), "TIME_DATE", strDimensionTableName, "TIME_DATE")
dsoCube.JoinClause = jcJoin.GetJoinClause
dsoCube.Update
dsoCube.Process (processFull)
End If
Next dsoCube
For Each dsoCube In dsoDatabase.MDStores
If DicCubes.Exists(dsoCube.Name) And dsoCube.SubClassType = sbclsVirtual Then
dsoCube.Dimensions.AddNew (strDimensionName)
dsoCube.Update
dsoCube.Process (processFull)
End If
Next dsoCube
fSuccess = True
LblErrorHandler:
Set dsoDimension = Nothing
Set dsoLevelAll = Nothing
Set dsoLevel = Nothing
Set dsoCube = Nothing
If (Not fSuccess) Then
Call TraceAndRaise("Error in ModifyTimeDimension.")
End If
End Function


Popularity: 1% [?]
Close a project in EPM
31 March 2008One way to avoid this is to remove the project from EPM system. However, we may need the project data for statistic. There is one way we can keep the project in EPM. Portfolio manager can view the data in OLAP cube, but the project manager cannot modify it, and team member cannot put any hours against project. To do so, we need:
2. Open every project in Project Professional set the value of the custom outline code and republishes it.
3. Create a security, Closed Projects, which disables projects in the list for opening and viewing.
4. Open the finished projects in Project Professional to change the resource from committed to purposed.
5. Put those finished project in the Closed Projects.
2. Create a SQL agent that execute periodically, which close all projects with closed status.
3. Create a SQL trigger that execute immediately when project manager saves the project. If the project manager set the project status to be closed, then the trigger will close the project.


Popularity: 1% [?]
Generate .NET Code by using Olymars
31 March 2008<*
// ----------------------------------------------------------------------------------------------------
// GetName function for element: 'Data Access Layer Interface'
// ----------------------------------------------------------------------------------------------------
public string IDataAccessLayer_GetName() {
// Choose whatever name you wish for this object
return (@"IDataAccessLayer.cs");
}
// ----------------------------------------------------------------------------------------------------
// Creation method for element: 'Data Access Layer Interface'
// ----------------------------------------------------------------------------------------------------
public void IDataAccessLayer() {
try {
Source.CurrentTemplate.ExecutionStatusMessage = "Code Generation succeed. ";
Response.WriteLine("// File Name: " + IDataAccessLayer_GetName());
Response.WriteLine("// Code Generated By: " + DynamicParameters.DeveloperAlias);
Response.WriteLine("// Code Generated On: " + System.DateTime.Now.ToShortDateString());
Response.WriteLine();
Response.WriteLine("using System;");
Response.WriteLine("using System.Data;");
Response.WriteLine();
Response.WriteLine("namespace " + DynamicParameters.CompanyName + ".Data");
Response.WriteLine("{");
Response.WriteLine("tpublic interface IDataAccessLayer");
Response.WriteLine("t{");
Response.WriteLine("ttstring ConnectionString {get;}");
Response.WriteLine("ttbool WithTransaction {get;}");
StoredProcedureCollection Procedures = Source.SelectedStoredProcedures;
foreach (StoredProcedure SP in Procedures)
{
string ReturnType;
if (SP.ReturnsData == true)
{
if (SP.Resultsets.Count > 1)
ReturnType = "DataSet";
else
ReturnType = "DataTable";
}
else
{
ReturnType = "void";
}
ParameterCollection Parameters = SP.Parameters;
string ParameterString = "";
foreach (Parameter P in Parameters)
{
string Direction = "";
if (P.Direction == ParameterDirection.Output)
{
Direction = "out ";
}
else if (P.Direction == ParameterDirection.ReturnValue)
{
continue;
}
if (ParameterString != "")
{
ParameterString += ",";
}
string DotNetName = P.Name;
if (DotNetName.Substring(0,1) == "@")
{
DotNetName = DotNetName.Remove(0,1);
}
ParameterString += Direction + P.DotNetType.CommonTypeSystemEquivalent + " " + DotNetName;
}
Response.WriteLine("tt" + ReturnType + " " + SP.Name.Replace(" ", "_") + "(" + ParameterString + ");");
}
Response.WriteLine("t}");
Response.WriteLine("}");
}
catch (System.Exception GlobalException) {
Source.CurrentTemplate.ExecutionStatusCode = GenerationStatus.Error;
Source.CurrentTemplate.ExecutionStatusMessage = GlobalException.Message;
Response.WriteLine();
Response.WriteLine("*************************");
Response.WriteLine(" AN EXCEPTION WAS THROWN");
Response.WriteLine("*************************");
Response.WriteLine(GlobalException.Message);
Response.WriteLine();
Response.WriteLine("****************");
Response.WriteLine(" FULL EXCEPTION");
Response.WriteLine("****************");
Response.WriteLine(GlobalException.ToString());
if (Source.DesignMode) {
System.Windows.Forms.MessageBox.Show(GlobalException.ToString(), "An error has occured", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
else {
throw;
}
}
}
// ----------------------------------------------------------------------------------------------------
// GetName function for element: 'Data Access Layer Basic Implementation'
// ----------------------------------------------------------------------------------------------------
public string DataAccessLayer_GetName() {
// Choose whatever name you wish for this object
return (@"DataAccessLayer.cs");
}
// ----------------------------------------------------------------------------------------------------
// Creation method for element: 'Data Access Layer Basic Implementation'
// ----------------------------------------------------------------------------------------------------
public void DataAccessLayer() {
try {
Source.CurrentTemplate.ExecutionStatusMessage = "Code Generation succeed. ";
Response.WriteLine("// File Name: " + DataAccessLayer_GetName());
Response.WriteLine("// Code Generated By: " + DynamicParameters.DeveloperAlias);
Response.WriteLine("// Code Generated On: " + System.DateTime.Now.ToShortDateString());
Response.WriteLine();
Response.WriteLine("using System;");
Response.WriteLine("using System.Data;");
Response.WriteLine("using System.Data.SqlClient;");
Response.WriteLine("using Microsoft.ApplicationBlocks.Data;");
Response.WriteLine("using " + DynamicParameters.CompanyName + ".Configure;");
Response.WriteLine();
Response.WriteLine("namespace " + DynamicParameters.CompanyName + ".Data");
Response.WriteLine("{");
Response.WriteLine("tpublic class DataAccessLayer : IDataAccessLayer");
Response.WriteLine("t{");
Response.WriteLine("tt// connection string of SQL database");
Response.WriteLine("ttprivate string _ConnectionString = "";");
Response.WriteLine("tt// transaction option");
Response.WriteLine("ttprivate bool _WithTransaction = false;");
Response.WriteLine("tt// connection");
Response.WriteLine("ttprivate SqlConnection _Connection = null;");
Response.WriteLine("tt// transaction");
Response.WriteLine("ttprivate SqlTransaction _Transaction = null;");
Response.WriteLine();
Response.WriteLine("tt// get connection string");
Response.WriteLine("ttpublic string ConnectionString");
Response.WriteLine("tt{");
Response.WriteLine("tttget {return _ConnectionString;}");
Response.WriteLine("tt}");
Response.WriteLine();
Response.WriteLine("tt// get or set transaction option");
Response.WriteLine("ttpublic bool WithTransaction");
Response.WriteLine("tt{");
Response.WriteLine("tttget {return _WithTransaction;}");
Response.WriteLine("tt}");
Response.WriteLine();
Response.WriteLine("tt// construction with connection string");
Response.WriteLine("ttpublic DataAccessLayer(string Connection)");
Response.WriteLine("tt{");
Response.WriteLine("ttt_ConnectionString = Connection;");
Response.WriteLine("tt}");
Response.WriteLine();
Response.WriteLine("tt// construction with configure");
Response.WriteLine("ttpublic DataAccessLayer(IConfigure Config)");
Response.WriteLine("tt{");
Response.WriteLine("ttt_ConnectionString = Config.GetConnectionString();");
Response.WriteLine("tt}");
Response.WriteLine();
Response.WriteLine("tt// construction with connection, caller will manage the connection");
Response.WriteLine("ttpublic DataAccessLayer(SqlConnection Connection)");
Response.WriteLine("tt{");
Response.WriteLine("tttif (Connection == null)");
Response.WriteLine("ttttthrow new Exception("Connection cannot be null.");");
Response.WriteLine("ttt_Connection = Connection;");
Response.WriteLine("tt}");
Response.WriteLine();
Response.WriteLine("tt// construction with transaction, caller will manage the connection and transaction");
Response.WriteLine("ttpublic DataAccessLayer(SqlTransaction Transaction)");
Response.WriteLine("tt{");
Response.WriteLine("tttif (Transaction == null)");
Response.WriteLine("ttttthrow new Exception("Transaction cannot be null.");");
Response.WriteLine("ttt_Connection = Transaction.Connection;");
Response.WriteLine("ttt_ConnectionString = _Connection.ConnectionString;");
Response.WriteLine("ttt_Transaction = Transaction;");
Response.WriteLine("ttt_WithTransaction = true;");
Response.WriteLine("tt}");
Response.WriteLine();
StoredProcedureCollection Procedures = Source.SelectedStoredProcedures;
foreach (StoredProcedure SP in Procedures)
{
string ReturnType;
if (SP.ReturnsData == true)
{
if (SP.Resultsets.Count > 1)
ReturnType = "DataSet";
else
ReturnType = "DataTable";
}
else
{
ReturnType = "void";
}
ParameterCollection Parameters = SP.Parameters;
string ParameterString = "";
string SqlDBParameterString = "";
int TrueParameter = 0;
foreach (Parameter P in Parameters)
{
string Direction = "";
if (P.Direction == ParameterDirection.Output)
{
Direction = "out ";
}
else if (P.Direction == ParameterDirection.ReturnValue)
{
continue;
}
if (ParameterString != "")
{
ParameterString += ",";
SqlDBParameterString += ",";
}
string DotNetName = P.Name;
if (DotNetName.Substring(0,1) == "@")
{
DotNetName = DotNetName.Remove(0,1);
}
ParameterString += Direction + P.DotNetType.CommonTypeSystemEquivalent + " " + DotNetName;
SqlDBParameterString += P.Name + " " + P.SqlFullType;
TrueParameter ++;
}
Response.WriteLine("tt// Execute stored procedure:");
Response.WriteLine("tt// " + SP.Name + "(" + SqlDBParameterString + ")");
Response.WriteLine("ttpublic " + ReturnType + " " + SP.Name.Replace(" ", "_") + "(" + ParameterString + ")");
Response.WriteLine("tt{");
if (SP.ReturnsData == true)
Response.WriteLine("tttDataSet ds = null;");
Response.WriteLine();
Response.WriteLine("ttttry");
Response.WriteLine("ttt{");
if (TrueParameter > 0)
{
Response.WriteLine("ttttSqlParameter[] Params = new SqlParameter[" + TrueParameter + "];");
Response.WriteLine();
int i = 0;
foreach (Parameter P in Parameters)
{
if (P.Direction == ParameterDirection.ReturnValue)
{
continue;
}
string DotNetName = P.Name;
if (DotNetName.Substring(0,1) == "@")
{
DotNetName = DotNetName.Remove(0,1);
}
Response.WriteLine("ttttParams[" + i + "] = new SqlParameter("" + P.Name+ "", "+ P.DotNetType.FullSqlDbTypeEquivalent + ", " + P.Length+ ");");
Response.WriteLine("ttttParams[" + i + "].Value = " + DotNetName +";");
if (P.Direction == ParameterDirection.Output)
Response.WriteLine("ttttParams[" + i + "].Direction = ParameterDirection.Output;");
Response.WriteLine();
i++;
}
}
string MethodName = "";
string ReturnDataSet = "";
if (SP.ReturnsData == true)
{
MethodName = "ExecuteDataset";
ReturnDataSet = "ds = ";
}
else
{
MethodName = "ExecuteNoQuery";
}
string ParamString = "";
if (TrueParameter > 0)
{
ParamString = ", Params";
}
Response.WriteLine("ttttif (_Transaction != null)");
Response.WriteLine("tttt{");
Response.WriteLine("ttttt" + ReturnDataSet+ "SqlHelper." + MethodName + "(_Transaction, CommandType.StoredProcedure, "" + SP.Name + """ + ParamString + ");");
Response.WriteLine("tttt}");
Response.WriteLine("ttttelse if (_Connection != null)");
Response.WriteLine("tttt{");
Response.WriteLine("ttttt" + ReturnDataSet+ "SqlHelper." + MethodName + "(_Connection, CommandType.StoredProcedure, "" + SP.Name + """ + ParamString + ");");
Response.WriteLine("tttt}");
Response.WriteLine("ttttelse");
Response.WriteLine("tttt{");
Response.WriteLine("ttttt" + ReturnDataSet+ "SqlHelper." + MethodName + "(_ConnectionString, CommandType.StoredProcedure, "" + SP.Name + """ + ParamString + ");");
Response.WriteLine("tttt}");
if (SP.ReturnsData == true)
{
if (SP.Resultsets.Count > 1)
Response.WriteLine("ttttreturn ds;");
else
Response.WriteLine("ttttreturn ds.Tables[0];");
}
else
Response.WriteLine("ttttreturn;");
Response.WriteLine("ttt}");
Response.WriteLine("tttcatch(Exception ex)");
Response.WriteLine("ttt{");
Response.WriteLine("ttttthrow new Exception("Cannot execute the stored procedure.", ex);");
Response.WriteLine("ttt}");
Response.WriteLine("tt}");
Response.WriteLine();
}
Response.WriteLine("t}");
Response.WriteLine("}");
}
catch (System.Exception GlobalException) {
Source.CurrentTemplate.ExecutionStatusCode = GenerationStatus.Error;
Source.CurrentTemplate.ExecutionStatusMessage = GlobalException.Message;
Response.WriteLine();
Response.WriteLine("*************************");
Response.WriteLine(" AN EXCEPTION WAS THROWN");
Response.WriteLine("*************************");
Response.WriteLine(GlobalException.Message);
Response.WriteLine();
Response.WriteLine("****************");
Response.WriteLine(" FULL EXCEPTION");
Response.WriteLine("****************");
Response.WriteLine(GlobalException.ToString());
if (Source.DesignMode) {
System.Windows.Forms.MessageBox.Show(GlobalException.ToString(), "An error has occured", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
else {
throw;
}
}
}
// ----------------------------------------------------------------------------------------------------
// GetName function for element: 'Configuration Interface'
// ----------------------------------------------------------------------------------------------------
public string IConfigure_GetName() {
// Choose whatever name you wish for this object
return (@"IConfigure.cs");
}
// ----------------------------------------------------------------------------------------------------
// Creation method for element: 'Configuration Interface'
// ----------------------------------------------------------------------------------------------------
public void IConfigure() {
try {
Source.CurrentTemplate.ExecutionStatusMessage = "Code Generated Succeed.";
Response.WriteLine("// File Name: " + IConfigure_GetName());
Response.WriteLine("// Code Generated By: " + DynamicParameters.DeveloperAlias);
Response.WriteLine("// Code Generated On: " + System.DateTime.Now.ToShortDateString());
Response.WriteLine();
Response.WriteLine("using System;");
Response.WriteLine();
Response.WriteLine("namespace " + DynamicParameters.CompanyName + ".Configure");
Response.WriteLine("{");
Response.WriteLine("tpublic interface IConfigure");
Response.WriteLine("t{");
Response.WriteLine("ttstring GetConnectionString();");
Response.WriteLine("t}");
Response.WriteLine("}");
}
catch (System.Exception GlobalException) {
Source.CurrentTemplate.ExecutionStatusCode = GenerationStatus.Error;
Source.CurrentTemplate.ExecutionStatusMessage = GlobalException.Message;
Response.WriteLine();
Response.WriteLine("*************************");
Response.WriteLine(" AN EXCEPTION WAS THROWN");
Response.WriteLine("*************************");
Response.WriteLine(GlobalException.Message);
Response.WriteLine();
Response.WriteLine("****************");
Response.WriteLine(" FULL EXCEPTION");
Response.WriteLine("****************");
Response.WriteLine(GlobalException.ToString());
if (Source.DesignMode) {
System.Windows.Forms.MessageBox.Show(GlobalException.ToString(), "An error has occured", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
else {
throw;
}
}
}
*>


Popularity: 1% [?]
Customize Issue on Homepage of PWA
31 March 2008

Popularity: 1% [?]
PDS with multiple hosted sites - Error 405 method not allowed
31 March 2008I am able to logon, but when i try to execute "ProjectsStatus" I get the error "… 405 method not allowed". The same application works fine with the "Main" Project Web Access.
2. Navigate into IIS
3. Right click on the original /projectserver virtual directory created during installation.
4. Click on Properties for the virtual directory
5. Click on the Configuration…button
6. Scroll all the way to the bottom and take note of the path of the "wsdl" extension
This should be something like "c:\Program Files\Common Files\MSSOAP\BINARIES\SOAPIS30.dll"
7. Click cancel twice to return to the main IIS screen
Now configure the new virtual directories:
1. Right click on the new virtual directory created using EditSite
2. Click on Properties for the new virtual directory
4. Click on the Configuration… button
5. Click Add…
6. Enter the path from step #6 above (with the quotes)
7. Enter GET, POST in the Limit To box
8. Enter wsdl in the Extension box
9. Click OK Twice.


Popularity: 1% [?]
Project Server 2007 Active Directory Synchronization Error
31 March 2008I have experienced Project Server 2007 Active Directory Synchronization failure on client. As the result, Active Directory cannot be synchronized and even worse, the user/resource edit page shows error when you tried to edit a synchronized user/resource. It may potentially create corrupted assignments in project plan.
In the event log on project server, there are errors in application category.
Error Message:
Standard Information:PSI Entry Point:
Project User: IHESS\sdai
Correlation Id: 837bfd5f-9502-4e09-a193-2af20c8392b0
PWA Site URL: http://hacssia021/PWA
SSP Name: SharedServices_MOPS
PSError: Success (0)
A general exception occurred during communication with Active Directory. Context: SyncGroup. Additional Information: An exception occurred while syncing a project server group with active directory. GroupName: ‘%s’. PWA Group Guid: ‘%s’ Exception: ‘%s’.. Exception Info: EPIS Team Members
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
There also are errors in system category:
Error Message:
The application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID
{61738644-F196-11D0-9953-00C04FD919C1}
to the user IHESS\SRV_PROJSVR_DB SID (S-1-5-21-789336058-2052111302-839522115-106752). This security permission can be modified using the Component Services administrative tool.
From the error message, I decided to change the DCOM configuration first. By searching the registry, I found that (S-1-5-21-789336058-2052111302-839522115-106752) is the ID of IIS WAMREG Admin Service component.
Open the Component Services on project server and select “Component Services” – “DCOM Config”.
Right click on component and select “Property”. Then select “Security”.
Select “Edit” button in “Launch and Activation Permissions”, then add the SharePoint farm service user in and give it “Local Launch” and “Local Activation” permissions.
After done, I tried to synchronize the users again. However, I still got errors. When I check the event log, the errors are different.
Error Message:
Standard Information:PSI Entry Point:
Project User: IHESS\sdai
Correlation Id: 837bfd5f-9502-4e09-a193-2af20c8392b0
PWA Site URL: http://hacssia021/PWA
SSP Name: SharedServices_MOPS
PSError: Success (0)
Changes were detected for a resource during Project Server Active Directory Synchronization. However, the changes could not be applied because the resource could not be checked out. The checkout failed because the resource is checked out to another user. Resource GUID: 67581218-21cd-4f5e-9ee0-6ad4f0e25799
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
It shows some resource has been checked out. But in force-in resource page, I did not find any check-out resources. Actually, those resources are checked-out by AD synchronization process.
I used “SQL Server Management Studio” to open the Project Server 2007 published database.
Run the script to check back in the resources
UPDATE MSP_RESOURCES
SET RES_CHECKOUTBY = NULL
WHERE RES_UID in (
SELECT
RES_UID
FROM MSP_Resources
WHERE RES_CHECKOUTBY = ‘00000000-0000-0000-0000-000000000000′)
If you have corrupted assignments, you may use the script to find out:
SELECT MSP_PROJECTS.PROJ_NAME,
MSP_ASSIGNMENTS_SAVED.TASK_NAME,
MSP_RESOURCES.RES_NAME,
MSP_ASSIGNMENTS_SAVED.ASSN_UID,
MSP_ASSIGNMENTS_SAVED.PROJ_UID,
MSP_ASSIGNMENTS_SAVED.TASK_UID,
MSP_ASSIGNMENTS_SAVED.RES_UID
FROM MSP_ASSIGNMENTS_SAVED INNER JOIN
MSP_PROJECTS ON MSP_ASSIGNMENTS_SAVED.PROJ_UID =
MSP_PROJECTS.PROJ_UID INNER JOIN
MSP_RESOURCES ON MSP_ASSIGNMENTS_SAVED.RES_UID =
MSP_RESOURCES.RES_UID
WHERE (NOT EXISTS
(SELECT TASK_UID
FROM MSP_TASKS_SAVED
WHERE (TASK_UID = MSP_ASSIGNMENTS_SAVED.TASK_UID)))
Reference:
http://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=288068&SiteID=235
x” height=”1px” border=”0″ alt=”">
Popularity: 5% [?]
A Better Way to Create Indicator
31 March 2008Sometimes, you need to create a very complex formula for indicator. It’s very hard to understand and maintain.
For example, client wants to show schedule indicator green when duration variance within 10% of baseline duration, 11%~20% for yellow and above 20% shows red.
Sample formula:
SWITCH([Finish Variance]=0,"On Target",[Finish Variance]<0,CSTR(CINT([Finish Variance]*(-100)/[Baseline Duration]))+"% Ahead Of Schedule", true,CSTR(CINT([Finish Variance]*100/[Baseline Duration]))+"% Over Schedule")
Then when you set graphic indicator, use "Is Less Than" or "Is Greater Than". You can set as
Is Less Than 11 Green
Is Less Than 21 Yellow
Any Value Red
Project Professional is smarter enough to compare the percent as number. You can event put percent in the middle of the data, such as "Task 10% Behind Schedule".
.com/CollectionWebService/c.gif?cid=3272762737651157669&page=RSS%3a+A+Better+Way+to+Create+Indicator&referrer=” width=”1px” height=”1px” border=”0″ alt=”">
Popularity: 1% [?]
How to setup analysis service with project server 2007
31 March 2008Project Server 2007 can work with SQLServer 2000 and SQLServer 2005. To setup OLAP cube for project server 2007, here is some references and some tips:
1. For Analysis Service 2000
You can just follow the microsoft MSDN document: http://technet2.microsoft.com/Office/en-us/library/5d90076f-bbcc-48c1-a569-bd236862d47c1033.mspx?mfr=true
2. For Analysis Service 2005
Here is the microsoft MSDN document:
It is working if you install analysis service on the same computer of project server. However, it does not work if you separate those two, which is the most case.
You will get the following error:
Failed to build the OLAP cubes. Error: Analysis Services session failed with the following error: Failed to delete the Olap database: PWA_AnalysisServices. Error: Your permissions on the server computer do not allow you to administer this Analysis server.
The reason is because the SSP account does not have permission to manage analysis service remotely by using DSO. To enable remote administer analysis service through DSO, you will need to create shared folder for analysis service: MSOLAPRepository$. This is just for back compatible to DSO. Analysis service 2000 will create it during the installation. However, since analysis service 2005 no longer need it. It will not create the shared folder. Then you have to do it yourself. The folder will only be used for remote administer. So if you install analysis service on the same box of project server, you don’t need it.
Use this two steps with the MSDN document, you can setup OLAP cube.
Create the shared folder
1. In Windows Explorer, browse to the folder containing the Analysis Services installation. By default, it is located at:
C:\Program Files\Microsoft SQL Server\MSSQL.2\OLAP
2. In this folder, create a new folder and name it DSO9.
3. Right-click the DSO9 folder, and choose Sharing and Security.
4. On the Sharing and Security page, in the Sharing tab, select Share this folder. In the Share Name box, type MSOLAPRepository$ as the share name for the folder.
5. On the Sharing tab, in the Group or user names list, click Add. On the Select User, Computers, or Groups page, add the SQLServer2005MSOLAPUser$<Servername>$MSSQLServer account from the local computer. Click OK.
6. In the Group or user names list, select the SQLServer2005MSOLAPUser$<Servername>$MSSQLServer account. In the Permissions for SQLServer2005MSOLAPUser$<Servername>$MSSQLServer box, select Allow next to Full Control. Click OK.
7. On the Security tab, in the Group or user names list, select SQLServer2005MSOLAPUser$SERVERNAME$MSSQLSERVER. Select the Allow check box next to the Full Control item in the Permissions list, and then click OK.
8. On the New Folder Properties page, click OK.
Configure Analysis Services For DSO
1. In SQL Server 2005, start SQL Server Management Studio. On the Connect to Server window, select Analysis Services, and then click Connect.
2. In SQL Server Management Studio, in the Object Explorer pane, right-click the Analysis Services name, and then choose Properties.
3. On the Analysis Services Properties page, in the Select a page section select General. Select Show Advanced (All) Properties.
4. Select DSO\RepositoryConnectionString from the Name list.
a. Select the corresponding value for the string in the Value column, and then click the box that appears to the right of the value to display the Connection Manager page.
b. On the Connection Manager page, in the Provider list, select Native OLE DB\SQL Native Client.
c. In the Server Name list, select the server on which the repository database is located.
d. In the Logon to the server field, enter the account information to log onto the server.
e. In the Connect to database section, select Select or enter a database name and enter the name of the repository file.
f. Click OK.
5. Select DSO\RemoteRepositoryConnectionString from the Name list.
a. Select the corresponding value for the string in the Value column, and then click the box that appears to the right of the value to display the Connection Manager page.
b. On the Connection Manager page, in the Provider list, select Native OLE DB\SQL Native Client.
c. In the Server Name list, select the server on which the repository database is located.
d. In the Logon to the server field, enter the account information to log onto the server.
e. In the Connect to database section, select Select or enter a database name and enter the name of the repository file.
f. Click OK.
6. Select DSO\LocksDirectory from the Name list, enter the local path of the shared folder. For example: E:\MSSQL.3\OLAP\DSO9\
7. Select DSO\RemoteLocksDirectory from the Name list, enter the UNC name of the shared folder. For example: \\HACSSDB028\MSOLAPRepository$\
8. On the Analysis Server Properties page, click OK.
NOTES:
1. When you configure analysis service 2005, MSDN gaves you two choices: creating Access MDB file or SQLServer 2005 database. You can do either one of them. However, you cannot migrate from MDB to SQLServer 2005.
2. To view project server OLAP view in PWA, the client computer (with Windows XP. Vista already has those component) has to install the following components:
- Microsoft Core XML Services (MSXML) 6.0
- Microsoft SQL Server 2005 Analysis Services 9.0 OLE DB Provider
style=”font-size:8pt;color:black;font-family:’Tahoma’,’sans-serif’”>You can find them in SQLServer 2005 feature pack: http://www.microsoft.com/downloads/details.aspx?FamilyID=50b97994-8453-4998-8226-fa42ec403d17&DisplayLang=en
TP=netsleeper.spaces.live.com>1=NetSleeper”>
Popularity: 12% [?]

