如果调用Add-Type
函数在函数中添加一段C#代码,那么一旦函数执行完毕,“type”会被垃圾收集吗?或者该类型是否仍然存在于内存中,因为它是加载到AppDomain中的(虚拟)程序集的一部分? (因此是“内存泄漏”)
在下面的Lock-WorkStation
定义中,Add-Type
用于添加用C#编写的代码:
function Lock-WorkStation {
$signature = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
'@
$name = "Win32LockWorkStation"
$LockWorkStation = Add-Type -MemberDefinition $signature -Name $name -Namespace Win32Functions -PassThru
$LockWorkStation::LockWorkStation() | Out-Null
}
我的问题是,如果这个函数被称为多个类型,那么它会不断地解析并添加C#代码作为(虚拟)程序集。 (或者是垃圾收集?)
将它写成:
更好吗?Function Lock-WorkStation {
if (!$Global:LockWorkStation) {
$signature = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
'@
$name = "Win32LockWorkStation"
$global:LockWorkStation = Add-Type -MemberDefinition $signature -Name $name -Namespace Win32Functions -PassThru
}
$global:LockWorkStation::LockWorkStation() | Out-Null
}
这样C#代码只被实例化为程序集一次?
答案 0 :(得分:1)
测试结果类型是否已存在:
function Lock-WorkStation {
$name = 'Win32LockWorkStation'
$namespace = 'Win32Functions'
$signature = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
'@
if(-not ($LockWorkStation = "$namespace.$name" -as [type])){
$LockWorkStation = Add-Type -MemberDefinition $signature -Name $name -Namespace $namespace -PassThru
}
$LockWorkStation::LockWorkStation() | Out-Null
}
答案 1 :(得分:1)
谢谢Mathias的回答。然而,我的问题是关于调用Add-Type
每次调用时是否实例化类型。我查看了文档,其中说:
会话中的类型名称和命名空间必须为唯一。您无法卸载类型或更改它。如果需要更改类型的代码,则必须更改名称或启动新的Windows PowerShell会话。否则,命令失败。 (Add-Type Documentation)
Add-Type
将在第一次调用时实例化该类型。在具有相同参数的后续调用中,因为该类型已存在,所以它将不执行任何操作。因此,在if
语句中包含Add-Type
条件的唯一原因是出于效率原因,因为调用Add-Type
会产生检查类型是否已存在的开销。
您的if
条件:
-not ($LockWorkStation = "$namespace.$name" -as [type])
恕我直言,效率不高,因为它使用字符串插值来计算类型名称,然后检查类型是否存在,然后每次运行时都将类型分配给变量。
相反,您可以设置一次类型变量(范围为Script:
)。 if
语句可以检查它是否为null,如果是,则实例化它:
function Lock-WorkStation {
if ($Script:Win32LockWorkStation -eq $null) {
$namespace = 'Win32Functions'
$name = 'Win32LockWorkStation'
$signature = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
'@
$Script:Win32LockWorkStation = Add-Type -Namespace $namespace -Name $name -MemberDefinition $signature -PassThru
}
$Script:Win32LockWorkStation::LockWorkStation() | Out-Null
}
如果您愿意,可以查看performance comparison在函数中使用Add-Type
的不同方法。