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.
Thanks to Buddy for this post. Buddy developed a script which would mirror folders and documents from one project to another. In this post, I am going to take that idea and mirror the folders of a Work Area in one datasource to a corresponding Work Area in a second datasource. This is the precursor to mirroring the documents, which will be in a subsequent post. We will take advantage of the ProjectWise session capabilities. This will allow us to be logged into both datasources simultaneously, and switch back and forth.
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.21.5.0. Take a look at the help for each of the cmdlets to become familiar with their functionality, available parameters, etc.
- New-PWLogin
- Get-SecureStringFromEncryptedFile
- Get-PWSessions
- Get-PWCurrentDatasource
- Set-PWSession
- Show-PWFolderBrowserDialog
- Get-PWFolders
- New-PWFolder
- Remove-PWFolder
- Undo-PWLogin
Get-PWSessions
The Get-PWSessions cmdlet returns all active ProjectWise datasources within the active PowerShell session. If you are not logged into a datasource, you will receive the following error message.
Log In to ProjectWise Datasources
Source Datasource
I will be logging into the source datasource using the New-PWLogin cmdlet and providing the datasource name, user name and entering the password when prompted.
$SourceDatasource = 'BMF-WS2016-PWDI:ProjectWise' $Splat_LoginSource = @{ DatasourceName = $SourceDatasource UserName = 'pwadmin' Password = (Read-Host -Prompt "Enter password:" -AsSecureString) } New-PWLogin @Splat_LoginSource
TargetDatasource
I will be logging into the target datasource in the same manner, except I will read the password from an encrypted file.
$TargetDatasource = 'BMF-WS2016-PWDI:PowerShell' $Password = Get-SecureStringFromEncryptedFile -FileName 'd:\PowerShell\mysecretpassword.txt' $Splat_LoginTarget = @{ DatasourceName = $TargetDatasource UserName = 'pwadmin' Password = $Password } New-PWLogin @Splat_LoginTarget
Set Session
Now, we can use the Get-PWSessions to see that we are logged into both datasources.
We can use the Get-PWCurrentDatasource to determine which one is active. Then we will use the Set-PWSession to set the one we want active. By default the last login will be active. So, in this instance we are logged into the Target datasource. We want to be in the Source datasource.
Get Work Area Folders
Here we will use the Show-PWFolderBrowserDialog cmdlet to select the Work Area folder within the Source datasource. This is the folder structure we will be mirroring in the target datasource. We will be filtering the results to only return the FullPath of the selected Work Area folder.
Source Datasource
Select the Work Area folder and then the subfolders for the Source datasource.
$SourceFolderRoot = Show-PWFolderBrowserDialog | Select-Object -ExpandProperty FullPath
SubFolders
We will obtain the folder objects for the subfolders of the Source as we will need additional metadata for any folders created within the target. We will also use the -PopulatePaths parameter so that the FullPaths of the folders will be returned.
# Get all subfolders for source. $SourceFolders = Get-PWFolders -FolderPath $SourceFolderRoot -PopulatePaths
Target Datasource
Now, we will switch to the Target datasource and select the corresponding folder.
# Set the Target datasource active. Set-PWSession $TargetDatasource $DestinationFolderRoot = Show-PWFolderBrowserDialog | Select-Object -ExpandProperty FullPath
Next, we will get all of the subfolders for the Target Work Area. Again, we will include the -PopulatePaths switch parameter. Here we will only need the full path, so we with filter the results.
# Get all subfolders for Target. <# Explicitly set the type to a string array. Otherwise, you may encounter errors if there is only one folder fullpath returned. #> [string[]] $DestinationFolders = Get-PWFolders -FolderPath $DestinationFolderRoot -PopulatePaths | Select-Object -ExpandProperty FullPath
Mirror Folders
The first step in the mirroring process is verify and create any missing subfolders in the Target to match what is in the Source Work Area. To accomplish this we will loop through each of the Source subfolders, determine if there is a corresponding folder in the Target, if one does not exist, we will create it.
Note: For the sake of brevity, we are going to assume the Target datasource contains the same Environment(s) as the Source datasource.
# Iterate through all subfolders in SourceFolders. # Replicate folders that do not exist. foreach ($SourceFolder in $SourceFolders) { Write-Host "Source Folder $($SourceFolder.FullPath)" -ForegroundColor Cyan # Remove the Source Work Area folder name from the fullpath. $SourceFolderDiffPath = $($SourceFolder.FullPath).Substring($SourceFolderRoot.Length) # Add the Target Work Area folder name. $tempDestination = "$($DestinationFolderRoot)$SourceFolderDiffPath" <# We can search the DestinationFolders for the new path in the tempDestination variable. If it is found, nothing to do. If it is not, create the folder. #> if ($DestinationFolders.Contains($tempDestination)) { Write-Host "Destination folder '$tempDestination' exists." -ForegroundColor DarkGreen } else { Write-Host "Creating Folder '$tempDestination'." -ForegroundColor Red $newPWFolder = New-PWFolder $tempDestination -Environment $SourceFolder.Environment # Add the new folder path to the Destination folders for future comparisons. $DestinationFolders += $tempDestination } } # end foreach ($SourceFolder in $SourceFolders...
The following shows some of the output to the console.
The following shows an updated list of Destination folders. All of the Source folders have been created.
Now we need to clean up any folders that are not needed within the Target Work Area.
# Cleanup any folders no longer needed in the Target. foreach ($DestinationFolder in $DestinationFolders) { Write-Host "Destination Folder $DestinationFolder" -ForegroundColor Cyan # This time, we will remove the Target Work Area folder name from the fullpath. $DestinationFolderDiffPath = $DestinationFolder.Substring($DestinationFolderRoot.Length) # Add the Source Work Area folder name. $tempSource = "$($SourceFolderRoot)$DestinationFolderDiffPath" <# We can search the SourceFolders for each of the folders in the DestinationFolders. If it is found, nothing to do. If it is not, remove the folder from the Target. #> if ($($SourceFolders.FullPath).Contains($tempSource)) { Write-Host "Source folder '$tempSource' exists." -ForegroundColor DarkGreen } else { Write-Host "Mirror - removing Folder '$DestinationFolder'." -ForegroundColor Red Remove-PWFolder -FolderPath $DestinationFolder -RemoveDocuments -RemoveFolders -ProceedWithDelete } } # end foreach ($DestinationFolder in $DestinationFolders...
The following shows the end result. Notice only the folders contained in the Source are now listed. All unnecessary folders have been removed.
Log Out of Your Datasources
Be sure to log out of each of the ProjectWise datasources.
You can use the Get-PWCurrentDatasource cmdlet to determine which datasource is active. Then log out. Switch sessions and then log out of the other datasource.
Get-PWCurrentDatasource Undo-PWLogin Set-PWSession -Datasource $SourceDatasource Undo-PWLogin
Summary
In this post, we mirrored a set of folders based on a Work Area within a Source datasource to a selected Work Area within a Target datasource. This same process could be used to mirror folders from a ProjectWise datasource to a Windows folder. Ensure you add any error handling as needed.
Experiment with it and have fun. And please, let me know if there is a topic you would like to see a post for. Or share a solution you have developed.
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. And thank you for checking out my blog.
Hi Brian,
I’m new to PW Powershell. For some reason the Set-PWSession is not switching the current datasource (it says it does):
PS C:\Windows\system32> get-pwsessions
mwdh2o-pw.bentley.com:MWD_Projects
mwdh2o-pw.bentley.com:MWD_Test
PS C:\Windows\system32> Set-PWSession -Datasource mwdh2o-pw.bentley.com:MWD_Test
Changed to mwdh2o-pw.bentley.com:MWD_Test
PS C:\Windows\system32> Get-PWCurrentDatasource
mwdh2o-pw.bentley.com:MWD_Projects
using pwps_dab 1.30.3.4
LikeLike
There doesn’t appear to be anything wrong with what you are doing. And I cannot replicate the issue. Have you posted this to the Bentley Communities site?
Cheers,
Brian
LikeLike
I’ll post it there.
Thank you Brian
LikeLike