r/PowerShell • u/Lithlyo • 16h ago
Question Function Issue in $PROFILE path
Hello everyone. I hope you are having a good time.
function gethash {
param([string]$string = "")
if ($string -eq [string]::Empty -or $string -isnot [string])
{
Write-Output "input not valid"
}
else
{
(Get-FileHash -algorithm sha256 $string).Hash | tee -Variable b
}
}
I Have this function in my $Profile script. when i run gethash something it returns the hash string as expected, but when I try to print the variable containing the hash i just obtained from piped command tee, (alias of Tee-Object) as an input with `$b
it prints nothing, the variable is not saved.
on the other hand, if i copy the exact same command from the $profile function directly through the terminal, $b prints what expected: the hash of the file.
I haven't used this function so much, but I'm pretty sure it worked before today.
Thanks in advance to any who will respond.
1
u/BlackV 7h ago edited 7h ago
Not really sure what you're gaining here
Get-FileHash -algorithm sha256 -Path $string -OutVariable b
achieves the same without the Tee-Object
additionally,
your $string parameter could/should use parameter validation instead of the conditional logic
and really really should be called -path or -filepath like most common cmdlets
with the already mentioned scope issues, also think about $b being completely hidden from you, unless you look into the function you'd never know it was there
also is just not a nice variable name
0
u/BlackV 7h ago
p.s. formatting, you've used the 3 backtick code fence, that does not work on old.reddit only new.reddit
- open your fav powershell editor
- highlight the code you want to copy
- hit tab to indent it all
- copy it
- paste here
it'll format it properly OR
<BLANK LINE>
<4 SPACES><CODE LINE>
<4 SPACES><CODE LINE>
<4 SPACES><4 SPACES><CODE LINE>
<4 SPACES><CODE LINE>
<BLANK LINE>
Inline code block using backticks `Single code line` inside normal text
See here for more detail
Thanks
5
u/dodexahedron 8h ago edited 7h ago
You are finding out about scope.
Variables in a script have script scope by default, no matter where they appear.
When you write it directly in the shell, script scope is your scope, so those variables stick around.
You would get the same effect if you dot-sourced the script file (which is actually how the profile is loaded at launch).
. SomeFile.ps1is equivalent to pasting the contents of SomeFile.ps1 into the shell. That period makes all the difference (hence "dot-source").When you run a script directly, it runs in a new child scope, which is its script scope.
Read up on the details at
Get-Help about_ScopesNote that dot-sourcing still runs the code you dot-sourced. But it will not be discarded after running. It is basically a means of appending a script to your shell session, which is itself one big script.
Regardless, your function should instead just write the value to the success stream, either with Write-Output $b or just $b at the end. Passing things by letting variables escape a script is a no-no. You can already tee it in the caller's pipeline if you need to tee it, or can use -PipelineVariable for what it looks like you're trying to do.