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-ID: 3831877829

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

Ausgedruckt am: 22.11.2024 um 13:11 Uhr

Avihaa
Avihaa 05.09.2022, aktualisiert am 25.02.2023 um 17:26:59 Uhr
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]
Johann.Z
Johann.Z 05.09.2022 um 12:19:59 Uhr
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
Johann.Z
Lösung Johann.Z 02.11.2022 um 13:16:42 Uhr
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