dbs*_*bso 8 powershell add-type winscp-net
我在PS中使用WinSCP Powershell Assembly.在其中一种方法中,我使用的是WinSCP中的各种类型.
只要我已经添加了程序集,这就可以正常工作 - 但是,由于Powershell在使用类时读取脚本的方式(我假设?),在加载程序集之前会抛出错误.
实际上,即使我将Write-Host放在顶部,它也不会加载.
在解析文件的其余部分之前,有没有办法强制运行某些东西?
Transfer() {
$this.Logger = [Logger]::new()
try {
Add-Type -Path $this.Paths.WinSCP
$ConnectionType = $this.FtpSettings.Protocol.ToString()
$SessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::$ConnectionType
HostName = $this.FtpSettings.Server
UserName = $this.FtpSettings.Username
Password = $this.FtpSettings.Password
}
Run Code Online (Sandbox Code Playgroud)
Protocol = [WinSCP.Protocol] :: $ ConnectionType
无法找到类型[WinSCP.Protocol].
mkl*_*nt0 12
正如您所发现的,PowerShell拒绝运行包含引用当时不可用(尚未加载)类型的类定义的脚本 - 脚本解析阶段失败.
using assembly在脚本的顶部语句不会在这种情况下帮助,因为在你的情况下,该类型是在一个上下文中引用PS类定义 -这可能会固定于PowerShell的核心,但是,在GitHub问题中正在跟踪所需的工作.正确的解决方案是创建一个脚本模块(*.psm1),其关联的manifest(*.psd1)通过RequiredAssemblies密钥声明包含引用类型的程序集作为先决条件.
如果不能使用模块,请参见底部的替代解决方案.
这是一个简化的演练:
创建测试模块tm如下:
在其中创建模块文件夹./tm和manifest(*.psd1):
# Create module folder
mkdir ./tm
# Create manifest file that declares the WinSCP assembly a prerequisite.
# Modify the path to the assembly as needed; you may specify a relative path, but
# note that the path must not contain variable references (e.g., $HOME).
New-ModuleManifest ./tm/tm.psd1 -RootModule tm.psm1 `
-RequiredAssemblies C:\path\to\WinSCPnet.dll
Run Code Online (Sandbox Code Playgroud)*.psm1在模块文件夹中创建脚本模块文件():
./tm/tm.psm1使用类定义创建文件; 例如:
class Foo {
# Simply return the full name of the WinSCP type.
[string] Bar() {
return [WinSCP.Protocol].FullName
}
}
Run Code Online (Sandbox Code Playgroud)
注意:在现实世界中,模块通常放置在其中定义的标准位置之一中$env:PSMODULEPATH,因此模块只能通过名称引用,而无需指定(相对)路径.
使用模块:
PS> using module ./tm; (New-Object Foo).Bar()
WinSCP.Protocol
Run Code Online (Sandbox Code Playgroud)
该using module语句导入模块 - 与 - 不同Import-Module- 也使模块中定义的类可用于当前会话.
由于RequiredAssemblies模块清单中的键导入模块隐式加载了WinSCP程序集,因此实例化Foo引用程序集类型的类成功.
如果您的用例不允许使用模块,您可以Invoke-Expression在紧要关头使用,但请注意,Invoke-Expression为了避免安全风险,通常最好避免使用,以避免安全风险[1]
.
# Adjust this path as needed.
Add-Type -LiteralPath C:\path\to\WinSCPnet.dll
# By placing the class definition in a string that is invoked at *runtime*
# via Invoke-Expression, *after* the WinSCP assembly has been loaded, the
# class definition succeeds.
Invoke-Expression @'
class Foo {
# Simply return the full name of the WinSCP type.
[string] Bar() {
return [WinSCP.Protocol].FullName
}
}
'@
(New-Object Foo).Bar()
Run Code Online (Sandbox Code Playgroud)
[1]在这种情况下,这并不是一个问题,但通常情况下,如果Invoke-Expression可以调用存储在字符串中的任何命令,将其应用于不完全受您控制的字符串可能会导致执行恶意命令.这个警告类似地适用于其他语言,例如Bash的内置eval命令.
另一种解决方案是将您的 Add-Type 逻辑放入单独的 .ps1 文件中(命名它AssemblyBootStrap.ps1或其他名称),然后将其添加到ScriptsToProcess模块清单的部分。ScriptsToProcess在根脚本模块 ( *.psm1) 之前运行,并且程序集将在类定义查找它们时加载。
| 归档时间: |
|
| 查看次数: |
3741 次 |
| 最近记录: |