I've written a small program with PowerShell 5 which works. With PowerShell 7, the script stops executing.
This is a minimal sample I could build to reproduce the issue.
Without the dialog or the Out-Speech function, it's working.
I don't know why this combination isn't working.
I start my script with a small batch
pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0test.ps1"
pause
and
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0test.ps1"
pause
Start the script and close the window.
function Ask4Password()
{
$pwdForm = New-Object System.Windows.Forms.Form
$pwdForm.Text = 'Please enter password'
$pwdForm.Size = New-Object System.Drawing.Size(300,140)
$pwdForm.StartPosition = 'CenterScreen'
$pwdForm.KeyPreview = $true
$pwdForm.Topmost = $true
[void] $pwdForm.ShowDialog()
return 'abc'
}
function Out-Speech( $text )
{
$speechy = New-Object 鈥揅omObject SAPI.SPVoice
[void]$speechy.Speak( $text, 1 ) # 1 = async
}
# only needed for PowerShell 5
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
Ask4Password
Write-Host 'Wrong Password'
Out-Speech 'Wrong Password'
Script should exit like with PowerShell 5
Execution stops
Name Value
---- -----
PSVersion 7.0.0
PSEdition Core
GitCommitId 7.0.0
OS Microsoft Windows 10.0.18363
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Follow works in PowerShell Core:
[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
$pwdForm = New-Object System.Windows.Forms.Form
I wouldn't be at all surprised if the COM object either works differently with .NET Core or simply doesn't work. I've not had a great many COM objects work well in .NET Core.
The hang is definitely worth investigating.
Pragmatically speaking, the problem only arises due to the _asynchronous_ call to .Speak(), and even though Windows PowerShell doesn't _hang_, the speech output _doesn't actually work_ - unless you make the call _synchronous_, simply by omitting the 1 argument: $speechy.Speak($text)
You can also avoid the hang if you explicitly release the COM component before exiting your script (though speech output still won't work): [System.Runtime.InteropServices.Marshal]::ReleaseComObject($speechy)
@Jawz84, .NET Core 3 added WinForms and WPF support (on Windows), so PowerShell 7 automatically supports it too.
@Tragen, as an aside, I suggest using the PowerShell-idiomatic way of loading a well-known assembly (by simple name):
Add-Type -AssemblyName System.Windows.Forms, rather than the declared-obsolete [System.Reflection.Assembly]::LoadWithPartialName method.
Thanks for the hint about loading the the assembly. It's an old script.
I also think you should investigate it.
It's not a problem about COM not working, But the async speed ouput or something else seems to block the exit.
Most helpful comment
Follow works in PowerShell Core: