1

I'm creating a PowerShell script for DPM which outputs offsite ready tapes. The below code takes a few seconds to complete the DPM connection and to return the query, which is fine.

# Connect to local DPM server
$DPMServer = $env:COMPUTERNAME
Connect-DPMServer -DPMServerName $DPMServer | Out-Null

# Get the DPM libary
$DPMLib = Get-DPMLibrary

#Format output
$Formatting = @{Expression={$_.Barcode}; Label="Barcode "; Width=12}, 
     @{Expression={"{0:MM/dd/yyyy HH:mm tt}" -f $_.CreationDate}; Label="Creation Date      "; Width=23}, 
     @{Expression={$_.DisplayString}; Label="Tape Label              "; Width=28}, 
     @{Expression={"{0,15:N0}" -f $_.DataWrittenDisplayString}; Label="Data Written   "}

#Calculate Monday at midnight of this week
$Monday = (Get-Date).AddDays((-1 * (Get-Date).DayOfWeek.Value__) + 1).Date

# Get specific tapes
$Tapes = Get-DPMTape -DPMLibrary $DPMLib | 
    Where-Object {$_.Barcode -notlike "CLN*"} |
    Where-Object {$_.DisplayString -notlike "Free"} |
    Where-Object {$_.CreationDate -gt $Monday} |
    Sort-Object Barcode |
    Format-Table -Property $Formatting

Write-Host "`nOffsite Ready Tapes:" -ForegroundColor Cyan

#Output tapes
$Tapes

This outputs like so:

PowerShell Output

My question is how do I now select just the barcodes listed within the $Tapes array, and output them (below what I already have) as a comma delimited list, without running the DPM query again. I've tried all sorts of things with no luck, I'm missing something obvious.

If I do a second connection to DPM, I can do it like this, but I'm trying to avoid doubling the time it takes to run. This is part of my original newbie script that I'm trying to better.

# Define DPM server to connect to
$DPMServer = $env:COMPUTERNAME
Connect-DPMServer -DPMServerName $DPMServer | Out-Null

# Get the DPM libary
$DPMLib = Get-DPMLibrary

# Get tape display strings and barcodes, sort by barcode
$Tapes = Get-DPMTape -DPMLibrary $DPMLib | Select-Object CreationDate, DisplayString, Barcode | Sort-Object Barcode

# Create empty array
$DPMTapesForOffsite = @()

Write-Host "`nOffsite Ready Tapes:`n" -ForegroundColor Cyan

foreach ($_ in $Tapes) {
    # Exclude cleaning tapes
    if ($_.Barcode -notlike "CLN*") {
        # Exclude marked as free
        if ($_.DisplayString -notlike "Free") {
            $TimeStamp = Get-Date $_.CreationDate
            # Timestamp is from this week
            if ($Timestamp -gt $Monday) {
                $DPMTapesForOffsite = $DPMTapesForOffsite + $_.barcode
                Write-Host $_.barcode
            }
        }
    }
}

# Format tape list as comma delimited
$DPMTapesForOffsite = $DPMTapesForOffsite -join ","

I'm missing some obvious, any help would greatly be appreciated.

0

1 Answer 1

1
# Omit Format-Table initially, so as to store actual *data* in $tapes,
# not *formatting instructions*, which is what Format-* cmdlets return.
$tapes = Get-DPMTape -DPMLibrary $DPMLib | 
    Where-Object {$_.Barcode -notlike "CLN*"} |
    Where-Object {$_.DisplayString -notlike "Free"} |
    Where-Object {$_.CreationDate -gt $Monday} |
    Sort-Object Barcode

# Now you can apply the desired formatting.
Write-Host "`nOffsite Ready Tapes:" -ForegroundColor Cyan
$tapes | Format-Table -Property $Formatting

# Thanks to PowerShell's member-access enumeration feature,
# accessing property .Barcode on the entire $tapes *collection* 
# conveniently returns its *elements'* property values.
# -join ',' joins them with commas.
$tapes.Barcode -join ','

Format-* cmdlets output objects whose sole purpose is to provide formatting instructions to PowerShell's output-formatting system - see this answer.
In short: only ever use Format-* cmdlets to format data for display, never for subsequent programmatic processing.

This answer explains member-access enumeration.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, the formatting was the issue! I also needed to dig a little deeper to get the values with: $Tapes.Barcode | Select-Object -ExpandProperty Value
Glad to hear it, @TechFA. I had assumed that .Barcode directly returns the value of interest; it looks like you could simplify to $tapes.Barcode.Value - you can nest member enumerations.
Ah even better, thanks for the tips!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.