Cnfan.net中国网络
IT网络技术专家
微软技术
 最新专题: Windows Server 2003 安全指南   IIS 技术专题   Exchange 2007 技术专题   SharePoint 2007 教程   跟我从头学WSH   专题 | 分类 | 投稿 | 搜索
 微软技术首页 | 微软动态 | Vista | Windows | ISA | Exchange | Share Point | SQL Server | System Center | 其它

跟我从头学powershell (一)

简介:一.开始 (1) 所有的*nix(linux,unix)系统都有内置的命令行接口,就算它们有图形化的接口,真正的工作还是从CLI进行在。 Windows传统采用内置的GUI接口,采用GUI中进行自动化任务,通常比CLI接口更困难 ...

关键字: powershell 跟我从头学

一.开始
(1)
所有的*nix(linux,unix)系统都有内置的命令行接口,就算它们有图形化的接口,真正的工作还是从CLI进行在。
Windows传统采用内置的GUI接口,采用GUI中进行自动化任务,通常比CLI接口更困难,比如怎么检查一个check box是否被选中,诸如此类。
微软传统上提供了一系列的CLI工具。这些工具基于CLI接口,称为批处理文件或脚本。毕竟,这些CLI工具只能实现windows的一部分功能,只能执行微软提供给这些工具的自动化任务。
       这些工具和VBScript都有共同的问题,因为这些工具开发的时间很长了,由很多不同的团队和部门开发,彼此之间没有共享标准和工作。导致相互之间有很多不同,这意味着每个工具都要经历一个新的学习过程。微软没有真正的为windows提供过一个自动化脚本。
       Powershell不是一个新的Vbscript脚本语言,它是一个新的管理接口,你不用脚本而交互使用它。提供给windows或其他微软服务器产品。你也可以用脚本编写复杂的任务。
              Exchange 2007就是使用powershell的实例,是Exchange 2007的管理工具的一部份。
              Powershell被设计为最新的windows,基于64位处理器。安装powershell的要求就是.net framework v2.0
 
(2)快速开始
       Power shell很容易启动和运行,可以用powershell.exe来运行,或在开始菜单中选择快捷方式运行。Powershell是一个完整的shell。在此环境中,你可以用你熟悉的方法运行GUI的应用程序(Notepad,Calc),或者,如果应用程序是字符输出的,你可以在powershell中捕获这些输出。
       在powershell下,主要工作采用cmdlets,被命名为verb-noun format,比如get-process,你可以使用get-help cmdlet来阅读,Get-Help Get-Process显示get-process的帮助命令。
 
(3)指示你的系统
       传统的cmd.exe提供了访问驱动器的能力,powershell也提供了访问的能力,同时也提供了访问额外资源的能力,比如注册表。
       Powershell将这些额外的资源“映射”为额外的资源,使其看起来像一个驱动器:
       Get-PSDrive cmdlet的输出
Name     Provider      Root                   CurrentLocation
----       --------      ----                         ---------------
A        Microsoft.... A:\
Alias     Microsoft....
C        Microsoft.... C:\                       ...TEM\MSMAPI\1033
cert       Microsoft.... \
D         Microsoft.... D:\
Env       Microsoft....
F         Microsoft.... F:\
Function   Microsoft....
HKCU    Microsoft.... HKEY_CURRENT_USER
HKLM    Microsoft.... HKEY_LOCAL_MACHINE
Variable   Microsoft....
 
注意,HKLM drive映射到HKEY_LOCAL_MACHINE。同时注意Provider列,发现提供者为registry。 Provider使得powershell更加具有易用性。可以通过简单添加provider,可以使得powershell访问整个新的资源。额外的providers在Visual SourceSafe和SharePoint services可用,其他的providers将在未来开发。
可以采用以下的命令改变location
PS C:\>Set-Location HKLM:\
注意,可以设置自己的完整location
PS C:\>Set-location "C:\Documents and Settings"
 
Powershell同时维护一个location棧,我们可以使用push-location和pop-location来调整push-location将当前位置放置在stack的最顶端。如果你指定一个路径,则将当前路径作为top,并将后面的路径改为当前路径。 Pop-location可以使用pop-location来从statck中获取路径。
PS C:\>Push-Location C:\Test
PS C:\Documents and Settings>Pop-Location
则可以返回C:\
 
(4)使用power-shell命令行
       Power-shell有非常基本的行编辑能力:
上下键显示先前输入的命令
左右键移动光标
Home移动到行首
End移动到行尾
Ctrl+left和ctrl+right跳一个单词
Insert键在insert/overwrite之间切换
Backspace删除左面字符
Delete删除右面字符
Tab自动补全输入
Esc清除整个命令行
 
(5)Aliases
       使用set-aliases命令可以将一些Powershell命令转化成你所熟悉的命令
       PS C:\>Set-Alias popl Pop-Location
你可以使用remove-item来删除:
PS C:\>Remove-Item alias:popl
通过get-alias可以检查aliases。
注意,要永久使用aliases,你可以将其添加到你的profile中。
 
(6)基本的cmdlets
我们可以使用get-command命令获得一个所有注册的cmdlets列表。
       可以用下面的命令来描述set-alias命令
        PS C:\>Get-Command Set-Alias
       可以用get-help获得更加详细的描述,也可以用通配符来获得多个命令的帮助:
       PS C:\>Get-Help *Service
       注意,可以使用help命令来代替get-help命令。
       参数,许多cmdlets可以接受参数,比如下面的示例将创建一个新的文件
       PS C:\>New_Item -type file "myfile.txt"
       普遍的参数
       大多数的cmdlets支持一组普遍的参数:
              -Debug (-db):指导cmdlets提供额外的操作细节
              -ErrorAction (-ea): 指定发生错误或执行的动作,可以是 NotifyContinue (default), NotifyStop, SilentContinue, SilentStop, and Inquire.
              -ErrorVariable (-ev)
              -OutVariable (-ov)
              -Verbose (-vb): 指示额外输出
 
(7)Snap-ins
       Snap-in本质上是一个cmdlets的集合。可以通过get-passnapin来显示snap-ins。
       你可以通过给get-command加上-pssnapin参数,来看cmdlets命令是属于哪个snap-in的。
       如果你创建的脚本依赖一个snap-in,共享给另一个管理员,而他没有该snap-in,则这个脚本就不能运行。
#requires -PSSnapIn Microsoft.PowerShell.Utility
可以用该命令来解决这个问题。
 
(8)配置文件
Powershell采用配置文件来定制shell环境。
下面这些文件用来定制配置文件
%windir%\system32\WindowsPowerShell\v1.0\profile.ps1 给所有用户调用的配置文件
%windir%\system32\WindowsPowerShell\v1.0\ Microsoft.PowerShell_profile.ps1 给所有用户调用,并且是只影响powershell的默认实例
%UserProfile%\My Documents\WindowsPowerShell\profile.ps1 每个用户调用的配置文件,并且影响所有安装的powershell版本
%UserProfile%\\My Documents\WindowsPowerShell\ Microsoft.PowerShell_profile.ps1 每个用户调用的配置文件,但只影响默认的powershell实例
 
默认情况,并没有配置文件存在,但你可以创建一个。如果存在多个配置文件,并有冲突,遵循最后读入的文件优先级最高的原则。
下面是一个配置文件举例(注意,这些配置并不真的由powershell运行,而是作为powershell的核心的一部分运行) :
# Copyright (c) 2005 Microsoft Corporation. All rights reserved.
#
# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
# OF ANY KIND, EITHER EXPRESSED or IMPLIED, INCLUDING BUT NOT LIMITED
# TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
# PARTICULAR PURPOSE
 
 
 
set-alias cat        get-content
set-alias cd         set-location
set-alias clear      clear-host
set-alias cp         copy-item
set-alias h          get-history
set-alias history    get-history
set-alias kill       stop-process
set-alias lp         out-printer
set-alias ls         get-childitem
set-alias mount      new-drive
set-alias mv         move-item
set-alias popd       pop-location
set-alias ps         get-process
set-alias pushd      push-location
set-alias pwd        get-location
set-alias r          invoke-history
set-alias rm         remove-item
set-alias rmdir      remove-item
set-alias echo       write-object
 
set-alias cls        clear-host
set-alias chdir      set-location
set-alias copy       copy-item
set-alias del        remove-item
set-alias dir        get-childitem
set-alias erase      remove-item
set-alias move       move-item
set-alias rd         remove-item
set-alias ren        rename-item
set-alias set        set-variable
set-alias type       get-content
 
function help
{
    get-help $args[0] | out-host -paging
}
 
function man
{
    get-help $args[0] | out-host -paging
}
 
function mkdir
{
    new-item -type directory -path $args
}
 
function md
{
    new-item -type directory -path $args
}
 
function prompt
{
    "PS " + $(get-location) + "> "
 
}
 
& {
    for ($i = 0; $i -lt 26; $i++)
    {
        $funcname = ([System.Char]($i+65)) + ':'
        $str = "function global:$funcname { set-location $funcname } "
        invoke-command $str
    }
}
 
(8)脚本
到目前为止,我们都是直接运行cmdlets,并且察看其输出,powershell脚本被设计为将多个cmdlets命令结合在一起运行,来完成自动化任务。
       Powershell 的脚本必须有.ps1的文件扩展名,执行脚本,最简单的可以直接打入文件名,而不需要输入文件扩展名。如果你的脚本有输入量,在输入的文件名后跟上它们。
Myscript arg1 arg2
 
当你打入一串字符,powershell首先察看alias,然后是函数,然后是cmdlet, 然后是脚本,然后是外部可执行命令。
为什么powershell要采用新的语言来替换掉早期的vbscript, 一个原因是因为powershell是建立在.net基础上的。出于.net的功能和兼容性,vbscript是做不到的(没有任何一个脚本语言可以作到)。另外,一个新的语言可以有更多的一致性。微软决定采用C#.net的子集来作为脚本语言。作为从powershell到完整版本C#语言的跨越。
 
(9)重定向
将输出重定向或将两个cmdlet命令结合在一起始常见的事情,你可以将cmdlets的输出重新定向文件:
PS C:\>Get-Command > commandref.txt
注意,将其添加到现有文件的后面,应该用“〉〉”
 
你可以将一个cmdlets的输出作为另一个cmdlet的输入,采用的语法是$(cmdlet),比如下面的一个举例:
PS C:\>Get-ChildItem $(Read-Host -Prompt "Enter file path/name: ")
 
(10)变量
变量像一个容器,可以有一个值,Powershell的变量以$开头。
PS C:\>$var = 100
你可以在powershell的环境中申明变量,而不需要在脚本中使用:
PS C:\Documents and Settings> $var = "C:\"
PS C:\Documents and Settings> set-location $var
PS C:\>
 
变量也可以包含一个cmdlets的输出,下面就是一个变量,包含了get-process 的输出
PS C:\>$a = get-process
 
Powershell的变量并不需要先申明。
 
变量名和内在值
变量名可以包含任何字符,如果变量不是以字符开头,应该用花括号括起来
$var = 4
$var2 = 3
${@@123} = 2
 
这种花括号的变量名容易引起人们的疑惑,但下面是一个具体的示例,显示这种变量的一个应用:
PS C:\>${C:\File.txt} = "Hello!"
 
变量是对象
在powershell中,变量是一个对象,不再是如vbscript那样的简单的一个值,所以它就具备了一些列的能力,举例:
PS C:\>$var = "Hello, World"
 
因为$var是一个对象,所以可以采用一些方法,比如substring()
PS C:\>Write-Host $var.SubString(2,2)
Substring方法,从第三个字符位置开始,取两个字符,将输出”ll”
PS C:\>Write-Host $var.Length
将输出12
注意,变量可以是字符串或数字,这些值不同,导致方法输出不同:
PS C:\> $var = 3
PS C:\> write-host $var.length
注意,因为是数字,所以长度方法没有输出
PS C:\> $var = "Hello"
PS C:\> write-host $var.length
5
输出为5
 
字串变量和嵌套
PS C:\> $var = "Hello"
PS C:\> $var2 = "$var, World!"
PS C:\> write-host $var2
Hello, World!
在这个例子中,$var2变量就是包含了$var的值
 
换一个写法,可见不同之处:
PS C:\> $var = "Hello"
PS C:\> $var2 = '$var, World!'
PS C:\> write-host $var2
$var, World!
差别在于用单引号代替了双引号,这样就不会将$var展开了。
双引号也可以包含一个表达式,比如:
PS C:\> $var = "2+2 is $(2+2)"
PS C:\> write-host $var
2+2 is 4
 
分析模式
注意,write-host有没有括号是不同的:
PS C:\> write-host 2+2
2+2
PS C:\>
 
PS C:\> write-host (2+2)
4
PS C:\>
在命令行中,Powershell将所有东西看成是字符串。
l         If the first character is a number, a variable ($), or a quoted string, then the shell works in expression mode, in which all strings must be quoted
l         If the first character is a letter, ampersand (&), or a dot followed by a space or a letter, then the shell works in command mode, which is where everything is assumed to be a string unless it's a variable or is in parentheses, as we've demonstrated
(11)特殊字符
有些时候,你需要显示一些无法打入的字符,出于这个原因,powershell提供了一个特殊的字符`.
Character
Escape Code
Null
`0
Alert
`a
Backspace
`b
Form feed
`f
New line
`n
Carriage return
`r
Tab
`t
Vertical quote
`v
 
(12)作用范围
作用范围是描述函数或变量在Powershell的可视范围,除非你特别指定,变量只能在初始创建的位置读取和修改。
除非用.前缀,默认情况下,所有的脚本运行在一个新建的scope中。子scope或由scope创建的其他的scope,能够读取父scope的变量,但不能容易的改变它们。父scope不能访问子scope
当你开始一个新的powershell实例,你工作在一个global scope中,所有的子scope,都可以访问global scope的变量,通过明确的label来表明访问的变量
 
Scope name
Global scope被命名为global,其他的scope由脚本名来命名。
下面是一个举例:
一个脚本命名了变量$var,一个函数运行,同样也声明了变量$var,一个是script级别的scope,另一个是函数scope,因为函数包含在script中,所以是script scope的子scope。意味着函数可以访问script级别的变量,采用$script:var的方式。
变量也可以申明为私有的,意味着这个函数只能在这个scope中被访问,子对象不能访问,下面举例是申明一个私有变量var:
PS C:\>$private:var
 
(13) 函数
函数是一小段代码,用来完成特定的功能。函数有自己的scope,在函数内申明的变量只能被函数访问,但可以访问脚本范围的变量。函数由关键词function开头:
function myFunction {
$var = 3
$script:var = "Hello"
}
 
(14)管道
       将数据和对象从一个cmdlet传递到另一个,有点类似于cmd.exe中的more:
C:\>Dir | More
这个操作是将dir的输出”pipes”给More,这样一页一页的显示。
这样的功能powershell也有,下面是一个举例:
 PS C:\>Get-Process | where { $_.handlecount -gt 400 } | Format-List
这实例实际上执行了3个cmdlets
第一个,是get-process,返回运行的process的列表
第二个where是where-object的cmdlet的别名,作用对一系列对象进行分类,并取出符合要求的对象,在这里,是指handlecount属性(-gt argument)大于400。
第三个是formet-list, 创建一个漂亮的结果列表
 
(15)获得帮助
Powershell内置了帮助系统。要查看可用的帮助主题,打Help *_*.
要查看某个专题的帮助,可以运行Help topicname比如Help about_Alias.
 
 

二.你的第一个powershell脚本
Powershell不包含一个全功能的编辑和脚本开发环境,所以,windows的notepad是一个基本骨干的编辑器,用艾编辑你初始的脚本,随着编写脚本的深入,可以考虑使用专门的脚本开发环境,比如Sapien Primalscript
 
举例:Restart-Computers.ps1
# Define input parameters
param (
 [string] $filename = $(throw "Filename is required!")
)
 
Write-Host "Reading computer names from $filename"
 
# Read file
$computers = get-content $filename
foreach ($computer in $computers) {
 
 # Connect to WMI
 $wmi = get-wmiobject -class "Win32_OperatingSystem" `
   -namespace "root\cimv2" -computer $computer
 
 # Restart computer
 foreach ($item in $wmi) {
    $wmi.reboot()
    write-host "Restarted " + $computer
 }
}
 
首先,Param块为脚本简单的定义了输入参数,注意,这里采用了[string]来定义数据类型,同时注意,我们给输入的参数一个特定的值,通常,特定值是用来指定一个变量在没有指明值的情况下使用的,在这里,我们的“默认”值是关键字“throw”,是说明,如果$filename变量没有被赋予值得话,则脚本不进行运行,throw关键词的简单意思是“产生一个错误”,并且后面跟的是错误的消息。
 
其次,我们要讨论get-content cmdlet,这个命令需要一个文件名,我们把结果存在$computers这个变量中,这个变量是一个字符串的集合,每个字符串是一个计算机名。
 
接下来,用到了foreach循环,它从$wmi中读取信息到$item中。换句话说,$item每次从win32_operationgsystem class中获得一个单独得实例。
 
因为$item反映出wmi类,它将有所有的属性和方法,所以也具有Reboot的方法。
# Restart computer
 foreach ($item in $wmi) {
    $wmi.reboot()
    write-host "Restarted " + $computer
 }
}
 
那么我怎么知道win32_operatingsystem class有一个reboot方法呢?当然可以阅读相应的
WMI文档,当然也可以通过其他方法来获得这些信息:
首先,通过查询powershell返回类的实例,然后,采用get-member,查询powershell来显示信息类型。
PS:> Get-wmiobject –list
 
PS > $wmi = get-wmiobject -class Win32_OperatingSystem -namespace
root\cimv2
 
PS C:\> $wmi | get-member
 
如果同一行有多个语句,相互之间可以采用分号分隔。
下面的语句是一样的
foreach ($item in $wmi)
{
 $wmi.reboot()
 write-host "Restarted " + $computer
}
 
foreach ($item in $wmi)
{ $wmi.reboot(); write-host "Restarted " + $computer}

  <欢迎投稿>  <论坛讨论>
 »相关文章  »论坛新贴
精彩文章 活动资讯 今日头条