PowerShell logon script form oddities

I was recently asked to add some logic to our old vbs logon script, but since the old one had a lot of unused functions and needed a rewrite anyway I decided to try to rewrite it in PowerShell. Since I wanted to give some user feedback when something went wrong I need a function to present data. First of all I wrote the script and got it working just as I wanted, but when I then applied it as a logon script it did not behave in the same way any more. I still don’t why it behaves the way it does but I will present my findings and the workarounds I found. Since I wanted to format the output to the user and also needed the form to be “topmost” I decided to go with the “Forms” assembly instead of MessageBox.

The behavior with the code snippets below is based on PowerShell logon script and the GPO setting for “’Run logon scripts visible” is set to “Not configured”. The reason I have it this way is that even without it the script works and when there is no output it runs in the background. If enabled the user will see a “PowerShell”-command prompt every time they logon which is annoying in my opinion :)

This code uses MessageBox and works both standalone and as a GPO:

[void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[System.Windows.Forms.MessageBox]::Show("text" , "This is a MessageBox") |Out-Null

 

This code uses the forms and does only work as a script, when used in a GPO this code will hang the script in the background waiting for user input.

[void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
    $Form = New-Object 'System.Windows.Forms.Form'
	$Form.Text = "This is a test"
	$Form.AutoScroll = $True
	$Form.AutoSizeMode = "GrowAndShrink"
	$Form.BackColor = "White"
	$Form.Topmost = $true
	$Form.ShowDialog()

 

If you add a MessageBox before the form code above both the MessageBox and the form will be displayed properly, the downside is of course that you probably don’t need two windows with information.

[void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
[System.Windows.Forms.MessageBox]::Show("text" , "This is a MessageBox") |Out-Null
    $Form = New-Object 'System.Windows.Forms.Form'
	$Form.Text = "This is a test"
	$Form.AutoScroll = $True
	$Form.AutoSizeMode = "GrowAndShrink"
	$Form.BackColor = "White"
	$Form.Topmost = $true
	$Form.ShowDialog()

 

I did find a workaround for just displaying a form and here is the code needed to get just a form displayed properly when used in a GPO.

[void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")

    $Form = New-Object 'System.Windows.Forms.Form'

    #Create Form fix for GPO
	$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'

	$Form_StateCorrection_Load=
	{
		$Form.WindowState = $InitialFormWindowState
	}

    $Form.Text = "This is a test"
	$Form.AutoScroll = $True
    $Form.AutoSizeMode = "GrowAndShrink"
	$Form.BackColor = "White"
	$Form.Topmost = $true

    #Load Fix
	$InitialFormWindowState = $Form.WindowState
	$Form.add_Load($Form_StateCorrection_Load)

    $Form.ShowDialog()

The problem with the code above is that even if the form gets displayed properly the “$Form.Topmost = $true” is ignored and the form might be hidden in the background if anything else is loaded before the script returns any output.

Since I also wanted a BallonTip giving user info I added that to the code above before the form was presented and for some reason that also made “$Form.Topmost = $true” working again. So the final code that works as you should expect both as a GPO and a standalone script is the following:

[void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")

   	$objBalloon = New-Object System.Windows.Forms.NotifyIcon 
	$objBalloon.Icon = "stop.ico"

	# You can use the value Info, Warning, Error
	$objBalloon.BalloonTipIcon = "Info"

	# Put what you want to say here for the Start of the process
	$objBalloon.BalloonTipTitle = "Begin Title" 
	$objBalloon.BalloonTipText = "test"
	$objBalloon.Visible = $True 
	$objBalloon.ShowBalloonTip(10000)

    $Form = New-Object 'System.Windows.Forms.Form'

    #Create Form fix for GPO
	$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'

	$Form_StateCorrection_Load=
	{
		$Form.WindowState = $InitialFormWindowState
	}

    $Form.Text = "This is a test"
	$Form.AutoScroll = $True
    $Form.AutoSizeMode = "GrowAndShrink"
	$Form.BackColor = "White"
	$Form.Topmost = $true

    #Load Fix
	$InitialFormWindowState = $Form.WindowState
	$Form.add_Load($Form_StateCorrection_Load)

    $Form.ShowDialog()

Beware of any line breaks in the code above, for example the “[void}[reflec…” should all be one one line.

Why PowerShell behaves differently when run from a GPO I do not know, these are just my findings and I wanted to share my workaround if any of you also wanted to rewrite your old logon vbscript to a more modern PowerShell script.

Hope this saves someone else some troubles!

Written by , Posted .
  • http://myITforum.com/myitforumwp/community/members/dennislviridis/ Dennis

    I actually have trouble following your code :-(

    You create a reference to the the form when created?
    And then you relead that reference some how to work around the bug in PS?

    I find the labeling very confusing. Could you please clarify?

    • http://myITforum.com/myitforumwp/community/members/matbe/ Matt Benninge

      Hi Dennis,

      I’m sorry but I do not understand you question, what exactly is it you need clarified?
      Just to be clear, I am not a coder so I can not explain in detail what actually goes on in the code. The workaround I found (on the net, but i can remeber exactly where) was another way to load a form so I cannot explain why it works and why not without it. The purpose of the post was mearly to show what works and what does not and to share my findings.

      /Matt

  • http://myITforum.com/myitforumwp/community/members/dennislviridis/ Dennis

    Never mind.
    This specific fix was already implemented by PowerShell Studio 2012 in the autogenerated “hidden” parts.

  • http://myITforum.com/myitforumwp/community/members/matbe/ Matt Benninge

    Ok!

    And nice to see some more swedes here ;)

  • Dwayne Allen

    I ran into the same issue with $Form.TopMost = $True not applying when running an SCCM package. Adding the BalloonTip did work as a work around. Did you ever figure out what was causing the issue in the first place?