Maintaining Consistent Primavera P6 Client Configuration Files Across Multiple Users Using PowerShell – Part 2

PowerShell 5.0 icon

A refactored and updated version of the P6config.cmd script below allows for multiple profiles, both Local and Roaming. 

 

@echo off
setlocal enabledelayedexpansion
for %%A in (Local Roaming) do (
	set profpath=C:\Users\%username%\AppData\%%A\Oracle\Primavera P6\P6 Professional\18.8.0
	if exist !profpath! goto subroutine
	rem echo !profpath! does not exist.
	:return
	rem echo return
)
goto eof

:subroutine
copy "C:\Program Files\Oracle\Primavera P6\P6 Professional\18.8.0\Data\PrmBootStrapV2.xml" "!profpath!" /y 
powershell (Get-ChildItem '!profpath!\PrmBootStrapV2.xml').CreationTime = $(Get-Date) 
powershell (Get-ChildItem '!profpath!\PrmBootStrapV2.xml').LastAccessTime = $(Get-Date) 
powershell (Get-ChildItem '!profpath!\PrmBootStrapV2.xml').LastWritetime = $(Get-Date)
goto return

:eof
endlocal

Maintaining Consistent Primavera P6 Client Configuration Files Across Multiple Users Using PowerShell

PowerShell 5.0 icon

In setting up Oracle’s Primavera P6 EPPM version 18.8, I discovered that users who connected to the client via Citrix were not picking up changes that were made to the default configuration file.

Normally, if that file is changed and is newer than the user’s own file, it will be overwritten with the default. In this case, users were not seeing the newer file, and when I looked, they often had no local profile on the Citrix server.

As it turned out, the user profiles were set up as roaming profiles that were deleted upon logoff. This wouldn’t necessarily be a problem, except that the their copy of the config file was always listed as newer than the default.

A workaround was to be logged into the server via RDP, and to have the user log in via Citrix. At that time, the config file could be manually copied, overwriting the user’s old file, and then (most importantly!) manually opening and saving the user’s file, so that it would remain in place in their roaming profile even after logoff.

This is clearly not a feasible practice in a production environment. However, an automated script that does this could solve this problem! Save the following as a .cmd file and make sure it is run prior to running the P6 client executable.

copy "C:\Program Files\Oracle\Primavera P6\P6 Professional\18.8.0\Data\PrmBootStrapV2.xml" "C:\Users\%username%\AppData\Roaming\Oracle\Primavera P6\P6 Professional\18.8.0" /y

powershell (Get-ChildItem 'C:\Users\%username%\AppData\Roaming\Oracle\Primavera P6\P6 Professional\18.8.0\PrmBootStrapV2.xml').CreationTime = $(Get-Date)
powershell (Get-ChildItem 'C:\Users\%username%\AppData\Roaming\Oracle\Primavera P6\P6 Professional\18.8.0\PrmBootStrapV2.xml').LastAccessTime = $(Get-Date)
powershell (Get-ChildItem 'C:\Users\%username%\AppData\Roaming\Oracle\Primavera P6\P6 Professional\18.8.0\PrmBootStrapV2.xml').LastWritetime = $(Get-Date)

As long as the Citrix server has PowerShell installed, this should work.

Update: Part 2 has a script that will allow for both Local and Roaming profiles.

Changing the Authentication Mode in Oracle Primavera P6 EPPM Using SQL

Oracle Primavera P6 EPPM

I am currently in the process of setting up an Oracle Primavera P6 EPPM 18.8 environment. The operating system on the application and Web server is Windows Server 2012 R2, the middleware is Oracle WebLogic 12c, and Oracle Database 12c for the RDBMS.

This is the first time I’ve ever set up P6 from scratch, and I’m doing it without any assistance from Oracle, other than their documentation.

I’ve learned quite a lot in my adventure so far. One thing that I learned is that you REALLY don’t want to turn on LDAP Authentication everywhere until you’re sure it’s working.

(Relevant documentation: Configuring LDAP Settings in the Primavera P6 Administrator)

In the P6 Administration website, there are two places to change the type of authentication used: NATIVE, LDAP, and WebSSO. The Authentication tab:

P6 Administration screen - Authentication tab

And the authentication section on the database instance itself:

P6 Administration screen - Authentication section on DB instance

If both are set to “LDAP” (and presumably “WebSSO” as well) when things aren’t yet set up properly, you’ll get this lovely error: “Primavera P6 was configured to use a different authentication mode than the database selected”.

Google suggests that you read this Oracle doc to fix the problem. However, this problem is only fixed with this solution if only the DB instance setting is “LDAP”. If both are set that way, this solution does not fix the problem – though it should still be run so as to fix the setting on the DB instance page.

After poking around in the database, I discovered that the offending configuration setting was stored in a BLOB in the ADMIN_CONFIG table. Unfortunately, editing this BLOB is not easy without some assistance. Fortunately, I found an article on StackOverflow that had functions for converting a BLOB into a CLOB, at which point the REPLACE function could be used. Then convert the CLOB back to a BLOB, and UPDATE the database table.

First, create the two conversion functions:

CREATE OR REPLACE FUNCTION convert_to_clob(l_blob BLOB) RETURN CLOB IS
      l_clob         CLOB;
      l_dest_offset  NUMBER := 1;
      l_src_offset   NUMBER := 1;
      l_lang_context NUMBER := dbms_lob.default_lang_ctx;
      l_warning      NUMBER;
   BEGIN
      dbms_lob.createtemporary(l_clob, TRUE);
      dbms_lob.converttoclob(dest_lob     => l_clob,
                             src_blob     => l_blob,
                             amount       => dbms_lob.lobmaxsize,
                             dest_offset  => l_dest_offset,
                             src_offset   => l_src_offset,
                             blob_csid    => nls_charset_id('AL32UTF8'),
                             lang_context => l_lang_context,
                             warning      => l_warning);
      RETURN l_clob;
   END convert_to_clob;
   /
CREATE OR REPLACE FUNCTION convert_to_blob(l_clob CLOB) RETURN BLOB IS
      l_blob         BLOB;
      l_dest_offset  NUMBER := 1;
      l_src_offset   NUMBER := 1;
      l_lang_context NUMBER := dbms_lob.default_lang_ctx;
      l_warning      NUMBER;
   BEGIN
      dbms_lob.createtemporary(l_blob, TRUE);
      dbms_lob.converttoblob(dest_lob     => l_blob,
                             src_clob     => l_clob,
                             amount       => dbms_lob.lobmaxsize,
                             dest_offset  => l_dest_offset,
                             src_offset   => l_src_offset,
                             blob_csid    => nls_charset_id('AL32UTF8'),
                             lang_context => l_lang_context,
                             warning      => l_warning);
      RETURN l_blob;
   END convert_to_blob;
   /

Then run an UPDATE statement, something like this, changing the CONFIG_NAME appropriately:

UPDATE ADMIN_CONFIG
     SET CONFIG_DATA = convert_to_blob(
                          REPLACE(convert_to_clob(CONFIG_DATA),
                                 '<mode desc="SET_AUTHENTICATION_MODE" o1="NATIVE" o2="WebSSO" o3="LDAP" type="javax.swing.JComboBox">LDAP</mode>',
                                 '<mode desc="SET_AUTHENTICATION_MODE" o1="NATIVE" o2="WebSSO" o3="LDAP" type="javax.swing.JComboBox">NATIVE</mode>')
                          )
   WHERE CONFIG_NAME = 'myprimavera.bre.YourConfigName';
COMMIT;

After running this script and restarting the application servers, you should once again be back in NATIVE mode and able to get back into P6 to see what went wrong, and no longer crying over the website you thought you had bricked just a few minutes prior.

Primavera P6 Session Hung on Oracle Database

Oracle Primavera P6 EPPM

Occasionally a user will close a P6 application and the user’s session does not just go away. The easiest thing I’ve found is to check to see if there are hung sessions in the usession table (in Oracle – other database types may use a different name). This is the type of error you might see:

Primavera P6 hung user session

Look for hung sessions by running the following query, plugging the actual username into ‘Username’:

SELECT * FROM usession WHERE user_id = (
SELECT user_id FROM users WHERE user_name = 'Username');

If any are present, run this query:

DELETE FROM usession WHERE user_id = (
SELECT user_id FROM users WHERE user_name = 'Username');
COMMIT;

The user should again be able to log into P6 at this point.