Be sure to check out my Scripting4Crypto initiative. It’s a fun way to get into using cryptocurrencies all while getting your PowerShell needs met.
In this post, I will go through the process of adding access control settings to a project folder. Then resetting and updating access control on each of the immediate children folders to the project. And finally updating access control for one sub-folder.
We will be using the following cmdlets to accomplish this task. All of the ProjectWise related cmdlets are available using the PWPS_DAB module. At the time of this post, I am using version 1.12.2.0. Take a look at the help for each of the cmdlets to become familiar with their functionality, available parameters, etc.
- Get-PWCurrentDatasource
- New-PWLogin
- Undo-PWLogin
- Get-PWFolders
- Get-PWGroups
- Get-PWUserLists
- Get-PWFoldersImmediateChildren
- Reset-PWFolderSecurity
- Update-PWFolderSecurity
Parameters
First thing we need to do is create our parameter and value pairs. The help messages will explain the purpose for each parameter. I am also going to include a few requires statements to ensure the correct version of PowerShell and the PWPS_DAB module are used. As well as require that the Run As Administrator option is used to run the PowerShell Console or PowerShell ISE.
#Requires -Version 5.0 #Requires -Modules @{ModuleName="PWPS_DAB";ModuleVersion='1.12.2.0'} #Requires -RunAsAdministrator [CmdletBinding()] param( [ValidateNotNullOrEmpty()] [Parameter( HelpMessage = 'Project folder.', Position = 0 )] [string] $ParentFolder = 'Projects\BSI900 - Adelaide Tower', [ValidateNotNullOrEmpty()] [ValidateSet('Group', 'UserList')] [Parameter( HelpMessage = 'Limiting MemberType to Group or UserList', Position = 1 )] [string] $MemberType = 'UserList', [ValidateNotNullOrEmpty()] [Parameter( HelpMessage = 'Name of group or userlist.', Position = 2 )] [string] $MemberName = 'Read_Only', [ValidateNotNullOrEmpty()] [Parameter( HelpMessage = 'Access control settings to use. See the help for Update-PWFolderSecurity possible MemberAccess values.', Position = 3 )] [string] $MemberAccess = ('r', 'w'), [ValidateNotNullOrEmpty()] [Parameter( HelpMessage = 'Project sub-folder.', Position = 4 )] [string] $subFolder = "$ParentFolder\01-WIP\CAD_Data', [ValidateNotNullOrEmpty()] [Parameter( HelpMessage = 'Name of group or userlist.', Position = 5 )] [string] $MemberName_CADD = 'CADD_Users', [ValidateNotNullOrEmpty()] [Parameter( HelpMessage = 'Access control settings to use. See the help for Update-PWFolderSecurity possible MemberAccess values.', Position = 6 )] [string] $MemberAccess_CADD = ('c', 'r', 'w', 'fr', 'fw') ) # end param
Begin
The next thing we will do is ensure we are logged into ProjectWise. If we are not logged into a ProjectWise datasource, the ProjectWise login dialog will be displayed. I am going to add these steps into the BEGIN section of the script.
I want to take a second and point out a couple of conventions that I use in my scripts. First, you may notice that I put a comment at the end of many of the blocks of code. Doing this makes it easier for me to determine where a block of code starts and ends. Comes in handy when troubleshooting a script. I also add text ([BEGIN], [PROCESS], [END]) in the output messages (Write-Verbose, Write-Warning, Write-Error) corresponding to the section of the script I am in. Again, this makes it obvious where something occurs within the script.
BEGIN { $Continue = $true $StartTime = Get-Date Write-Verbose -Message "[BEGIN] Start time: $StartTime" <# Determine if we are currently logged into a ProjectWise datasource. If not, display the ProjectWise Login Dialog. #> if(Get-PWCurrentDatasource) { Write-Verbose -Message "[BEGIN] Currently logged into ProjectWise datasource '$(Get-PWCurrentDatasource)'." } else { if(New-PWLogin -UseGui) { Write-Verbose -Message "[BEGIN] Successfully logged into ProjectWise datasource '$(Get-PWCurrentDatasource)'." } else { Write-Error -Message '[BEGIN] Failed to log into ProjectWise datasource.' $Continue = $false } } # end if(Get-PWCurrentDatasource... } # end BEGIN
PROCESS
Now that we are logged into a ProjectWise datasource, we can proceed to the PROCESS code block.
You can see that if the Continue variable equals false, a warning message will be displayed and we will proceed to the END code block to log out of ProjectWise and exit the script.
PROCESS { if( -not ($Continue)) { Write-Warning -Message "[PROCESS] Exiting script." } else { ... } } # end PROCESS
Next we will use the value in the $ParentFolder variable to get the corresponding folder object. If the folder is not found, an error will be thrown and the script will end.
# We are going to wrap the core of the processing in a try / catch block. try { # Determine if parent folder supplied is valid. If not, error out. $pwFolders = Get-PWFolders -FolderPath $ParentFolder -JustOne -ErrorAction Stop
Next we will need to verify the provided member name exists. Again, if the member is not found, an error will be thrown and the script will end.
# Verify the member provided is valid. switch($MemberType) { 'group' { $pwMemberResult = Get-PWGroups -GroupName $MemberName break } 'userlist' { $pwMemberResult = Get-PWUserLists -UserListName $MemberName break } } # If the member specified is not valid, throw an error message. Exit script. if([string]::IsNullOrEmpty($pwMemberResult)) { throw("Specified member type does not exist.") }
We will now populate a Splat with our parameter value pairs corresponding to the Update-PWFolderSecurity cmdlet. Then we will run the Update-PWFolderSecurity cmdlet to update the access control for the parent folder.
The following shows the access control settings for the parent folder.
# Add read-only userlist to the parent folder's Folder and Document Security. # Using a Splat for readibility and reusability. $SPlat_UpdateSecurity = @{ MemberType = $MemberType MemberName = $MemberName MemberAccess = $MemberAccess } $SPlat_UpdateSecurity.InputFolder = $pwParentFolder Update-PWFolderSecurity @SPlat_UpdateSecurity -FolderSecurity -ErrorAction Stop
The following shows the access control for the parent folder after updating the folder security. Notice that the Read_Only userlist has been added to folder security with read only permissions set. This will allow all users to see the folder, but not any documents contained in the folder.
Next we will get an array of immediate child folder objects of the parent folder. We will be resetting and updating access control for each of these folders.
# Get immediate child folders to the parent project. $pwImmediateChildFolders = Get-PWFoldersImmediateChildren -FolderID $pwParentFolder.ProjectID -ErrorAction Stop
We now have our folder objects which we will loop through and reset and update access control for each.
The following shows the access control to one of the immediate child folders prior to updating. We want to remove all explicitly set access control for each of the immediate child folders. Both folder and document security.
# Reset folder security for each of the child folders. # The following is a counter for the progress bar. $Counter = 1 $ItemCount = $pwImmediateChildFolders.count # Loop through each item in the collection. foreach($pwImmediateChildFolder in $pwImmediateChildFolders) { #region PROGRESS SECTION $Progress = @{ Activity = "Resetting folder security for '$($pwImmediateChildFolder.Name)'." Status = "Processing $Counter of $ItemCount" PercentComplete = $([math]::Round($(($Counter / $ItemCount) * 100 ), 2)) } Write-Progress @Progress -Id 1 # Increment the counter. $Counter #endregion PROGRESS SECTION # Reset access control for the current child folder. Reset-PWFolderSecurity -InputFolder $pwImmediateChildFolder -AllSecurity -ErrorAction Stop
The following shows that the access control has been reset for the 01-WIP folder. It is now inheriting permissions from the parent folder which is indicated by the small green downward pointing arrow icon.
Now we will update the folder security for the 01-WIP folder. We will be adding the Read_Only user list to the documents permissions.
# Update InputFolder value within the Splat. $SPlat_UpdateSecurity.InputFolder = $pwImmediateChildFolder # Add new member to document security for each folder. Keep the existing access control. Update-PWFolderSecurity @SPlat_UpdateSecurity -DocumentSecurity -IncludeInheritance -ErrorAction Continue } # Close the progress bar. Write-Progress -Activity 'Completed processing.' -Id 1 -Completed
The following shows that access control for the 01-WIP folder has been updated to explicitly set the document permissions. This will allow all members of the Read_Only access list to view documents within the folder.
Next, we want to explicitly set access control for the sub-folder 01-WIP\CAD_DATA. We will be adding the CADD_Users userlist to the document permissions only to allow for users to create and modify documents.
We will need to verify that the sub-folder exists, as well as the provided member name exists. Again, if either is invalid, an error will be thrown and the script will end.
# Again, determine if folder supplied is valid. If not, error out. $pwFolder = Get-PWFolders -FolderPath $subFolder -JustOne -ErrorAction Stop <# Again, verify the CADD member provided is valid. This could be put into a FUNCTIONs to eliminate duplicate code. #> switch($MemberType) { 'group' { $pwMemberResult = Get-PWGroups -GroupName $MemberName break } 'userlist' { $pwMemberResult = Get-PWUserLists -UserListName $MemberName_CADD break } } # If the member specified is not valid, throw an error message. Exit script. if([string]::IsNullOrEmpty($pwMemberResult)) { throw("Specified member type does not exist.") } # Update the values within the Splat. $SPlat_UpdateSecurity.InputFolder = $pwFolder $SPlat_UpdateSecurity.MemberName = $MemberName_CADD $SPlat_UpdateSecurity.MemberAccess = $MemberAccess_CADD # Add new member to document security for each folder. Keep the existing access control Update-PWFolderSecurity @SPlat_UpdateSecurity -DocumentSecurity -IncludeInheritance -ErrorAction Continue } catch { $line = $_.InvocationInfo.ScriptLineNumber Write-Warning -Message "[PROCESS] $($Error[0].Exception.Message) Error occurred on line '$Line'." } # end try / catch
The following shows that we have successfully added the CADD_Users userlist to the CAD_Data folder’s document security.
We have completed all steps in the access control update process.
END
Lastly, we will proceed to the END block of code to log out of our ProjectWise session. You will also see that we have calculated the amount of time it had taken to complete the process.
END { $EndTime = Get-Date Write-Verbose -Message "[END] It took $([Math]::Round($EndTime.Subtract($StartTime).TotalMinutes, 2)) minutes to complete process." Write-Verbose -Message '[END] Logging out of ProjectWise.' Undo-PWLogin } # end END
The following is a link to the full PowerShell script.
HowTo_UpdateProjectWiseFolderSecurity
Experiment with it and have fun.
Hopefully, you find this useful. Please let me know if you have any questions or comments. If you like this post, please click the Like button at the bottom of the page.