Added a parameter and now I'm getting ParameterBindingValidationException errors

Welcome Forums General PowerShell Q&A Added a parameter and now I'm getting ParameterBindingValidationException errors

This topic contains 9 replies, has 3 voices, and was last updated by

 
Participant
2 months, 2 weeks ago.

  • Author
    Posts
  • #163758

    Participant
    Topics: 2
    Replies: 7
    Points: 23
    Rank: Member

    I've added a parameter to a script and I'm now getting ParameterBindingValidationException errors on cmdlets like test-path, and out-file, presumably because the files they refer to don't exist yet.  They shouldn't, or don't need to exist until written to.

    I've added a single parameter, and it's now validating the paths.  What are my options for handling it?

    Param
    (
    # The batchnumber is a two digit number that is used in the filename of the batch CSV (E.G. 09).
    # This assumes the standard file name format is "PhaseXX_Mailboxes.csv", where the batchnumber replaces "XX"
    [Parameter(Mandatory=$true,Position=0)]
    [ValidatePattern("[0-9][0-9]")]
    [string]$batchnumber
    )

    Then in the script I have lines as follows that generate the errors:

    "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"), Batch:$Batchnumber , User:$I, $($MigraMB.PrimarySMTPAddress)" | out-file $LogPath -Append

    and

     If(test-path $ErrorLogPath)

    Errors:

    Test-Path : Cannot bind argument to parameter 'Path' because it is null.
    At C:\scripts\O365-Migration-DuplicateSendAsToEXO\O365-Migration-DuplicateSendAsToEXO.ps1:196 char:18
    + If(Test-Path $ErrorLogPath)
    + ~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Test-Path], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.TestPathCommand

    Out-File : Cannot bind argument to parameter 'FilePath' because it is null.
    At C:\scripts\O365-Migration-DuplicateSendAsToEXO\O365-Migration-DuplicateSendAsToEXO.ps1:192 char:105
    + ... $E" | out-file $ErrorLogPath -Append}
    + ~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Out-File], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.OutFileCommand

     

  • #163767

    Participant
    Topics: 14
    Replies: 43
    Points: 146
    Helping Hand
    Rank: Participant

    Could you post more of the script? I think the errors you are getting refer to the parameters used in your

    Out-File

    and

    Test-Path

    cmdlets. Not the parameter you added to your script.

    Steve

    • #163770

      Participant
      Topics: 2
      Replies: 7
      Points: 23
      Rank: Member

      Here are the variables at the beginning of the script that set up the paths.  The error log won't  be created if there aren't any.

      
      $PathRoot = "C:\scripts\"
      
      $D = Get-Date -Format "yyyy-MM-dd_HH-mm"
      $LogPath = (Join-Path $PathRoot -ChildPath "Logs\all_LOG_$D.txt")
      $MBoutFile = (Join-Path $PathRoot -ChildPath "Data\ALL_$D.csv")
      $MigrationUsersFile = (Join-Path $PathRoot -ChildPath "Batches\Phase$($Batchnumber)_Mailboxes.csv")
      $SendAsPermsFile = (Join-Path $PathRoot -ChildPath "Data\ALL-SendAs_$D.csv")
      $ExportObjectFile = (Join-Path $PathRoot -ChildPath "Logs\all_LOG_$D.csv")
      $TranscriptLogPath = (Join-Path $PathRoot -ChildPath "Logs\all-Transcript_$D.txt")
      $ErrorLogPath = (Join-Path $PathRoot -ChildPath "Logs\all_ERRORS_$D.log")
      
      

      One of the errors is on the test-path line of the following:

      
      FINALLY
      {
      If(test-path $ErrorLogPath)
      {
      $FE = GC $ErrorLogPath | Out-String
      Send-MailMessage -TO "me@domain.com" -From "him@domain.com" `
      -SmtpServer server1.domain.com `
      -Subject "O365-SendAsDuplicater Completed with Errors: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")" `
      -body "Check Error log on server $($env:computername): `n: $($ErrorLogPath) `n $($FE)"
      }
      ELSE
      {
      Send-MailMessage -TO "me@domain.com" -From "him@domain.com" `
      -SmtpServer server1.domain.com `
      -Subject "Duplicater Completed without Errors: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")" `
      -body "Completed on server $($env:computername)"
      }
      
      } # FINALLY END
      
      

      Another error is on the scripts overall try\catch, although there are other "out-file $ErrorLogPath -Append" lines within the body.  That makes it seems that it's validating paths associated with the overall try\catch\finally, and not the body of the script.  Does putting in a single parameter force it to validate those paths, or does having a paramater with a validation attribute force that?

      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error Main: $E" | out-file $ErrorLogPath -Append}
  • #163941

    Participant
    Topics: 2
    Replies: 54
    Points: 278
    Helping Hand
    Rank: Contributor

    It seems that your path variables aren't being assigned at all. Is the section of your script that assigns the paths to variables inside a function?

    • #163956

      Participant
      Topics: 2
      Replies: 7
      Points: 23
      Rank: Member

      Here's the entire script cleaned up...I hope.  The variables are inside the main Try\Catch, but not in a separate function.  I could move them outside the Try\Catch, which is what the errors are on.

      
      TRY{
      #### VARIABLES START #####################
      
      # *** CHANGE $Prefix FOR EACH BATCH ***
      $Prefix = "HERE"
      $PSTnames = (get-Item "\\server1\c$\PSTs\UPload\$Prefix-*").name
      
      # *** Change the $PathRoot as needed ***
      $PathRoot = "C:\scripts\import\Logs"
      $D = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
      
      sl $PSScriptRoot
      
      # These strings will be removed...
      $ReplaceFileString1 = "$($Prefix)-"
      $ReplaceFileString2 = "_Export_0001"
      $ReplaceFileString3 = ".pst"
      
      # Log paths
      $LogPath = (Join-Path $PathRoot -ChildPath "Purge_General.log")
      $ErrorLogPath = (Join-Path $PathRoot -ChildPath "Purge_ERRORS_$D.log")
      $MBstatsBeforeTagPurge = (Join-Path $PathRoot -ChildPath "Purge_MBstats-BEFORE.csv")
      $MBstatsAfterTagPurge = (Join-Path $PathRoot -ChildPath "Purge_MBstats-AFTER.csv")
      $ItemsReport = (Join-Path $PathRoot -ChildPath "Purge_Report.log")
      $TranscriptLogPath = (Join-Path $PathRoot -ChildPath "Transcripts\Purge-Transcript_$D.txt")
      Start-Transcript -Path $TranscriptLogPath -IncludeInvocationHeader -NoClobber
      
      #### VARIABLES END #######################
      
      #### FUNCTION START ######################
      
      # Function to set...
      TRY{
      
      Function TagNeverDelete ($Mailbox)
      {
      # Set the mailbox SMTP for the Service
      $service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress,$Mailbox)
      
      # Set up search criteria to find the "MaFold" and "HistItems" folders
      $FolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
      $FolderView.Traversal = [Microsoft.Exchange.Webservices.Data.FolderTraversal]::Shallow
      $SearchFilterManagedFolders = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,"MaFold")
      $SearchFilterHistItems = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,"HistItems")
      
      # Create the properties needed to apply the personal tag: PR_POLICY_TAG [0x3019], PR_RETENTION_FLAGS [0x301D], PR_RETENTION_PERIOD [0x301A]
      $PolicyTag = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x3019,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Binary);
      $RetentionFlags = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x301D,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);
      $RetentionPeriod = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x301A,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);
      
      # Set up the personal tag...
      $PolicyTagGUID = new-Object Guid("{674c6a14-3ed5-432e-9edb-c6620a8278f0}");
      
      ######### Primary Mailbox START #########
      
      # Search for the "MaFold" folder
      $FindFolderResultsPrimaryManagedFolders = $service.FindFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$SearchFilterManagedFolders,$FolderView)
      
      # If the "MaFold" folder is NOT FOUND add a log entry and take no action
      if ($FindFolderResultsPrimaryManagedFolders.TotalCount -eq 0)
      {
      Write-host "MaFold (PRIMARY) DOES NOT EXIST: $($Mailbox)"
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") MaFold (PRIMARY) DOES NOT EXIST: $($Mailbox)" | out-file $LogPath -Append
      }
      
      # If the "MaFold" folder is FOUND look for subfolder "HistItems"
      else
      {
      # Search for subfolder "HistItems"
      $FindFolderResultsPrimaryHistItems = $service.FindFolders($FindFolderResultsPrimaryManagedFolders.id,$SearchFilterHistItems,$FolderView)
      
      # If the "HistItems" folder is NOT FOUND add a log entry and take no action
      if ($FindFolderResultsPrimaryHistItems.TotalCount -eq 0)
      {
      Write-host "HistItems (PRIMARY) DOES NOT EXIST: $($Mailbox)"
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") HistItems (PRIMARY) DOES NOT EXIST: $($Mailbox)" | out-file $LogPath -Append
      }
      
      # If the "HistItems" folder is FOUND assign the never delete tag
      Else
      {
      # Bind to "HistItems" folder
      $Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$FindFolderResultsPrimaryHistItems.Folders[0].Id)
      
      # Set property values: PR_POLICY_TAG [0x3019], PR_RETENTION_FLAGS [0x301D], PR_RETENTION_PERIOD [0x301A]
      $Folder.SetExtendedProperty($RetentionFlags, 137)
      $Folder.SetExtendedProperty($RetentionPeriod, 0)
      $Folder.SetExtendedProperty($PolicyTag, $PolicyTagGUID.ToByteArray())
      
      # Apply the changes to the folder
      $Folder.Update()
      
      Write-host "Retention policy stamped on HistItems (PRIMARY): $($Mailbox)"
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Retention policy stamped on HistItems (PRIMARY): $($Mailbox)" | out-file $LogPath -Append
      
      } # else Inner Primary Mailbox END
      
      } # else Outer Primary Mailbox END
      
      ######### Primary Mailbox END #########
      
      ######### Archive Mailbox START #########
      
      # Search for the "MaFold" folder
      $FindFolderResultsArchiveManagedFolders = $service.FindFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::ArchiveMsgFolderRoot,$SearchFilterManagedFolders,$FolderView)
      
      # If the "MaFold" folder is NOT FOUND add a log entry and take no action
      if ($FindFolderResultsArchiveManagedFolders.TotalCount -eq 0)
      {
      Write-host "MaFold (ARCHIVE) DOES NOT EXIST: $($Mailbox)"
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") MaFold (ARCHIVE) DOES NOT EXIST: $($Mailbox)" | out-file $LogPath -Append
      }
      
      # If the "MaFold" folder is FOUND look for subfolder "HistItems"
      else
      {
      # Search for subfolder "HistItems"
      $FindFolderResultsArchiveHistItems = $service.FindFolders($FindFolderResultsArchiveManagedFolders.id,$SearchFilterHistItems,$FolderView)
      
      # If the "HistItems" folder is NOT FOUND add a log entry and take no action
      if ($FindFolderResultsArchiveHistItems.TotalCount -eq 0)
      {
      Write-host "HistItems (ARCHIVE) DOES NOT EXIST: $($Mailbox)"
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") HistItems (ARCHIVE) DOES NOT EXIST: $($Mailbox)" | out-file $LogPath -Append
      }
      
      # If the "HistItems" folder is FOUND assign the never delete tag
      Else
      {
      # Bind to "HistItems" folder
      $Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$FindFolderResultsArchiveHistItems.Folders[0].Id)
      
      # Set property values: PR_POLICY_TAG [0x3019], PR_RETENTION_FLAGS [0x301D], PR_RETENTION_PERIOD [0x301A]
      $Folder.SetExtendedProperty($RetentionFlags, 137)
      $Folder.SetExtendedProperty($RetentionPeriod, 0)
      $Folder.SetExtendedProperty($PolicyTag, $PolicyTagGUID.ToByteArray())
      
      # Apply the changes to the folder
      $Folder.Update()
      
      Write-host "Retention policy stamped on HistItems (ARCHIVE): $($Mailbox)"
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Retention policy stamped on HistItems (ARCHIVE): $($Mailbox)" | out-file $LogPath -Append
      
      } # else Inner Archive Mailbox END
      
      } # else Outer Archive Mailbox END
      
      ######### Archive Mailbox END #########
      
      
      # Make sure the user is NULLed out for good measure before processing the next
      $service.ImpersonatedUserId = $null
      
      } # Function TagNeverDelete END
      
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error Function TagNeverDelete: $($E)" | out-file $ErrorLogPath -Append}
      
      #### FUNCTION END ########################
      
      # Create credential object using pass hash file previously created:
      TRY{
      $Username = "user@domain.com"
      $Password = Get-Content "C:\HashFile.pwd" | ConvertTo-SecureString
      $Credential = New-Object System.Management.Automation.PSCredential($Username,$Password)
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error Credential Create: $($E)" | out-file $ErrorLogPath -Append}
      
      # Connect to EXO. Import only necessary Exchange cmdlets.
      #########################################################################################################################
      TRY{
      $SessionEXO = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential -Authentication Basic -AllowRedirection
      $ImportResultsEXO = Import-PSSession $SessionEXO -Prefix EXO -CommandName "Get-Mailbox", "start-managedfolderassistant", "Get-MailboxFolderStatistics" -DisableNameChecking
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error Connect Exchange EXO: $($E)" | out-file $ErrorLogPath -Append}
      #########################################################################################################################
      
      # Import "Microsoft Exchange Web Services Managed API 2.2" to adjust retention properties
      # DOWNLOAD: https://www.microsoft.com/en-us/download/details.aspx?id=42951
      TRY{
      Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error Import WebServices Module: $($E)" | out-file $ErrorLogPath -Append}
      
      # TagNeverDelete service setup: Create the service object to access the mailboxes
      $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList Exchange2013_SP1
      $service.Credentials = new-object Microsoft.Exchange.WebServices.Data.WebCredentials -ArgumentList $Credential.UserName, $Credential.GetNetworkCredential().Password
      $service.Url= new-object Uri("https://outlook.office365.com/EWS/Exchange.asmx")
      $service.TraceEnabled = $true
      
      # Intiate array to collect the mailbox UPNs
      $UPNs = @()
      
      # For each mailbox...
      foreach($PSTname in $PSTnames)
      {
      $UserDisplayName = $PSTname -replace ("$ReplaceFileString1","") -replace ("$ReplaceFileString2","") -replace (',',', ') -replace ("$ReplaceFileString3","")
      # $UserDisplayName
      
      # Get the Mailbox UPN, and add them to an array to later use to start the MFA for each mailbox
      TRY{
      $UPN = (Get-EXOMailbox $UserDisplayName).userprincipalname
      
      $UPNs += $UPN
      
      $StatsArchive = Get-EXOMailboxFolderStatistics $UPN -Archive | sort Name |
      select @{n='DATE';e={Get-Date -Format "yyyy-MM-dd HH:mm:ss"}},@{n='MBtype';e={"Archive"}}, Identity, FolderPath, Name, DeletePolicy, ArchivePolicy, CreationTime, LastModifiedTime, FolderType, FolderSize, FolderAndSubfolderSize, ItemsInFolder, VisibleItemsInFolder, HiddenItemsInFolder, DeletedItemsInFolder, ItemsInFolderAndSubfolders, DeletedItemsInFolderAndSubfolders, FolderId
      $StatsArchive | Export-Csv $MBstatsBeforeTagPurge -NoTypeInformation -Append -Force
      
      $StatsPrimary = Get-EXOMailboxFolderStatistics $UPN | sort Name |
      select @{n='DATE';e={Get-Date -Format "yyyy-MM-dd HH:mm:ss"}},@{n='MBtype';e={"Primary"}}, Identity, FolderPath, Name, DeletePolicy, ArchivePolicy, CreationTime, LastModifiedTime, FolderType, FolderSize, FolderAndSubfolderSize, ItemsInFolder, VisibleItemsInFolder, HiddenItemsInFolder, DeletedItemsInFolder, ItemsInFolderAndSubfolders, DeletedItemsInFolderAndSubfolders, FolderId
      $StatsPrimary | Export-Csv $MBstatsBeforeTagPurge -NoTypeInformation -Append -Force
      
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error on Get-EXOMailbox for $($UPN): $($E)" | out-file $ErrorLogPath -Append}
      
      # Assign never delete to "HistItems" folder
      TRY{
      Write-host "`n"
      # "`n" | out-file $LogPath -Append
      
      TagNeverDelete -Mailbox $UPN
      
      Write-host "`n"
      # "`n" | out-file $LogPath -Append
      
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error on TagNeverDelete function for $($UPN): $($E)" | out-file $ErrorLogPath -Append}
      
      # Remove...
      TRY{
      "`n******" | out-file $ItemsReport -Append
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"): -START- ItemsReport for $($UPN)" | out-file $ItemsReport -Append
      "******" | out-file $ItemsReport -Append
      .\Remove-MessageClassItems.ps1 $UPN -ArchiveOnly -ScanAllFolders -MessageClass 'IPM.NOTE.type1.Shortcut' -Credentials $Credential -Impersonation -Server outlook.office365.com -Verbose -Confirm:$false < #-WhatIf:$true#> *>> $ItemsReport
      "`n******" | out-file $ItemsReport -Append
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"): -END- ItemsReport for $($UPN)" | out-file $ItemsReport -Append
      "******" | out-file $ItemsReport -Append
      
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error on Remove-MessageClassItems for $($UPN): $($E)" | out-file $ErrorLogPath -Append}
      
      } # foreach($PSTname... END
      
      sleep 20
      
      # Start Managed Folder Assistant to apply newly assigned tag
      Foreach($UPN in $UPNs) #{$UPN}
      {
      # Start Managed Folder Assistant to apply tag
      TRY{
      
      start-exomanagedfolderassistant $UPN # -WhatIf
      
      Write-host "MaFold Assistant has been run for: $($UPN)" #-foregroundcolor $info
      "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") MaFold Assistant has been run for: $($UPN)" | out-file $LogPath -Append
      
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error on start-exomanagedfolderassistant for $($UPN): $($E)" | out-file $ErrorLogPath -Append}
      
      } # Foreach($U... END
      
      sleep 300
      
      # Get Mailbox Folder stats after changes
      Foreach($UPN in $UPNs) #{$UPN}
      {
      $StatsArchive = Get-EXOMailboxFolderStatistics $UPN -Archive | sort Name |
      select @{n='DATE';e={Get-Date -Format "yyyy-MM-dd HH:mm:ss"}},@{n='MBtype';e={"Archive"}}, Identity, FolderPath, Name, DeletePolicy, ArchivePolicy, CreationTime, LastModifiedTime, FolderType, FolderSize, FolderAndSubfolderSize, ItemsInFolder, VisibleItemsInFolder, HiddenItemsInFolder, DeletedItemsInFolder, ItemsInFolderAndSubfolders, DeletedItemsInFolderAndSubfolders, FolderId
      $StatsArchive | Export-Csv $MBstatsAfterTagPurge -NoTypeInformation -Append -Force
      
      $StatsPrimary = Get-EXOMailboxFolderStatistics $UPN | sort Name |
      select @{n='DATE';e={Get-Date -Format "yyyy-MM-dd HH:mm:ss"}},@{n='MBtype';e={"Primary"}}, Identity, FolderPath, Name, DeletePolicy, ArchivePolicy, CreationTime, LastModifiedTime, FolderType, FolderSize, FolderAndSubfolderSize, ItemsInFolder, VisibleItemsInFolder, HiddenItemsInFolder, DeletedItemsInFolder, ItemsInFolderAndSubfolders, DeletedItemsInFolderAndSubfolders, FolderId
      $StatsPrimary | Export-Csv $MBstatsAfterTagPurge -NoTypeInformation -Append -Force
      
      } # Foreach($UPN... END
      
      Stop-Transcript
      
      }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error Caught Main: $($E)" | out-file $ErrorLogPath -Append}
      
      FINALLY
      {
      If(Test-Path $ErrorLogPath)
      {
      $FE = GC $ErrorLogPath | Out-String
      Send-MailMessage -TO "who@domain.com" -From "Purge@domain.com" `
      -SmtpServer server2.domain.com `
      -Subject "Purge Completed with Errors: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")" `
      -body "Check Error log on server $($env:computername): `n: $($ErrorLogPath) `n $($FE)"
      }
      ELSE
      {
      Send-MailMessage -TO "who@domain.com" -From "Purge@domain.com" `
      -SmtpServer server2.domain.com `
      -Subject "Purge Completed without Errors: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")" `
      -body "Completed on server $($env:computername)"
      }
      
      } # FINALLY END
      
      
  • #163959

    Participant
    Topics: 2
    Replies: 7
    Points: 23
    Rank: Member

    Move the variables outside the Try\Catch stops the errors from happening.  I guess that's fine, but it doesn't anser why the paths are erroring.

  • #163980

    Participant
    Topics: 2
    Replies: 7
    Points: 23
    Rank: Member

    When the parameter is in it's own try\catch with the validation attribute it errors on the same 2 lines in the Catch\Finally that is for the body of the script.  When I remove the validation attribute of the parameter it errors on the Catch at the end of the variable section.  So, it seems if you have a parameter within a TRY\CATCH it will validate the Catch and Finally, which includes any paths in them, prior to doing anything within the TRY\CATCH. And having a validation attribute changes the behaviour of the validations. This must be known behaviour?

    This has the parameter validation attribute, and errors on the CATCH\FINALLY that is for the script body, not on the CATCH that holds the parameter and variables:

    
    TRY{
    
    Param
    (
    [Parameter(Mandatory=$true,Position=0)]
    [ValidatePattern("^[0-9][1-9]$")]
    $batchnumber
    )
    
    #### VARIABLES START #####################
    
    # *** CHANGE $Prefix FOR EACH BATCH ***
    $Prefix = "HERE"
    $PSTnames = (get-Item "\\server1\c$\PSTs\UPload\$Prefix-*").name
    
    # *** Change the $PathRoot as needed ***
    $PathRoot = "C:\scripts\import\Logs"
    $D = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
    
    sl $PSScriptRoot
    
    # These strings will be removed...
    $ReplaceFileString1 = "$($Prefix)-"
    $ReplaceFileString2 = "_Export_0001"
    $ReplaceFileString3 = ".pst"
    
    # Log paths
    $LogPath = (Join-Path $PathRoot -ChildPath "Purge_General.log")
    $ErrorLogPath = (Join-Path $PathRoot -ChildPath "Purge_ERRORS_$D.log")
    $MBstatsBeforeTagPurge = (Join-Path $PathRoot -ChildPath "Purge_MBstats-BEFORE.csv")
    $MBstatsAfterTagPurge = (Join-Path $PathRoot -ChildPath "Purge_MBstats-AFTER.csv")
    $ItemsReport = (Join-Path $PathRoot -ChildPath "Purge_Report.log")
    $TranscriptLogPath = (Join-Path $PathRoot -ChildPath "Transcripts\Purge-Transcript_$D.txt")
    Start-Transcript -Path $TranscriptLogPath -IncludeInvocationHeader -NoClobber
    
    #### VARIABLES END #######################
    }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error on variablese: $($E)" | out-file $ErrorLogPath -Append}
    
    

    For this the parameter has no validation attribute, and only errors on the CATCH at the end of the Parameter\variable, not on the script body CATCH\FINALLY:

    
    TRY{
    Param
    (
    [Parameter(Mandatory=$true,Position=0)]
    $batchnumber
    )
    
    #### VARIABLES START #####################
    
    # *** CHANGE $Prefix FOR EACH BATCH ***
    $Prefix = "HERE"
    $PSTnames = (get-Item "\\server1\c$\PSTs\UPload\$Prefix-*").name
    
    # *** Change the $PathRoot as needed ***
    $PathRoot = "C:\scripts\import\Logs"
    $D = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
    
    sl $PSScriptRoot
    
    # These strings will be removed...
    $ReplaceFileString1 = "$($Prefix)-"
    $ReplaceFileString2 = "_Export_0001"
    $ReplaceFileString3 = ".pst"
    
    # Log paths
    $LogPath = (Join-Path $PathRoot -ChildPath "Purge_General.log")
    $ErrorLogPath = (Join-Path $PathRoot -ChildPath "Purge_ERRORS_$D.log")
    $MBstatsBeforeTagPurge = (Join-Path $PathRoot -ChildPath "Purge_MBstats-BEFORE.csv")
    $MBstatsAfterTagPurge = (Join-Path $PathRoot -ChildPath "Purge_MBstats-AFTER.csv")
    $ItemsReport = (Join-Path $PathRoot -ChildPath "Purge_Report.log")
    $TranscriptLogPath = (Join-Path $PathRoot -ChildPath "Transcripts\Purge-Transcript_$D.txt")
    Start-Transcript -Path $TranscriptLogPath -IncludeInvocationHeader -NoClobber
    
    #### VARIABLES END #######################
    }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error on variablese: $($E)" | out-file $ErrorLogPath -Append}
    

    This doesn't error at all, The paramter is not in a TRY\CATCH:

    Param
    (
    [Parameter(Mandatory=$true,Position=0)]
    [ValidatePattern("^[0-9][1-9]$")]
    $batchnumber
    )
    
    TRY{
    #### VARIABLES START #####################
    
    # *** CHANGE $Prefix FOR EACH BATCH ***
    $Prefix = "HERE"
    $PSTnames = (get-Item "\\server1\c$\PSTs\UPload\$Prefix-*").name
    
    # *** Change the $PathRoot as needed ***
    $PathRoot = "C:\scripts\import\Logs"
    $D = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
    
    sl $PSScriptRoot
    
    # These strings will be removed...
    $ReplaceFileString1 = "$($Prefix)-"
    $ReplaceFileString2 = "_Export_0001"
    $ReplaceFileString3 = ".pst"
    
    # Log paths
    $LogPath = (Join-Path $PathRoot -ChildPath "Purge_General.log")
    $ErrorLogPath = (Join-Path $PathRoot -ChildPath "Purge_ERRORS_$D.log")
    $MBstatsBeforeTagPurge = (Join-Path $PathRoot -ChildPath "Purge_MBstats-BEFORE.csv")
    $MBstatsAfterTagPurge = (Join-Path $PathRoot -ChildPath "Purge_MBstats-AFTER.csv")
    $ItemsReport = (Join-Path $PathRoot -ChildPath "Purge_Report.log")
    $TranscriptLogPath = (Join-Path $PathRoot -ChildPath "Transcripts\Purge-Transcript_$D.txt")
    Start-Transcript -Path $TranscriptLogPath -IncludeInvocationHeader -NoClobber
    
    #### VARIABLES END #######################
    }CATCH{$E = $_ | select Exception;"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") Error on variablese: $($E)" | out-file $ErrorLogPath -Append}
    
  • #163992

    Participant
    Topics: 14
    Replies: 43
    Points: 146
    Helping Hand
    Rank: Participant

    Pretty sure your parameter block cannot be inside a Try/Catch. I'm not really sure why you would want it to be. In addition, you have a function definition inside a try/catch block. Again, not sure why that is the case either??

    Also – FWIW, there are a lot of nested try/catch blocks here, and with your code formatted left justified it makes it a little difficult to follow. If you use vscode as your editor, a couple of simple settings will auto-format your code for easier readability. And finally, it is more of a best practice / pattern to use parameter splatting vs back ticks when sending longer parameter sets into a cmdlet – like where you are using your Send-Mail.

  • #164046

    Participant
    Topics: 2
    Replies: 7
    Points: 23
    Rank: Member

    I'm a hack I suppose.  I've read up and watched a number of MS instructional videos on powershell a number of years ago, but since then I figure it out as I go, and read up on certain things, which leaves me behind, forgetting certain things, and not in the know of many best practices.  One practice I found useful was to have those nested try\catch blocks, and the code in them is indented in them in the script. It didn't copy that way apparently.  I didn't give it much thought about having the parameters in a TRY\CATCH.  I don't use parameters much to tell the truth, and I'm used to putting the entire script in a TRY\CATCH so that's what happened.  The nested function is there for the same reason.  I didn't want to separate it from the main script as a separate file.

    I've tried vscode, but I always connect to both on-prem and exchange online with remote powershell, and the editor window does not allow me to use both sets of cmdlets even though, as is my normal practice, I set a prefix for one of them.  the editor window will only resolve one set of cmdlets (e.g. on-prem), and not the other.  I posted about that in stackoverflow, and couldn't get a satisfactory solution.  So, I continue to use ISE.  I've used splatting before.  That's one of those things where I've just copied from another script, but I can change the way i do that.

    Thank you for the feedback

  • #164049

    Participant
    Topics: 14
    Replies: 43
    Points: 146
    Helping Hand
    Rank: Participant

    I'm a hack I suppose.

    Aren't we all? 🙂

    While I am sure that some would say pulling that function out of the file into a separate ps1 file – I'm not sure it would be completely necessary. Typically when I have defined functions within a script, I try to do it at the top (below the param block if there is one). The only rule there is that the function needs to be defined before you use it.

    Thank you for the feedback

    Happy to provide, hope it helped.

    Steve

You must be logged in to reply to this topic.