【问题标题】:How to specify custom COM enum as PowerShell method parameter如何将自定义 COM 枚举指定为 PowerShell 方法参数
【发布时间】:2016-10-10 18:38:29
【问题描述】:

如何为在 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 Management Framework 升级到更新版本。

更新:这是来自 Visual Studio 对象浏览器的屏幕截图,以防提供任何线索。

【问题讨论】:

  • a) 试试$obj.SetHomeDir([Int32]1) b) 您使用的是 32 位还是 64 位 powershell?如果 64 尝试 32 位。
  • 不要认为它适用于字符串名称,是吗? "abTrue"
  • 尝试字符串名称的好主意 - 但不,它会反弹Type Mismatch

标签: powershell enums com


【解决方案1】:

我们最终在 COM 对象周围使用了一个已编译的 C# 互操作包装器。我能够将int 指定为参数,并且只使用case 语句从枚举中传递正确的值。据我所知,没有办法直接从 Powershell 执行此操作,并且需要将 COM 对象包装在托管代码中。

我们已经与 Globalscape 建立了对话,希望这将是他们在未来版本中解决的问题。

【讨论】:

    【解决方案2】:

    我们可以尝试通过自己创建枚举并将其传递给函数来欺骗 com 对象:

    如果您可以升级到 Powershell 5,请尝试(在 Powershell - enum 是版本 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 中。

    【讨论】:

    • 我尝试了 Add-Type 方法,但它不起作用 - 它也抱怨类型不匹配。感谢您的建议!
    【解决方案3】:

    PowerShell v2.0 在这一点上已经过时了,但它不应该在这里阻止你。 SFTPAdvBool 似乎来自 GlobalScape EFT Server COM API,所以这就是我的假设。

    问题是你需要一个SFTPAdvBool 类型的值,根据 C# scripting examples (参见 ConfigureUser.cs 的一种用途)。对于 .Net 对象,您可以将其定义为 [SFTPAdvBool]::abTrue[SFTPCOMINTERFACELib.SFTPAdvBool]::abTrue,但我不确定这是否可行。我以前没有在 PowerShell 中使用过 COM 枚举。您可能需要New-Object -ComObject SFTPCOMINTERFACELib.SFTPAdvBool 或一些变体。

    如果没有任何效果,您可以使用 VBScript 或 C#,或者联系 GlobalScape,希望他们加入 21 世纪并放弃 COM,或者使用 WinSCP 的 .Net 库......但我敢打赌,因为你不能'正在为 EFT 服务器付费的地方工作。

    【讨论】:

    • 感谢您的建议 - 我们已联系 GlobalScape 并正在等待他们的回复。不幸的是,SFTPAdvBool 和其他 COM 枚举没有在 PowerShell 中作为类公开,因此我可以在它们上使用 New-Object 或静态成员访问运算符 - 至少我已经能够预测。
    【解决方案4】:

    在他们的知识库中有一些提示,库并不总是在进程外正常工作,因此可以远程应用,或者在 64 位进程中使用 32 位库时。

    例如:

    解决方案是在C:\Windows\SysWOW64\WindowsPowerShell\ 中使用 32 位 powershell。如果您需要远程调用它,您可能必须使用 & 运算符显式执行此操作。

    【讨论】:

    • 我们服务器上安装的版本是 32 位的,因此我们必须使用正确的 PowerShell 版本。我在您的链接中没有看到任何解决引用 COM 库中定义的枚举的一般问题的内容。如果有,您能否用该信息扩展您的答案?
    • 没有这样的问题,根据我的评论,枚举应该作为 int32 传递,也就是说,它只是特定 int 值的一组别名,它没有附加真正的类型信息到变量.... 有时人们使用自定义的Invoke 实现,它也将接受其他东西,如 int16 或字符串,但 Int32 每次都应该工作。如果不是,你有一个不同的问题。
    • 我同意它应该只是一个 int - 这就是它的基本存储方式。这就是为什么我尝试了很多方法来正确“装箱”它以匹配方法签名并希望避免MX Error。我用 PowerShell 认为的方法签名更新了这个问题,希望能更清楚地了解这个主题。
    • 在你说你尝试过[int16]演员的问题中。你试过[int32]吗?
    • 是的 - 我尝试了 long 和 Int 16,32,64 以及它们的无符号变体以获得良好的度量。他们都回击了可怕的MX Error: 7,我非常感谢您的想法并帮助我解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 2022-01-05
    • 2013-10-02
    相关资源
    最近更新 更多