SharePointVault ~/gotchas/powershell ⌕ Search 404 pages, error messages, scripts…Ctrl K ★ Star
M↓ README.mdM↓ ps7-ref-arguments-break-com-calls.md
sharepoint-vault›gotchas›powershell›ps7-ref-arguments-break-com-calls.mdhistoryedit on GitHub
● GOTCHApowershell· 2 min read

PowerShell 7 [ref] arguments break Office COM calls

applies to: PowerShell 7.x on Windows (Word/Excel/PowerPoint COM)reviewed: 2026-07-26#powershell#com#office-automation

In PowerShell 7 a [ref]-wrapped argument reaches the COM binder as a PSObject it cannot convert, so VBA-style calls like $doc.SaveAs2([ref]$path, [ref]$format) die with "Cannot convert … type psobject to type Object" — pass the values directly ($doc.SaveAs2($path, $format)); Office COM methods take them positionally just fine.

V PowerShellu 7 dorazí argument zabalený do [ref] do COM binderu jako PSObject, který neumí převést, takže volání ve stylu VBA $doc.SaveAs2([ref]$path, [ref]$format) spadne na „Cannot convert … type psobject to type Object“ – předávej hodnoty přímo ($doc.SaveAs2($path, $format)); pozičně je COM metody Office berou bez problému.

Symptom

Automating Word from PowerShell 7, with the [ref] pattern that decades of VBA-derived examples (and Windows PowerShell 5.1 experience) suggest:

$word = New-Object -ComObject Word.Application
$doc  = $word.Documents.Add()
$doc.SaveAs2([ref]$file, [ref]$format)
Exception setting "SaveAs2": Cannot convert the "C:\out\Document.docx" value of
type "psobject" to type "Object".

The message names your string but claims it is a psobject — which is the actual clue.

Cause

Office COM methods declare parameters as ref object, which is why old samples wrap everything in [ref]. PowerShell 7's COM interop wraps the referenced value in a PSObject on the way to the binder, and the conversion to the raw object the method expects fails. Windows PowerShell 5.1 marshalled the same pattern without complaint, so scripts break precisely when migrated to PS 7.

Fix

Drop the [ref] and pass plain values positionally:

$doc.SaveAs2($file, 16)     # 16 = wdFormatDocumentDefault, 17 = wdFormatPDF
$wb.SaveAs($file, 51)       # 51 = xlOpenXMLWorkbook
$pres.SaveAs($file, 24)     # 24 = ppSaveAsOpenXMLPresentation

The interop layer handles the by-ref plumbing itself; you only ever needed [ref] for parameters whose output you read back.

Notes

  • Use numeric constants (-2 = wdStyleHeading1 etc.) instead of localized style names — one more habit from English-only samples that breaks on non-English Office.
  • Release COM objects ([Runtime.InteropServices.Marshal]::ReleaseComObject) and Quit() in a finally, or orphaned WINWORD.EXE processes accumulate behind failed runs.
Was this helpful?ask or add your experience on GitHub →
Saved you an hour? A star on GitHub helps other SharePoint people find the vault.★ Star on GitHub
last reviewed: 2026-07-26last updated: 2026-09-24historyedit on GitHubview source