▲F#和PowerShell模块

作为可能是人类世界最强大的Shell,PowerShell最大的特点是能够直接在命令间传递.NET对象,而支持这种能力的命令被称作cmdlet。自己编写PowerShell模块,就能给PowerShell扩展更多的cmdlet。

为何要写本文

通常来讲,PowerShell模块有两种:脚本模块和二进制模块。顾名思义,脚本模块基本上就是一组PowerShell脚本,而二进制模块,实质上是一个.NET类库。微软对于二进制模块的官方文档中,只提供了C#的范例;但鉴于F#和C#几乎是同等强大的,我在想,使用F#也能编写出可以工作的PowerShell模块。经过一小段时间的研究和整理,我决定将可行的方案分享给之家的朋友们。

任务目标

使用F#编写一个PowerShell模块,提供一个名为Get-Sum的cmdlet,完成对一个整数数组求和的功能。至于为什么选择“求和”,是因为递归求和函数通常是F#这类函数式编程语言第一课必学的例子,这种递归的思想也算是函数式语言的特色之一。

正式开始

1、建立项目

开始上手操作之前,确保你安装了.NET Core SDK,并经过适当配置,可以在任意位置使用“dotnet”命令。

打开PowerShell,在你通常保存项目代码的地方创建一个目录,作为整个项目的根。在这个目录下,使用dotnet new命令创建一个F#的类库项目和一个解决方案文件,并将项目添加进解决方案中。

如此,我们便建立了解决方案fsharp-module和F#类库工程testmodule。

2、添加用于编写/生成PowerShell模块的组装件

使用dotnet add package为工程testmodule添加名为PowerShellStandard.Library的组装件,这个组装件由微软提供,并将为工程提供System.Management.Automation名称空间和必要的类型。

如此,我们建立的F#类库已经可以用于编写PowerShell模块了。

3、编写代码

使用自己喜爱的代码编辑器修改testmodule\Library.fs,代码内容如下,我将在代码的下方解释一些要点。

注0:代码中的向右的箭头是->两个字符,向右的三角形是|>两个字符。这种连体字由著名字体FiraCode提供。灰色注释是VSCode相关插件自动生成的;

注1:此名称空间包含了编写PowerShell模块必须的类型;

注2:任何作cmdlet存在的类型必须加上Cmdlet属性(Attribute)。任何cmdlet的名称都由两部分组成:动词(Verb)和名词(Noun),最终形成“Verb-Noun”形式的名称。在这里,我们定义VerbName为Get,NounName为Sum,即得到最终的cmdlet名称Get-Sum。需要注意的是,Verb的选择需要遵守微软的规范。如果你执意要使用奇怪的Verb,构建代码时和导入模块时就会产生警告。任何cmdlet类都必须继承于PSCmdlet类;

注3:一个很经典的递归求和函数。我知道这功能可以干脆使用Array.sum方法来实现,但作为函数式语言的标志性操作之一,展示出来可以展现函数式语言和命令式语言的某种区别;

注4:Parameter属性(Attribute)标记的InputArray属性(Property)用来接收传递过来的参数对象。可以在Parameter属性(Attribute)中指定关于这个参数的更多细节,比如参数的位置、能否从管道中接收等等;

注5:重写基类(部分Java程序员会称作父类,其实都一样)的EndProcessing方法(命令处理完成后)执行求和操作并输出结果。类似的可供重写的虚函数还有BeginProcessing、ProcessRecord和StopProcessing,它们分别表示命令开始执行之前、命令执行的主体和命令中断时的过程。原则上求和应放在ProcessRecord中执行,但由于我们命令的功能很简单,干脆直接在EndProcessing里直接输出求和的结果。

4、编译模块并测试

使用dotnet publish命令发布这个类库。之所以使用publish而不是build,是因为F#程序还依赖另一个组装件:FSharp.Core来运行,而build默认不包含该组装件,该模块将不能被导入PowerShell中。

发布完成后,使用Import-Module命令导入我们编写的模块,并测试功能。

其实,别看这个cmdlet输出的是看似文本的5050,其实它输出的是一个System.Int32,你可以使用GetType()函数来证明这一点:

也正是这种在管道中传递对象的能力,使PowerShell比别的一些Shell拥有更高的潜力。

使用F#编写PowerShell模块的更多相关文章

  1. 【转】PowerShell入门(十一):编写脚本模块

    转至:http://www.cnblogs.com/ceachy/archive/2013/03/08/PowerShell_Script_Module.html 现在通过编写模块就可以在PowerS ...

  2. 【转】PowerShell入门(十二):编写PowerShell管理单元和二进制模块

    转至:http://www.cnblogs.com/ceachy/archive/2013/03/13/PowerShell_SnapIn.html PowerShell一开始就提出利用管理单元来实现 ...

  3. 使用 Azure PowerShell 模块创建和管理 Windows VM

    Azure 虚拟机提供完全可配置的灵活计算环境. 本教程介绍 Azure 虚拟机的基本部署项目,例如选择 VM 大小.选择 VM 映像和部署 VM. 你将学习如何执行以下操作: 创建并连接到 VM 选 ...

  4. [转]使用 C 编写 Lua 模块

    Lua 作为一种小巧的语言,一般都是嵌入到 C/C++ 中作为扩展语言,但是也可以作为独立的脚本语言使用,并且可以使用 C/C++ 编写扩展模块.在参考资料 [1] 中有怎样用 C/C++ 编写模块的 ...

  5. 用Perl编写Apache模块续二 - SVN动态鉴权实现SVNAuth 禅道版

    代码地址:https://code.csdn.net/x3dcn/svnauth 以禅道项目管理系统的数据库结构为标准,实现了可用的svn authz验证功能. 以用户名.密码.项目的acl开发程度o ...

  6. 用Perl编写Apache模块

    前言 Apache被许多大流量网站所嫌弃,但很多企业级的场景则更为适用. Apache httpd 从 2.0 之后,已经不仅仅局限于一个 http 的服务器,更是一个完善而强大.灵活而健壮且容易扩展 ...

  7. 为Lua5.3编写C模块简单示例

    为Lua5.3编写C模块简单示例 一.编译安装Lua5.3 MSVC 命令行安装脚本: @echo off md bin md lib md include cd src cl /c /nologo ...

  8. 支持国内版Office 365的PowerShell模块现已发布

    作者:陈希章 发表于2017年5月12日 上一篇文章我详细介绍了如何在PowerShell中访问到Office 365的Graph API,在文章结尾处我留了一个问题,希望有朋友可以根据那个思路,尝试 ...

  9. 新版Azure Automation Account 浅析(二) --- 更新Powershell模块和创建Runbook

    前篇我们讲了怎样创建一个自动化账户以及创建时候"Run As Account"选项背后的奥秘.这一篇针对在Azure自动化账户中使用Powershell Runbook的用户讲一下 ...

随机推荐

  1. Redis+Lua解决高并发场景抢购秒杀问题

    之前写了一篇PHP+Redis链表解决高并发下商品超卖问题,今天介绍一些如何使用PHP+Redis+Lua解决高并发下商品超卖问题. 为何要使用Lua脚本解决商品超卖的问题呢? Redis在2.6版本 ...

  2. ES6新增语法(一)——let、const、var的区别

    ES6简介 ES6是ECMAScript 6.0的简称,是javascript语言的下一代标准,已经在2015年6月正式发布上线.目的就是为了统一javascript的语法标准,可以用来开发大型应用程 ...

  3. 家庭账本开发day09

    编写数据表格的编辑操作,大体思路和删除操作一样 点击按钮,弹出修改项目,从父窗口获取已有的值赋给 弹出的子窗口中相应的值,在子窗口中点击提交,ajax请求 servlet修改.成功后重载表格,或者up ...

  4. [003] - JavaSE面试题(三):JavaSE语法(1)

    第一期:Java面试 - 100题,梳理各大网站优秀面试题.大家可以跟着我一起来刷刷Java理论知识 [003] - JavaSE面试题(三):JavaSE语法(1) 第1问:& 和 & ...

  5. HTML5-CSS(二)

    一. CSS  文本样式 1.font-size p { font-size: 50px;}解释:设置文本的大小. xx-small.x-small.small.medium.large.x-larg ...

  6. 安装react后运行报错

    错误提示:npm WARN checkPermissions Missing write access to C:\Users\LXD\Desktop\webpack-base\node_module ...

  7. 【洛谷P2028 龙兄摘苹果】动态规划

    分析 第二类striling数 考虑最后一个数到底是放在之前的任意一个集合内,还是自成一个集合 \[F_{i\ j}=F_{i-1\ j-1}+j\times F_{i-1,j} \] AC代码 #i ...

  8. 【Azure Developer】【Python 】使用 azure.identity 和 azure.common.credentials 获取Azure AD的Access Token的两种方式

    问题描述 使用Python代码,展示如何从Azure AD 中获取目标资源的 Access Token. 如要了解如何从AAD中获取 client id,client secret,tenant id ...

  9. (Opencv07)绘制边框

    (Opencv07)绘制边框 cv2.boundingRect(img) 这个函数可以获得一个图像的最小矩形边框一些信息 cv2.rectangle()可以画出该最小矩形边框 x, y ,w, h = ...

  10. header.mapper 用法

    const header= [xxxx,xxxx] 基本用法是 const obj = header.map( item=>{ obj= item+'123'; return  obj }) c ...