如何将自定义 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 展开了对话,希望这将是他们在未来版本中解决的问题。