Here is example code that is causing me lots of headaches at the moment.
if (("Win32.NativeMethods" -as [type]) -eq $null){
Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
' -name NativeMethods -namespace Win32
}
class AppInstance
{
[string]$App = 'Notepad.exe'
[IntPtr]$hWnd = 0
[System.Object]$process
AppInstance () {
Start-Process $this.App
$this.process = get-process ($this.App.split('.'))[0]
start-sleep -Milliseconds 100
$this.hWnd = $this.process.MainWindowHandle
}
[void] Show () {
[Win32.NativeMethods]::ShowWindowAsync($this.hWnd, 3)
}
[void] Hide () {
[Win32.NativeMethods]::ShowWindowAsync($this.hWnd, 2)
}
}
This class can be used like so
$notepad = [AppInstance]::new()
$notepad.Hide()
$notepad.Show()
Basically, what I'm trying to do is to import a function from user32.dll
as type [Win32.NativeMethods]
and then use this type in a class
.
If I execute the Add-Type
statement separately in Powershell_ISE
the type gets created and subsequently the script works just fine.
However, when I try to execute the whole script before creating the type manually, I get the following Powershell parser error
At C:\class.ps1:26 char:10
+ [Win32.NativeMethods]::ShowWindowAsync($this.hWnd, 3)
+ ~~~~~~~~~~~~~~~~~~~
Unable to find type [Win32.NativeMethods].
At C:\Uclass.ps1:31 char:10
+ [Win32.NativeMethods]::ShowWindowAsync($this.hWnd, 2)
+ ~~~~~~~~~~~~~~~~~~~
Unable to find type [Win32.NativeMethods].
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TypeNotFound
Looks like the parser is ignoring the Add-Type
statement and exiting before execution.
Is there any way to overcome this issue? Maybe with a using
statement?
Or, is there any way to tell the parser that the type is dynamically created?
EDIT 1:
I have read the answer to Using .Net Objects within a Powershell (V5) Class and the accepted answer is not an answer to my question. Splitting a simple script into multiple files is not really an answer.
What I'm asking is weather there is a way to tell the parser that the type is dynamically created.
EDIT 2:
To clarify this a little further here is code equivalent to the one above, but implemented using functions
instead of classes
.
if (("Win32.NativeMethods" -as [type]) -eq $null){
Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
' -name NativeMethods -namespace Win32
}
[string]$script:App = 'Notepad.exe'
$process = Start-Process $App -PassThru
function Show () {
[Win32.NativeMethods]::ShowWindowAsync($process.MainWindowHandle, 3)
}
function Hide () {
[Win32.NativeMethods]::ShowWindowAsync($process.MainWindowHandle, 2)
}
This code will parse and execute perfectly fine. Are classes
handled by the parser in a different way to rest of the script?