在公开 PowerShell 模块成员时,我应该更喜欢 Export-ModuleMember 还是全局范围?

Should I prefer Export-ModuleMember or the global scope when exposing PowerShell module members?

我一直在编写一个 Cmdlet,并且为了保持界面整洁,我一直在使用 Export-ModuleMember.

手动导出我关心的功能

但是,有人指出我也可以将函数直接放在 global: scope 中,而无需调用 Export-ModuleMember.

哪个更好?

# Option A: Export-ModuleMember
function Do-Something {}
Export-ModuleMember -Function Do-Something

# Option B: global scope
function global:Do-AnotherThing {}

# Something else?

谢谢!


我的直觉是 Export-ModuleMember 更好,因为它让调用者决定函数最终在哪个范围内(例如,另一个 cmdlet 可以导入我的 cmdlet 而无需全局公开那些导出的函数),但我不是当然。

你说得对。不正确地导出函数会规避安装模块时通常预期的行为。

例如,Import-Module 可以防止 cmdlet 破坏当前会话已经可用的 cmdlet 等情况下的破坏。声明一个具有全局作用域的函数可以避免这种情况,并且很少有时候应该这样做,除非模块 的目的是 实际覆盖某些东西(比如它可能设置或修改以某种方式提示)。 按预期执行此操作应该crystal通过模块文档清楚地知道谁在安装模块。

Note: Clobbering is the same basic principle of overloading or overriding members in class inheritance. Creating a new entity with the same name that may (overload) or may not (override) have a different signature.

即使默认情况下 Import-Module 破坏错误,如果您需要会破坏现有命令的 cmdlet 并让用户选择是否允许,Import-Module -AllowClobber 是解决方案破坏。


但我也不推荐Export-ModuleMember either. Rather, you should prepare your module with a manifest (ModuleName.psd1) instead, and specify the exported functions and cmdlets there. There are also many other things you can set in the manifest as well

它的好处是使模块定义在操作上更容易理解。现在您不必用一堆 Export-ModuleMember 命令乱扔代码。

Note: If you don't specify the functions or cmdlets to export in your module manifest, or don't have one and do not make use of Export-ModuleMember, all functions and cmdlets will be exported. This may be desirable or it may not be for a given module, but it's important to understand.


关于编写模块的附加信息

根据评论中的要求,这里有一些关于设计和编写 PowerShell 模块的附加链接: