How to create and build an powershell script with windows ?
1.create an script of shell.
在PowerShell中不存在文件和目录的概念,涉及文件和目录的操作总是转换为项(item)处理,即Get-Item、Get-ChildItem和Get-ItemProperty。在PowerShell中的dir命令以Get-ChildItem的别名出现,通过项操作对象的原因是PowerShell作用的任何类型的对象均以项的形式存在。而不像类Unix系统中将所有的对象都抽象成文件,即使这个对象很明显不是文件的情况。
项是包含内容的属性对象,这些对象又可以包含其他项。这个定义可以很容易扩展到文件和目录,即它们是具有各自内容和属性的项。项的概念可以应用于多个系统对象,提供程序(provider)用来创建、找回、修改和移除项。它是官方提供的重要的Shell扩展机制之一,Shell与一些内置的提供程序一起发布给用户,其中提供了提供程序的接口。
1 创建脚本
典型的PowerShell脚本是文本类型的文件,可以使用任何文本编辑器来创建。通常情况下,具有.ps1的文件后缀。最好使用一些语法高亮,甚至是智能补全功能的编辑器,如创建本书中脚本文件的Notepad++编辑器。这是一个功能强大的编辑器,支持多种语言,并且提供语法高亮及关键字补全等;另外可以在PowerShell控制台下使用Set-Content这个cmdlet来创建脚本文件。下面使用该命令创建一个脚本文件:
PS C:\> $code = @" >> Write-Host "Hello World!!" >> "@ >> PS C:\> Set-Content hello-world.ps1 $code PS C:\> type hello-world.ps1 Write-Host "Hello World!!"
hello-world.ps1以普通的文本文件形式存在,可以使用type命令(以Get-Content命令的别名存在)来查看其内容。
1.1 调用脚本
在PowerShell中调用脚本文件时应在PATH环境变量中包含的路径中搜索,当前目录并不在系统的PATH中。调用当前目录中的脚本文件需要添加前缀,调用当前的脚本文件的方式应该是.\hello-world.ps1。
如果当前目录默认包含在PATH中,则允许***者采用恶意代码覆盖同名的默认程序。假设恶意用户在共享目录中写入与内置cmdlet同名的脚本,当管理员访问这个共享目录时并调用了该脚本,则可导致恶意操作。因此在PowerShell和Unix的Shell中需要用户通过在当前路径前增加.\前缀,显式地指明需要执行当前目录中的程序。
调用创建的hello-world.ps1脚本文件提示以下错误:
PS C:\> .\hello-world.ps1 File C:\hello-world.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details. At line:1 char:18 + .\hello-world.ps1 Get-ExecutionPolicy RemoteSigned
$what参数用来在通配符不包含.wma扩展名时添加扩展名,从而限制搜索文件的范围只限于.wma文件。代码递归遍历所有文件,并返回符合$what通配符的文件。将以上代码保存为Get-Music.ps1脚本文件,其中查找名为“ A Place Near by.wma”的音乐文件:
PS C:\> .\Get-Music.ps1 'D:\Music' *Near* Directory: D:\Music Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2009/3/1 20:38 3006849 A Place Near by.wma
有时需要隔离特定的变量或函数,对于特定的脚本文件来说它是全局的。需要让其中定义的所有函数和脚本块能够访问该变量或函数,但用户需要显式强调不能在脚本文件外访问对象。这时不能使用$global作用域前缀,因为这将使该变量或函数暴露在所有代码面,无论它们是否已在脚本文件中定义。解决这个问题的方法是使用$script作用域前缀,为了说明这个问题,建立如下脚本文件代码:
$script:name = "LiuTao" function Modify-Name() { $script:name = "XiaoGang" Write-Host "Variable within script function scope:$script:name" } Write-Host "Variable Original script global scope: $script:name" Modify-Name Write-Host "Variable Modified script global scope: $script:name"
上述代码中存在脚本全局作用域和Modify-Name函数作用域,在shell可以通过引用$script:name调用脚本全局变量。将以上脚本另存为“Variable-ScriptScope.ps1”文件并调用:
PS C:\> $name = "LiMing" PS C:\> .\Variable-ScriptScope.ps1 Variable Original script global scope: LiuTao Variable within script function scope:XiaoGang Variable Modified script global scope: XiaoGang PS C:\> Write-Host "Variable outeside of script: $name" Variable outeside of script: LiMing
能够看到对于脚本文件以外的$name变量并没有受到影响。
与此相对应,通过在脚本文件名前增加点(.)前缀来实现脚本文件访问所有的当前变量和函数,即将脚本文件点源引用(dot-sourcing)到当前shell进程中。点源引用使用点加空格再加上要引用的脚本文件名,将该脚本文件的所有变量、函数、脚本块释放在当前shell中供使用。下例以点源引用的方式来调用Variable-ScriptScope.ps1脚本文件:
PS C:\> $name = "LiMing" PS C:\> . .\Variable-ScriptScope.ps1 Variable Original script global scope: LiuTao Variable within script function scope:Mike Variable Modified script global scope: Mike PS C:\> Write-Host "Variable outeside of script: $name" Variable outeside of script: Mike
代码在第1个return语句之后终止,因而只输出一个文件对象。
如果是运行在顶层作用域中,return语句会退出脚本文件,但是上述代码中该语句只是退出当前作用域。即如果return语句是在脚本文件中的脚本块或函数中,只是退出该脚本块或函数,而脚本文件本身还将继续执行。为了显式退出脚本文件,需要使用exit语句。下例在脚本文件中的函数中退出整个脚本文件的执行:
function Verify-TextFile($file) { if(!$file.EndsWith(".txt")) { Write-Host "$file is not a text file" exit } } $files = "Names.txt","Music.wma","Photo.jpg" foreach($file in $files) { Verify-TextFile $file }
将文件另存为“Explicit-Exit.ps1”,然后调用如下:
PS C:\> .\Explicit-Exit.ps1 Music.wma is not a text file
可以看到未执行检测Photo.jpg文件的操作,而是在检测Music.wma文件后退出。
2 从其他环境中执行脚本
PowerShell代码与已经存在的解决方案结合,才能发挥最大作用。可以编写所需脚本并在Windows的计划任务中调用,也可以将现有的脚本解决方案逐块转换为用PowerShell开发,或者用命令方式调用现有解决方案。所有自动化环境,包括任务计划服务、软件系统,以及执行外部命令都可以将PowerShell扩展进来。可以调用PowerShell.exe并把脚本块名作为参数:
C:\>PowerShell.exe hello-world.ps1 The term 'hello-world.ps1' is not recognized as a cmdlet, function, operable pr ogram, or script file. Verify the term and try again. At line:1 char:16 + hello-world.ps1 .\Lib-User-DotSource.ps1 The term '.\Library.ps1' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again. At C:\Lib-User-DotSource.ps1:1 char:2 + .