This isn't strictly an answer, but I tested your code as is and it worked for me, even without running it as an admin.
That is, my first batch file had the following:
PowerShell -NoProfile -ExecutionPolicy Bypass -File C:\file.ps1
and it worked fine. It showed a blank form which I was able to close. Then, I tested your batch file and it worked fine too. When running as an admin, it opened a secondary PowerShell console before opening the form.
You mentioned that it doesn't find the classes that you use. Are you sure those classes aren't being created or imported in your PowerShell profile script ($PROFILE)?
If so, note that the command line in your batch file includes "-NoProfile", which will skip loading any profile scripts.
Edit: I don't have enough reputation yet to post comments, so I will follow up here
In response to:
Ok then I get an error for each type that it's not found, like
System.Windows.Forms.Label
What is the exact error message? What does the line look like that references System.Windows.Forms.Label?
I modified my own test script as follows:
Add-Type -AssemblyName System.Windows.Forms
$window = New-Object System.Windows.Forms.Form
$window.Width = 400
$window.Height = 600
$label = New-Object System.Windows.Forms.Label
$label.Text = 'This is a test'
$window.Controls.Add($label)
[void]$window.ShowDialog()
I ran this snippet using the same batch file you provided, and it started fine with no errors.
There's something going on that we haven't discovered yet.
Update 2:
Okay I see the problem now. You're attempting to define PowerShell classes based on .NET types imported via Add-Type. The problem is that class definitions are resolved during parsing, and not at runtime, meaning the Add-Type commands haven't been executed yet.
This issue is addressed in the following answer: https://stackoverflow.com/a/34637458/18815893
as an answer to Using .NET objects within a Powershell (V5) class
In short, there are two solutions offered:
Put the class definitions in a separate script that is dot-sourced from the parent script after the Add-Type definitions are called, or
Wrap the class definitions in a here-string and use Invoke-Expression.