#PowerShell, #PowerWiseScripting, #ProjectWise, PWPS_DAB

HowTo: Get Documents Updated After A Derived Date

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, we will be creating a PowerShell function script file (.psm1) which will return an array of ProjectWise Document objects in a project which have been updated after a specific date.  If any documents are returned, it indicates that the project is active. Otherwise, it is deemed in-active. The date used will be derived from the current date, meaning documents updated in the last 7 days, 30 days, etc. 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 Take a look at the help for each of the cmdlets to become familiar with their functionality, available parameters, etc.
  • Write-PWPSLog
  • Get-PWFolders
  • Add-PWSavedSearch
  • Remove-PWSavedSearch
  • Get-PWDocumentsBySearch

FUNCTION Definition

The following is the function wrapper which will contain the remainder of the code.
FUNCTION Get-MyPWDocumentsByUpdatedDate {
        Returns an array of ProjectWise document objects based on the document updated date.
        Returns a list of ProjectWise document objects based on the document updated date.
        The date used will be derived from the current date minus the number of days back specified.
        Example of how to use this cmdlet.
        $Splat_CallFunction = @{
            FolderPath = 'bsi900 - adelaide tower'
            SearchName = 'MyTempSavedSearch'
            NumberOfDaysBack = 30
            LogFilePathName = 'd:\temp\GetDocumentsByUpdatedDate.log'
        $pwDocs = Get-MyPWDocumentsByUpdatedDate @Splat_CallFunction -Verbose 
        Array of ProjectWise Document Objects

    #Requires -Version 5.0
    #Requires -Modules @{ModuleName="PWPS_DAB";ModuleVersion=''}

    param (...) # end param...

    BEGIN {...} # end BEGIN...

    PROCESS {...} # end PROCESS...

    END{...} # end END...
} # end FUNCTION Get-MyPWDocumentsByUpdatedDate...
Export-ModuleMember -Function Get-MyPWDocumentsByUpdatedDate


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. We will be generating a log file. You will see that I have incorporated “ValidateScript” for a few of the parameters. This way I do not have do any additional checks to determine if a specified ProjectWise folder exists, or the path to the log file we will generate exists, etc.
#Requires -Version 5.0
#Requires -Modules @{ModuleName="PWPS_DAB";ModuleVersion=''}

param ( 
    # Specifies the ProjectWise folder to be used in saved search.
    [ValidateScript({ Get-PWFolders -FolderPath $_ -JustOne })]
        HelpMessage = "Specifies the ProjectWise folder to be used in saved search.",
        Mandatory = $true,
        Position = 0)]
    [string] $FolderPath,

    # Specifies the temporary search name to be used in function.
        HelpMessage = "Specifies the temporary search name to be used in function.",
        Mandatory = $false,
        Position = 1)]
    [string] $SearchName = 'TEMP_SavedSearch',

    # Specifies the number of days back to search for documents.
    [ValidateScript({ $_ -gt 0 })] 
        HelpMessage = "Specifies the number of days back to search for documents.",
        Mandatory = $true,
        Position = 2)]
    [int] $NumberOfDaysBack,

    [ValidateScript({ Split-Path $_ | Test-Path -PathType Container })]
        HelpMessage = "Log file to write messages to.",
        Mandatory = $true,
        Position = 3)]
    [String] $LogFilePathName
) # end param...


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.
    $CmdletName = $MyInvocation.MyCommand.Name
    $Splat_Log = @{
        Path = $LogFilePathName 
        Cmdlet = $CmdletName
        Verbose = $true
    Write-PWPSLog @Splat_Log -Message "[BEGIN] $(Get-Date) - Entering '$CmdletName' Function..." -Level Info 
} # end BEGIN...


Now, we will proceed to the PROCESS code block.
    # Get project / folder to search for documents.
    try {
        $Project = Get-PWFolders -FolderPath $FolderPath -JustOne -ErrorAction Stop

        #region Create temporary saved search.

        <# Calculate the date to use in the Temporary Saved Search.
            We will be looking for documents that have been updated within the last n number of days.
            n equals the $NumberOfDaysBack value. #>
        $DateUpdatedAfter = (Get-Date).AddDays( - $NumberOfDaysBack)
        Write-PWPSLog @Splat_Log -Message "[PROCESS] '$DateUpdatedAfter' is the date being used in the saved search." -Level Info

        $Splat_SavedSearch = @{
            SearchName = $SearchName
            UpdatedAfter = $DateUpdatedAfter

        <# The following determines if the project is a Rich Project / Work
              Area and sets the appropriate parameter for the 
              Add-PWSavedSearch. #>
        if($Project.IsRichProject -eq $true) { 
            $Splat_SavedSearch.OwnerProject = $Project
        } else { 
            $Splat_SavedSearch.SearchFolder = $Project.FullPath
        <# Add new temporary saved search to return documents created after
              specified date. #>
        Add-PWSavedSearch @Splat_SavedSearch -SearchSubFolders

        #endregion Create temporary saved search.

        #region Determine if Project is Active.

        #If any documents are returned, the project is active.
        try {
             $pwDocuments = Get-PWDocumentsBySearch -SearchName $SearchName -WarningAction Stop
             Write-PWPSLog @Splat_Log -Message "[PROCESS] Project '$($Project.FullPath)' is active." -Level Info
        } catch {
             Write-PWPSLog @Splat_Log -Message "[PROCESS] Project '$($Project.FullPath)' is NOT active." -Level Warn

        #endregion Determine if Project is Active.

        # Remove the temporary saved search.
        Remove-PWSavedSearch -SearchName $SearchName 
    } catch {
        $Line = $Error[0].InvocationInfo.ScriptLineNumber
        $ErrorMessage = $Error[0].Exception.Message
        Write-PWPSLog @Splat_Log -Message "[PROCESS] An error occurred while attempting to retrieve document objects. Occurred on line: $Line. $ErrorMessage." -Level Warn
    } # end try/catch...
} # end PROCESS...
The following shows the temporary Saved Search within the Work Area’s Global Saved Searches. savedsearch


Lastly, we will proceed to the END block of code. We will put a entry into the log file and return any ProjectWise Document objects found within the function.
    Write-PWPSLog @Splat_Log -Message "[END] $(Get-Date) - Exiting '$CmdletName' Function..." -Level Info
    Write-Output -InputObject $Return
} # end END...

The following shows the content of the log file generated. The purpose of the log file was to demonstrate how to use the Write-PWPSLog cmdlet. log
The following is a link to the full PowerShell script. HowTo_GetDocumentsUpdatedAfterADerivedDate 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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.