使用F#编写PowerShell模块
▲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模块的更多相关文章
- 【转】PowerShell入门(十一):编写脚本模块
转至:http://www.cnblogs.com/ceachy/archive/2013/03/08/PowerShell_Script_Module.html 现在通过编写模块就可以在PowerS ...
- 【转】PowerShell入门(十二):编写PowerShell管理单元和二进制模块
转至:http://www.cnblogs.com/ceachy/archive/2013/03/13/PowerShell_SnapIn.html PowerShell一开始就提出利用管理单元来实现 ...
- 使用 Azure PowerShell 模块创建和管理 Windows VM
Azure 虚拟机提供完全可配置的灵活计算环境. 本教程介绍 Azure 虚拟机的基本部署项目,例如选择 VM 大小.选择 VM 映像和部署 VM. 你将学习如何执行以下操作: 创建并连接到 VM 选 ...
- [转]使用 C 编写 Lua 模块
Lua 作为一种小巧的语言,一般都是嵌入到 C/C++ 中作为扩展语言,但是也可以作为独立的脚本语言使用,并且可以使用 C/C++ 编写扩展模块.在参考资料 [1] 中有怎样用 C/C++ 编写模块的 ...
- 用Perl编写Apache模块续二 - SVN动态鉴权实现SVNAuth 禅道版
代码地址:https://code.csdn.net/x3dcn/svnauth 以禅道项目管理系统的数据库结构为标准,实现了可用的svn authz验证功能. 以用户名.密码.项目的acl开发程度o ...
- 用Perl编写Apache模块
前言 Apache被许多大流量网站所嫌弃,但很多企业级的场景则更为适用. Apache httpd 从 2.0 之后,已经不仅仅局限于一个 http 的服务器,更是一个完善而强大.灵活而健壮且容易扩展 ...
- 为Lua5.3编写C模块简单示例
为Lua5.3编写C模块简单示例 一.编译安装Lua5.3 MSVC 命令行安装脚本: @echo off md bin md lib md include cd src cl /c /nologo ...
- 支持国内版Office 365的PowerShell模块现已发布
作者:陈希章 发表于2017年5月12日 上一篇文章我详细介绍了如何在PowerShell中访问到Office 365的Graph API,在文章结尾处我留了一个问题,希望有朋友可以根据那个思路,尝试 ...
- 新版Azure Automation Account 浅析(二) --- 更新Powershell模块和创建Runbook
前篇我们讲了怎样创建一个自动化账户以及创建时候"Run As Account"选项背后的奥秘.这一篇针对在Azure自动化账户中使用Powershell Runbook的用户讲一下 ...
随机推荐
- C语言:char总结
char字符型数据1.用单引号限制的1字节的字符称为字符型数据,字符型常量2.字符型常量实质保存的是对应字符的ASCII码值,是一个整数3.字符型常量表示范围:0-2554.声明字符型变量 char ...
- ZooKeeper 分布式锁 Curator 源码 03:可重入锁并发加锁
前言 在了解了加锁和锁重入之后,最需要了解的还是在分布式场景下或者多线程并发加锁是如何处理的? 并发加锁 先来看结果,在多线程对 /locks/lock_01 加锁时,是在后面又创建了新的临时节点. ...
- 学习Git的基本业务逻辑
1,基本业务逻辑(假设针对index.html文件中内容): 1,在init版本库之前已写好开头部分:index 对index进行git init版本库: 进入到文件夹中,git init git a ...
- TCP通信简单梳理
一.什么是TCP协议 TCP协议是一种面向连接的可靠的通信协议,最重要的两个特点:连接.可靠. 二.TCP是如何进行通信的 TCP通过三次握手建立连接后客户端服务端的内核都分别开辟资源,这时候开始进行 ...
- Altium Designer 21.x中文版安装破解教程
Altium Designer 21.x是一款优秀的PCB设计工具,可以原理图设计.电路仿真.PCB绘制编辑.拓扑逻辑自动布线.信号完整性分析和设计输出等功能,为设计者提供了全新的设计解决方案,提高设 ...
- tomcat与springmvc 结合 之---第18篇 StandContext容器和SpringMVC的监听器的模型
writedby张艳涛 如何使用tomcat的监听器 public class BootStrap_ex06 { public static void main(String[] args) { Ht ...
- 使用javah 给.class类编译jni_helloworld.h文件头
第一步,在idea中,编写java文件,并且编译 package jni; public class HelloWorld { static { System.loadLibrary("He ...
- 前端知识点--CSS overflow 属性
问题:如何加滚动条? 给div 设置css 样式overflow:scroll div { width:150px; height:150px; overflow:scroll; } -------- ...
- jquey 定位到有某个类
$active = $('.g-pop-box .box-option a[class="on"]')
- SaltStack 水平权限绕过漏洞(CVE-2020-11651)
影响版本 SaltStack < 2019.2.4 SaltStack < 3000.2 poc git clone https://github.com/jasperla/CVE-202 ...