如何将自定义 COM 枚举指定为 PowerShell 方法参数
How to specify custom COM enum as PowerShell method parameter
如何为在 COM 对象内声明的枚举创建引用以传递给需要它的方法?具体来说,第 3 方 COM 对象上有一个方法 SetHomeDir
,它将枚举作为唯一参数。参数期望的定义基本上是:
typedef enum
{
abFalse = 0,
abTrue = 1,
abInherited = -2
} SFTPAdvBool;
它似乎是在 COM 对象的某处定义的,但不是我可以使用 New-Object 创建的对象。我尝试了以下方法,它们都给出了相同的 MX Error: 7
响应:
$obj.SetHomeDir($true)
$obj.SetHomeDir(1)
$obj.SetHomeDir([Object]1)
$obj.SetHomeDir([Int16]1)
Exception calling "SetHomeDir" with "1" argument(s): "MX Error: 7 (00000007)"
以下是尝试其他一些方法的结果:
PS C:\> New-Object -ComObject SFTPCOMINTERFACELib.SFTPAdvBool
New-Object : Cannot load COM type SFTPCOMINTERFACELib.SFTPAdvBool.
PS C:\> [SFTPAdvBool]::abTrue
Unable to find type [SFTPAdvBool]:
make sure that the assembly containing this type is loaded.
PS C:\> [SFTPCOMINTERFACELib.SFTPAdvBool]::abTrue
Unable to find type [SFTPCOMINTERFACELib.SFTPAdvBool]:
make sure that the assembly containing this type is loaded.
COM 向 PowerShell 公开的方法签名如下所示:
PS C:\> $user.SetHomeDir
MemberType : Method
OverloadDefinitions : {void SetHomeDir (SFTPAdvBool)}
TypeNameOfValue : System.Management.Automation.PSMethod
Value : void SetHomeDir (SFTPAdvBool)
Name : SetHomeDir
IsInstance : True
注意:这是 运行 在 Windows Server 2008 R2 上的 PowerShell 2.0 下,但我会考虑将 Windows 管理框架升级到更新版本,如果必要的。
更新: 这是 Visual Studio 对象资源管理器的屏幕截图,以防提供任何线索。
PowerShell v2.0 在这一点上是过时的,但它不应该在这里阻止你。 SFTPAdvBool
似乎来自 GlobalScape EFT Server COM API,所以这就是我的假设。
根据 C# scripting examples,问题是您需要 SFTPAdvBool
类型的值(请参阅 ConfigureUser.cs 了解一种用法)。对于 .Net 对象,您可以将其定义为 [SFTPAdvBool]::abTrue
或 [SFTPCOMINTERFACELib.SFTPAdvBool]::abTrue
,但我不确定这是否可行。我以前没有在 PowerShell 中使用过 COM 枚举。您可能需要 New-Object -ComObject SFTPCOMINTERFACELib.SFTPAdvBool
或一些变体。
如果没有任何效果,您可以使用 VBScript 或 C#,或者联系 GlobalScape 希望他们加入 21 世纪并放弃 COM,或者使用 WinSCP 的 .Net 库...但我敢打赌您不能因为您在为 EFT 服务器付费的地方工作。
他们的知识库中有一些提示表明库在进程外并不总是正常工作,因此可以远程应用,或者在 64 位进程中使用 32 位库时。
例如:
解决方案是在 C:\Windows\SysWOW64\WindowsPowerShell\
中使用 32 位 powershell 如果您需要远程调用它,您可能必须使用 & 运算符显式地进行。
我们可以尝试通过自己创建枚举并将其传递给函数来欺骗 com 对象:
如果您可以升级到 Powershell 5,请尝试(在 Powershell 中 - 枚举是版本 5 中的新关键字):
Enum SFTPAdvBool
{
abFalse = 0
abTrue = 1
abInherited = -2
}
并调用:
$obj.SetHomeDir([SFTPAdvBool]::abTrue)
对于任何早于 PS 5 你可以尝试:
$code = @"
namespace SFTPCOMINTERFACELib {
public enum SFTPAdvBool {
abFalse = 0,
abTrue = 1,
abInherited = -2
}
}
"@
Add-Type -TypeDefinition $code -Language CSharpVersion3
并调用:
$obj.SetHomeDir([SFTPCOMINTERFACELib.SFTPAdvBool]::abTrue)
这基本上会创建一个 C# 枚举,并将其作为一种类型添加到 Powershell 中。
我们最终在 COM 对象周围使用了经过编译的 C# 互操作包装器。我能够指定一个 int
作为参数,并且只使用 case 语句从枚举中传递正确的值。据我所知,没有办法直接从 Powershell 执行此操作,需要将 COM 对象包装在托管代码中。
我们已经与 Globalscape 展开了对话,希望这将是他们在未来版本中解决的问题。
如何为在 COM 对象内声明的枚举创建引用以传递给需要它的方法?具体来说,第 3 方 COM 对象上有一个方法 SetHomeDir
,它将枚举作为唯一参数。参数期望的定义基本上是:
typedef enum
{
abFalse = 0,
abTrue = 1,
abInherited = -2
} SFTPAdvBool;
它似乎是在 COM 对象的某处定义的,但不是我可以使用 New-Object 创建的对象。我尝试了以下方法,它们都给出了相同的 MX Error: 7
响应:
$obj.SetHomeDir($true)
$obj.SetHomeDir(1)
$obj.SetHomeDir([Object]1)
$obj.SetHomeDir([Int16]1)
Exception calling "SetHomeDir" with "1" argument(s): "MX Error: 7 (00000007)"
以下是尝试其他一些方法的结果:
PS C:\> New-Object -ComObject SFTPCOMINTERFACELib.SFTPAdvBool
New-Object : Cannot load COM type SFTPCOMINTERFACELib.SFTPAdvBool.
PS C:\> [SFTPAdvBool]::abTrue
Unable to find type [SFTPAdvBool]:
make sure that the assembly containing this type is loaded.
PS C:\> [SFTPCOMINTERFACELib.SFTPAdvBool]::abTrue
Unable to find type [SFTPCOMINTERFACELib.SFTPAdvBool]:
make sure that the assembly containing this type is loaded.
COM 向 PowerShell 公开的方法签名如下所示:
PS C:\> $user.SetHomeDir
MemberType : Method
OverloadDefinitions : {void SetHomeDir (SFTPAdvBool)}
TypeNameOfValue : System.Management.Automation.PSMethod
Value : void SetHomeDir (SFTPAdvBool)
Name : SetHomeDir
IsInstance : True
注意:这是 运行 在 Windows Server 2008 R2 上的 PowerShell 2.0 下,但我会考虑将 Windows 管理框架升级到更新版本,如果必要的。
更新: 这是 Visual Studio 对象资源管理器的屏幕截图,以防提供任何线索。
PowerShell v2.0 在这一点上是过时的,但它不应该在这里阻止你。 SFTPAdvBool
似乎来自 GlobalScape EFT Server COM API,所以这就是我的假设。
根据 C# scripting examples,问题是您需要 SFTPAdvBool
类型的值(请参阅 ConfigureUser.cs 了解一种用法)。对于 .Net 对象,您可以将其定义为 [SFTPAdvBool]::abTrue
或 [SFTPCOMINTERFACELib.SFTPAdvBool]::abTrue
,但我不确定这是否可行。我以前没有在 PowerShell 中使用过 COM 枚举。您可能需要 New-Object -ComObject SFTPCOMINTERFACELib.SFTPAdvBool
或一些变体。
如果没有任何效果,您可以使用 VBScript 或 C#,或者联系 GlobalScape 希望他们加入 21 世纪并放弃 COM,或者使用 WinSCP 的 .Net 库...但我敢打赌您不能因为您在为 EFT 服务器付费的地方工作。
他们的知识库中有一些提示表明库在进程外并不总是正常工作,因此可以远程应用,或者在 64 位进程中使用 32 位库时。
例如:
解决方案是在 C:\Windows\SysWOW64\WindowsPowerShell\
中使用 32 位 powershell 如果您需要远程调用它,您可能必须使用 & 运算符显式地进行。
我们可以尝试通过自己创建枚举并将其传递给函数来欺骗 com 对象:
如果您可以升级到 Powershell 5,请尝试(在 Powershell 中 - 枚举是版本 5 中的新关键字):
Enum SFTPAdvBool
{
abFalse = 0
abTrue = 1
abInherited = -2
}
并调用:
$obj.SetHomeDir([SFTPAdvBool]::abTrue)
对于任何早于 PS 5 你可以尝试:
$code = @"
namespace SFTPCOMINTERFACELib {
public enum SFTPAdvBool {
abFalse = 0,
abTrue = 1,
abInherited = -2
}
}
"@
Add-Type -TypeDefinition $code -Language CSharpVersion3
并调用:
$obj.SetHomeDir([SFTPCOMINTERFACELib.SFTPAdvBool]::abTrue)
这基本上会创建一个 C# 枚举,并将其作为一种类型添加到 Powershell 中。
我们最终在 COM 对象周围使用了经过编译的 C# 互操作包装器。我能够指定一个 int
作为参数,并且只使用 case 语句从枚举中传递正确的值。据我所知,没有办法直接从 Powershell 执行此操作,需要将 COM 对象包装在托管代码中。
我们已经与 Globalscape 展开了对话,希望这将是他们在未来版本中解决的问题。