Santiago Squarzon has provided the crucial pointer in a comment:
- All instances of
this.$totalBytesToTransfer
should be $this.totalBytesToTransfer
instead.
While to users already familiar with PowerShell class
your code could be seen as a mere typo, the required syntax is worth explaining:
The automatic $this
variable refers to the instance at hand.
To refer to a property of the instance at hand, you must use $this
combined with the usual dot notation, but without $
- prefixing the property name - even though properties must be declared with that prefix; that is:
To declare a property named TotalBytesToTransfer
, you must use variable syntax, which requires $
: $TotalBytesToTransfer
(typically declared with a type, e.g. [long] $TotalBytesToTransfer
).
To access that property, you must use $this.TotalBytesToTransfer
The surprising aspects are:
As for what you tried:
Anyone know what this message means?
Error message Variable is not assigned in the method.
is trying to tell you that, inside a given method, you attempted to reference a variable that wasn't also defined earlier in the same method, which was triggered by the accidental reference to non-existent variable $totalBytesToTransfer
.
As noted above, property-defining variables aren't implicitly accessible, and any variable references must be to method-local variables, i.e. to variables defined earlier in the same method.
- The exception are variable references with an explicit scope specifier, such as
$global:foo
; however, such references are best avoided in classes, so as not to break encapsulation.
The error message - cited as of PowerShell 7.3.4 - could be improved, which is the subject of GitHub issue #19767.
The reason only the last of your four this.$totalBytesToTransfer
references triggered the error is rooted in the fundamentals of PowerShell's syntax, which combines shell-like syntax with syntax familiar from traditional programming languages via distinct parsing modes (see the general information in the bottom section):
Perhaps surprisingly, this.$totalBytesToTransfer
is valid as a verbatim command name in PowerShell, i.e. as an identifier at the start of a statement, so there's no syntax problem.
E.g., you can define a function literally named this.$totalBytesToTransfer
and call it:
function this.$totalBytesToTransfer { 'hi!' }
this.$totalBytesToTransfer # -> 'hi!'
However, when the same token is used as a command argument, $totalBytesToTransfer
would get expanded (interpolated), i.e. treated as a variable reference; that is, this.$totalBytesToTransfer
is implicitly treated like an expandable (double-quoted) string ("..."
):
$totalBytesToTransfer = 42
Write-Output this.$totalBytesToTransfer # -> 'this.42'
Given the above, your this.$totalBytesToTransfer
tokens are interpreted as follows:
# Call to (hypothetical) command 'this.$totalBytesToTransfer'
# with arguments '=' and 0
this.$totalBytesToTransfer = 0
# Call to (hypothetical) command 'this.$totalBytesToTransfer'
# with arguments '+=' and the value of the .length property of the
# object stored in variable $file.
this.$totalBytesToTransfer += $file.length
# Call to (hypothetical) command 'this.$totalBytesToTransfer'
# with arguments '=' and the concatenation of 'this.' and the
# the value of a (hypothetical) $totalBytesToTransfer variable.
this.$bytesLeftToTransfer = this.$totalBytesToTransfer
In the last statement above, the hypothetical $totalBytesToTransfer
variable isn't previously defined inside the method at hand, which causes PowerShell to report the error you saw.
Generally, note that PowerShell - as both a shell and a (very capable) scripting language - of necessity needs to marry two distinct syntax worlds:
- shell commands (commands followed by whitespace-separated arguments) vs.
- expressions (operator-based operations and method calls), as in traditional programming languages).
This necessitates two distinct parsing modes, as described in about_Parsing.
In short: The start of each statement determines which of the two parsing mode applies, which also applies to nested statements. See this answer for background information.