johann.z
Goto Top

GUI-Script funktioniert nur in ISE aber nicht als PS-Aufruf oder .exe

Hallo zusammen,

ich habe ein Script geschrieben, aber der funktioniert einwandfrei nur, wenn ich den in ISE oder Visual Studio starte.

Starte ich den z.B. über eine Verknüpfung:

%windir%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NonInteractive -File "C:\temp\GUI_im_Hintergund_Test\GUI_im_Hintergund_Test.ps1"  

und drücke einen der Buttons (egal welchen, auch X), dann erhalte ich eine Exception:

System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
bei System.Management.Automation.ScriptBlock.InvokeWithPipe(Boolean useLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Boolean propagateAllExceptionsToTop, List`1 variablesToDefine, Dictionary`2 functionsToDefine, Object args)
bei System.Management.Automation.ScriptBlock.InvokeAsDelegateHelper(Object dollarUnder, Object dollarThis, Object args)
bei System.Windows.Forms.Control.OnClick(EventArgs e)
bei System.Windows.Forms.Button.OnClick(EventArgs e)
bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
bei System.Windows.Forms.Button.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


Das Gleiche gilt auch als exe kompiliert.

Script besteht in wesentlichen aus drei Teilen:
GUI-Designer-Script
Script 1 (Hauptskript)
Script 2 (wird mittels Runspace aus Script 1 aufgerufen)

Kommunikation zwischen der GUI ist per
$global:synkTable = [System.Collections.Hashtable]::Synchronized(@{})
umgesetzt.

Ich vermute, es liegt an der, am User Scope oder so was in der Art, aber in komme nicht dahinter was genau.
Als ob, die GUI (Sub-Theard) nicht mit dem Haupt-Thread kommuniziren kann.

Code:

Script 1 (Hauptskript)

Add-Type -AssemblyName system.windows.forms;
[void][reflection.assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')  
[void][reflection.assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')  

$global:synkTable = [System.Collections.Hashtable]::Synchronized(@{})
$GUI_im_Hintergund_Test_FormClosing ={}
$button_leeren_Click = {}

if ($synkTable.iRS_GEN_Status -eq $null -or $synkTable.iRS_GEN_Status -in 'Completed', 'Failed', 'Stopped') {  
    .(Join-Path $PSScriptRoot 'GUI_im_Hintergund_Test.designer.ps1')   
    $RS_GEN = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
    $RS_GEN.Name = "RS_GEN";   
    $RS_GEN.ApartmentState = "STA";   
    $RS_GEN.ThreadOptions = "ReuseThread"   
    $RS_GEN.Open(); 
    $RS_GEN.SessionStateProxy.SetVariable('synkTable',$global:synkTable)  
    $synkTable.GUI_im_Hintergund_Test = $GUI_im_Hintergund_Test
    $iRS_GEN = [powershell]::Create().addScript({
    [System.Windows.Forms.Application]::Run($synkTable.GUI_im_Hintergund_Test)
    # $synkTable.GUI_im_Hintergund_Test.ShowDialog() # Funktioniert aber dennoch exception nach GUI Interaktion
    })
    $iRS_GEN.Runspace.Name = "iRS_GEN"; $iRS_GEN.Runspace = $RS_GEN  
    Register-ObjectEvent -InputObject $iRS_GEN -EventName InvocationStateChanged -SourceIdentifier "iRS_GEN_InvocationStateInfo" -Action {  
        $iRS_GEN_Status = $Event.SourceEventArgs.InvocationStateInfo.State
        $synkTable.iRS_GEN_Status = $iRS_GEN_Status
        if ($iRS_GEN_Status -in 'Completed', 'Failed', 'Stopped') {  
                $iRS_GEN.Runspace.Close(); 
                $RS_GEN.Dispose()
                Unregister-Event -SourceIdentifier $($Event.SourceIdentifier) 
                Remove-Job -Name $($Event.SourceIdentifier) 
        }} ; $iRS_GEN.BeginInvoke()}

Designer

[void][System.Reflection.Assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')  
[void][System.Reflection.Assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')  
$GUI_im_Hintergund_Test = New-Object -TypeName System.Windows.Forms.Form
[System.Windows.Forms.Button]$button_leeren = $null
[System.Windows.Forms.FolderBrowserDialog]$folderBrowserDialog_ScannPath = $null
[System.Windows.Forms.TextBox]$textBox1 = $null
[System.Windows.Forms.Button]$button1 = $null
function InitializeComponent
{
$resources = . (Join-Path $PSScriptRoot 'GUI_im_Hintergund_Test.resources.ps1')  
$button_leeren = (New-Object -TypeName System.Windows.Forms.Button)
$folderBrowserDialog_ScannPath = (New-Object -TypeName System.Windows.Forms.FolderBrowserDialog)
$textBox1 = (New-Object -TypeName System.Windows.Forms.TextBox)
$GUI_im_Hintergund_Test.SuspendLayout()
#
#button_leeren
#
$button_leeren.Anchor = ([System.Windows.Forms.AnchorStyles][System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right)
$button_leeren.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]641,[System.Int32]13))
$button_leeren.Name = [System.String]'button_leeren'  
$button_leeren.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]131,[System.Int32]30))
$button_leeren.TabIndex = [System.Int32]1
$button_leeren.Text = [System.String]'Leeren'  
$button_leeren.UseVisualStyleBackColor = $true
$button_leeren.add_Click($button_leeren_Click)
#
#folderBrowserDialog_ScannPath
#
$folderBrowserDialog_ScannPath.add_HelpRequest($folderBrowserDialog_ScannPath_HelpRequest)
#
#textBox1
#
$textBox1.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]12,[System.Int32]47))
$textBox1.Multiline = $true
$textBox1.Name = [System.String]'textBox1'  
$textBox1.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]760,[System.Int32]452))
$textBox1.TabIndex = [System.Int32]2
#
#GUI_im_Hintergund_Test
#
$GUI_im_Hintergund_Test.AutoScroll = $true
$GUI_im_Hintergund_Test.ClientSize = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]784,[System.Int32]511))
$GUI_im_Hintergund_Test.Controls.Add($textBox1)
$GUI_im_Hintergund_Test.Controls.Add($button_leeren)
$GUI_im_Hintergund_Test.Icon = ([System.Drawing.Icon]$resources.'$this.Icon')  
$GUI_im_Hintergund_Test.MinimumSize = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]800,[System.Int32]550))
$GUI_im_Hintergund_Test.Name = [System.String]'GUI_im_Hintergund_Test'  
$GUI_im_Hintergund_Test.Text = [System.String]'Test'  
$GUI_im_Hintergund_Test.TopMost = $true
$GUI_im_Hintergund_Test.ResumeLayout($false)
$GUI_im_Hintergund_Test.PerformLayout()
Add-Member -InputObject $GUI_im_Hintergund_Test -Name button_leeren -Value $button_leeren -MemberType NoteProperty
Add-Member -InputObject $GUI_im_Hintergund_Test -Name folderBrowserDialog_ScannPath -Value $folderBrowserDialog_ScannPath -MemberType NoteProperty
Add-Member -InputObject $GUI_im_Hintergund_Test -Name textBox1 -Value $textBox1 -MemberType NoteProperty
Add-Member -InputObject $GUI_im_Hintergund_Test -Name button1 -Value $button1 -MemberType NoteProperty
}
. InitializeComponent


Aufruf Verknüpfung (Ziehl: C:\Temp\GUI_im_Hintergund_Test):

%windir%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NonInteractive -File "C:\temp\GUI_im_Hintergund_Test\GUI_im_Hintergund_Test.ps1"

Ergebnis


Vielen Dank für die Hilfe
2022-09-05 06_46_53-window

Content-Key: 3831877829

Url: https://administrator.de/contentid/3831877829

Printed on: April 28, 2024 at 08:04 o'clock

Member: Avihaa
Avihaa Sep 05, 2022, updated at Feb 25, 2023 at 16:26:59 (UTC)
Goto Top
It could be PowerShell's default security level, which (IIRC) will only run signed scripts. That will tell PowerShell to allow local (that is, on a local drive) unsigned scripts to run. Then try executing your script again. You have to run Powershell with administrator privileges, at least under Windows 8!


[URL="https://anonigstalk.com/"]anonigviewer[/URL]
[URL="https://bingenerator.one/"]bingenerator[/URL]
Member: Johann.Z
Johann.Z Sep 05, 2022 at 10:19:59 (UTC)
Goto Top
Leider klappt es auch so nicht.
Beides als Administator ausgeführt, unterschidliche Scope's ausprobiert, set's in beiden Scripten eingebaut.
Get-ExecutionPolicy | Out-GridView hat Start als Administartor aus beiden Scripten Unrestricted angezeigt.
Alles hat nichts gebracht.
Außerdem hatte ich es auch zu Hause auf dem privaten PC (User Admin) probiert mit gleichen Ergebnis.
Es muss deneke ich etwas anders sein.
2022-09-05 12_08_28-window
2022-09-05 12_05_43-test
Member: Johann.Z
Solution Johann.Z Nov 02, 2022 at 12:16:42 (UTC)
Goto Top
die Ursache war recht trivial.
Da im exe oder ink Modus sich der Hauptthread beendet kann die Kommunikation per synkTable nicht mehr stattfinden deswegen hat es mit der ISE funktioniert und per exe und ink nicht.
Die Lösung den Hauptthread offen lassen z.B. per while(true) oder einfach Read.Line()

Vielen Dank für die Vorschläge