Sep 13 2022 04:41 PM - edited Sep 13 2022 04:46 PM
PS Newb on 5.1
When last we left our traveler, he had been taught many wonderous things by this community. Indeed, he went on to enjoy many care-free days frolicking amongst the Object, Methods, Properties, and $. He was researching error handling. $error and $PSItem had great info, but were too verbose. So he started delving into the bits and pieces of the info. Upon the discovery of "InvocationInfo" the cry of "Eureka" was heard.
And then it all went badly ...
So here is the snippet of my offending code. Upon inspection of this snippet you will observe that I have introduced the additional column "Bill" in my insert but have not provided a source for Bill. Great! Error ensues and we enter the "catch". In my thinking I should be printing the name of the script, and then printing the error's invocation info. However, as is probably evident to the learned I get something else.
foreach ($Row in $DataTable.Rows) {
$insert = "insert into grain.dbo.AA_TODDPS (tseq, tnum, tstr, bill)
Values({0}, {1}, '{2}')" -f $seqnewValue, ($Row.tnum + ($count * 100)), $Row.tstr
try
{
invoke-Sqlcmd -Query $insert -ServerInstance 'WME-VM10-RW'
} #end try
catch
{
write-output "Name = $PSItem.InvocationInfo.ScriptName"
$PSItem.InvocationInfo
throw
}
Name = Invalid column name 'bill'.
There are more columns in the INSERT statement than values specified in the VALUES clause. The number of values in the VALUES
clause must match the number of columns specified in the INSERT statement..InvocationInfo.ScriptName
MyCommand : Invoke-Sqlcmd
BoundParameters : {}
UnboundArguments : {}
ScriptLineNumber : 48
OffsetInLine : 9
HistoryId : 23
ScriptName : C:\Users\wmeadmin\Documents\PS\TagWork.ps1
Line : invoke-Sqlcmd -Query $insert -ServerInstance 'WME-VM10-RW'
PositionMessage : At C:\Users\wmeadmin\Documents\PS\TagWork.ps1:48 char:9
+ invoke-Sqlcmd -Query $insert -ServerInstance 'WME-VM10-RW'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot : C:\Users\wmeadmin\Documents\PS
PSCommandPath : C:\Users\wmeadmin\Documents\PS\TagWork.ps1
InvocationName : invoke-Sqlcmd
etc.
Looking at the documentation it sure looks like $PSItem can get you to InvocationInfo, and that InvocationInfo has a property named "Scriptname". However, no amount banging, pushing, and foul-languageof gets me anything like I want. I get the same thing with ScriptLineNumber, though I swear I had that working at one point.
UPDATE: As I continued to throw stuff at the wall, I realized that
$PSItem.InvocationInfo.ScriptName
$PSItem.InvocationInfo.ScriptLineNumber
alone give me what I expect. That makes me feel good, but is infuriating at the same time. Evidently there is some nuance (or just my own ignorance) that keeps me from getting what I expect.
Thanks.
Sep 13 2022 05:46 PM
Noting your update, it seems you've largely got your head around the original question (though correct me if I'm wrong), so I'll keep this one brief.
Noting your Write-Output on line 13, specifically focusing on the variable reference embedded in the string, that's not going to work as you might intuitively thing it will.
PowerShell's default parsing of variables in strings is pretty basic, and where you think you're accessing the the child variable InvocationInfo, and then its property ScriptName, you're not, as PowerShell will only parse the top-level $PSItem - again, this is by default.
To utilise multi-part references, you need to use the subexpression operator: $(). This is in the same spirit of prefixing strings in C# with the dollar sign where it treats the content inside the operator as code.
So, this:
write-output "Name = $PSItem.InvocationInfo.ScriptName"
Will become this:
Write-Output -InputObject ("Name = $($PSItem.InvocationInfo.ScriptName)");
Also, on the topic of $PSItem:
In order to avoid that easy-to-fall-into trap (where the current object changes), I'd suggest doing any of the following in the catch block:
That way, as you invariably do other things that may result in $_ / $PSItem changing, you're not caught trying to track down not-so-obvious issues like this one.
With what you're doing, tapping into InvocationInfo is the best resource, but purely as an FYI, if you're looking for a quicker way to fetch the script name or path from which it's running, check out the built-in $PSCommandPath (former) and $PSScriptRoot (latter), as these are easier to drop into string for substitution, in commandlets like Join-Path, etc.
As a final note, it's good to see you using throw. I see a lot of people report an error but fail to incorporate any kind of flow control - which you're clearly aware of through using throw.
Cheers,
Lain
Sep 19 2022 05:07 AM - edited Sep 19 2022 05:10 AM
OK. Let me see if I have this straight:
On a Tuesday, if I am wearing my yellow socks, and you are working from home at your stand-up desk it is Y, if you are sitting, or it is a Thursday and my socks don't match, it is N. However there is the case ...
I am sure it all makes sense when it all makes sense. I once understood the similar contortions that are intrinsic to "C" (I am a "C" guy. None of this new-fangled "C#" stuff).