如何将自定义COM枚举指定为PowerShell方法参数

时间:2016-06-09 22:38:58

标签: powershell enums com

如何为在COM对象中声明的枚举创建引用以传递给需要它的方法?具体来说,第三方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对象资源管理器的屏幕截图,以防提供任何线索。

COM Object in Visual Studio Object Explorer

4 个答案:

答案 0 :(得分:3)

我们最终在COM对象周围使用了编译的C#interop包装器。我能够指定-- \i tmp.sql -- NOTE: date and domain are keywords in SQL CREATE TABLE ztable ( zdomain TEXT NOT NULL , zdate DATE NOT NULL , visitors INTEGER NOT NULL DEFAULT 0 , hits INTEGER NOT NULL DEFAULT 0 , PRIMARY KEY (zdomain,zdate) ); INSERT INTO ztable (zdomain,zdate,visitors,hits) VALUES ('www.domain1.com', '2016-04-12' ,1231 ,23423 ) ,('www.domain1.com', '2016-04-13' ,1374 ,26482 ) ,('www.domain1.com', '2016-04-17' ,1262 ,21493 ) ,('www.domain3.com', '2016-04-14' ,3245 ,53471 ) -- << cheating! ,('www.domain3.com', '2016-04-15' ,2435 ,34571 ) ,('www.domain3.com', '2016-04-16' ,2354 ,35741 ) ,('www.domain2.com', '2016-05-09' ,2345 ,35471 ) ; -- Create "Calendar" table with all possible dates -- from the existing data in ztable. -- [if there are sufficient different domains -- in ztable there will be no gaps] -- [Normally the table would be filled by generate_series() -- or even a recursive CTE] -- An exta advantage is that a table can be indexed. CREATE TABLE date_domain AS SELECT DISTINCT zdate AS zdate FROM ztable; ALTER TABLE date_domain ADD PRIMARY KEY (zdate); -- SELECT * FROM date_domain; -- Finding the closest previous record -- without using window functions or aggregate queries. SELECT d.zdate, t.zdate, t.zdomain ,t.visitors, t.hits , (d.zdate <> t.zdate) AS is_fake -- for fun FROM date_domain d LEFT JOIN ztable t ON t.zdate <= d.zdate AND NOT EXISTS ( SELECT * FROM ztable nx WHERE nx.zdomain = t.zdomain AND nx.zdate > d.zdate AND nx.zdate < t.zdate ) ORDER BY t.zdomain, d.zdate ; 作为参数,并使用case语句从枚举中传递正确的值。据我所知,没有办法直接从Powershell执行此操作,并且需要将COM对象包装在托管代码中。

我们已经打开了一个与Globalscape的对话框,希望这将是他们将来发布的内容。

答案 1 :(得分:1)

我们可以尝试通过自己创建枚举来欺骗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中。

答案 2 :(得分:0)

此时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服务器的地方工作。

答案 3 :(得分:0)

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

例如:

解决方案是使用C:\Windows\SysWOW64\WindowsPowerShell\中的32位PowerShell如果你需要远程调用它,你可能必须明确地使用&amp;操作