Hello,
The reason your query file is outputting $instance,$port literally is because PowerShell does not expand variables inside the SQL script when you pass it as an external file. The SQL engine only sees the text in the file, not the PowerShell variables. To solve this, you need to read the query file into PowerShell as a string, perform variable substitution there, and then pass the resulting query string to Invoke-Sqlcmd.
For example, instead of letting SQL interpret $instance and $port, you should load the file with Get-Content and replace placeholders before execution. A common approach is to use a token in the SQL file, such as {{INSTANCE}} and {{PORT}}, then in PowerShell do something like:
powershell
$queryTemplate = Get-Content "C:\path\to\query.sql" -Raw
$query = $queryTemplate -replace "{{INSTANCE}}", $instance -replace "{{PORT}}", $port
$results = Invoke-Sqlcmd -ServerInstance "$instance,$port" -Query $query
$results | Format-Table
This way, the substitution happens in PowerShell before the query is sent to SQL Server. If you keep $instance inside the SQL file, SQL Server will never expand it because it doesn’t know about PowerShell variables.
So the correct method is: treat the SQL file as a template, replace placeholders with PowerShell variables, then run the modified query string against each instance. That ensures the values from your CSV are injected properly into the query at runtime.
I hope you've found something useful here. If it helps you get more insight into the issue, it's appreciated to accept the answer. Should you have more questions, feel free to leave a message. Have a nice day!
Domic Vo.