【发布时间】:2016-02-05 17:06:03
【问题描述】:
这是目前让我很头疼的示例代码。
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)
}
}
这个类可以这样使用
$notepad = [AppInstance]::new()
$notepad.Hide()
$notepad.Show()
基本上,我要做的是从user32.dll 导入一个函数作为[Win32.NativeMethods] 类型,然后在class 中使用此类型。
如果我在Powershell_ISE 中单独执行Add-Type 语句,则会创建类型,随后脚本就可以正常工作。
但是,当我尝试在手动创建类型之前执行整个脚本时,我收到以下 Powershell 解析器错误
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
解析器似乎忽略了Add-Type 语句并在执行前退出。
有什么办法可以解决这个问题吗?也许有using 声明?
或者,有没有办法告诉解析器该类型是动态创建的?
编辑 1:
我已阅读Using .Net Objects within a Powershell (V5) Class 的答案,接受的答案不是我的问题的答案。将一个简单的脚本拆分成多个文件并不是一个真正的答案。
我要问的是天气是否有办法告诉解析器该类型是动态创建的。
编辑 2:
为了进一步澄清这一点,这里的代码等效于上面的代码,但使用functions而不是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)
}
此代码将完美地解析和执行。 classes 是否由解析器以不同于脚本其余部分的方式处理?
【问题讨论】:
-
可能是重复的,但在另一个问题上接受的答案并不是真正的答案。
-
怎么不是答案?它解释了问题并给出了解决方案?
-
也许我有点急于放弃它作为不是一个答案。然而,我希望更深入地了解为什么解析器会忽略带有类的“Add-Type”,而不是在普通脚本中。这就是为什么我问了一个具体的问题。还是我需要改写?
-
@JanChrbolka 建议的副本解释它:“在执行脚本中的第一条语句之前,每个 PowerShell 脚本都被完全解析。一个无法解析的类型名称令牌 在类定义中是认为是解析错误。”
-
这实际上是我的观点。我了解每个脚本首先由解析器解析。我试图找出的是为什么解析器没有选择类型定义。您在下面的回答清除了这一点。谢谢。