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.
	rem echo return
goto eof

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


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.

Adding Lines to the Beginning and Ending of Files Using PowerShell

Stack Overflow PowerShell question

In dealing with an application with which I had little familiarity, I discovered that troubleshooting an app (in this case developed using ColdFusion) where many of the source code files are “included” dynamically can be difficult – especially when JavaScript scripts are combined that have functions with identical names.

Because so many of the functions were not only identically named, but also similarly constructed, I decided to add commented identifiers to the beginning and ending of each JS file.

This could be done in a number of ways, but given my recent forays into using PowerShell scripts, I chose that route again.

Stack Overflow PowerShell question
Stack Overflow and Google – developers’ best friends.

After some Googling and a brief visit to Stack Overflow, I learned about the two PowerShell “cmdlets” that would be most useful here: Set-Content and Add-Content.

The text of the script is below. What this script does is recursively search through the file path in line 1, choosing only files that have the extension after the filter switch (.js in this case). Looping through these file names, each file is read into memory (using Get-Content). The root of the file is then removed with the first replace command, and for aesthetics, I chose to change backslashes into forward slashes with the second one (lines 4 and 5). Notice that backslashes must be escaped by using an extra backslash, whereas forward slashes are not escaped. Also, in case you’re wondering, the backtick-n (`n) is the newline character in PowerShell. The Set-Content cmdlet is used to add the “$newline” string and then the original file content. The Add-Content cmdlet is then used to add the line marking the end of the file.

Get-ChildItem "C:\Folder\Subfolder" -recurse -Filter *.js | `
    $content = Get-Content $_.FullName
    $fullname = $_.FullName -replace "C:\\Folder\\Subfolder", ""
    $fullname = $fullname -replace "\\", "/"

    $newline = "// file: " + $fullname + " `n"       
    Set-Content $_.FullName -value $newline, $content
    $endline = "// end of file: " + $fullname + " `n"
    Add-Content $_.FullName $endline

Adding a User to Multiple Exchange Distribution Lists Using Windows PowerShell

PowerShell command line window

Adding a user to multiple distribution lists via Outlook can be a tedious process if many lists are involved. For today’s problem, I had to add a user to many lists that have a similar prefix. Instead of spending a an hour or more of adding the user to the DLs through the Global Address Book, I decided to use PowerShell.

This script, which I call “addtodl.ps1”, receives three parameters: the user’s email address, the name of the distribution list – which can include a wildcard character (*) to get multiple names, and the Exchange Server FQDN.

	[string] $UserName,
	[string] $DLName,
	[string] $Exchange

$exch = "http://" + $Exchange + "/PowerShell/?SerializationLevel=Full"

$Credentials = Get-Credential
$ExSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $exch -Credential $Credentials -Authentication Kerberos
Import-PSSession $ExSession

$distlists =  Get-DistributionGroup $DLName

foreach ($distlist in $distlists) {		
	Add-DistributionGroupMember -Identity $distlist.PrimarySmtpAddress -Member $UserName
	#$ManagedBy = $distlist.ManagedBy
	#foreach ($owner in $ManagedBy) {
	#	echo $owner

Remove-PSSession -ID $ExSession.ID

By running this at the PowerShell command line with the parameters, you will be able to add the user to all distribution lists in the query that you manage. Those that you do not have access to will cause an error that will not halt the script. A dialog box asking for your username and password will appear first.

PowerShell command line window

When I have time, I intend to revisit this issue to get more useful information such as owner email addresses. Currently, if you uncomment the lines inside the foreach statement, the owners of each DL will be printed on the screen as well. It’s not too useful yet – which is why I still have it commented here.