Power Shell 简介
power shell 是微软公司为Windows管理员提供自动化管理的工具,可以通过脚本进行批处理,大大提高执行效率。从网上的资料来看似乎运维人员对power shell 的要求比较高。
学习动因
至于我为什么要学习power shell,主要是因为公司业务需要,要求在测试电脑上自动安装一些文件,从而完成自动化测试环境的配置,为了降低操作成本,要求我们自动化测试人员写一个power shell脚本,并与所需测试环境的配置文件一起打包,拷贝到测试电脑中,通过在测试电脑中以管理员身份运行powershell脚本,可在测试电脑中自动配置环境。
解决过程
我的需求有3个:1.将文件移动到指定文件夹。2.安装软件:检测测试电脑是否已安装该软件,如果已安装,则提示用户:是否要继续安装。3.开始新线程执行cmd命令批处理文件。
1.移动文件,删除文件的power shell 指令:
remove-item "要删除的文的件路径" -Recurse -force # 删除文件
copy-item "要删除的文件的路径" -Recurse -force # 复制文件
move-item "要删除的文件路径" -Recurse -force # 移动文件
参数解读:-Recurse: 删除给定位置的对象和所有位置的子项。
-force: 强制删除
2. 安装软件:
安装软件需要操作注册表,而power shell 6.2(似乎是)以下的版本,以管理员身份运行,默认不开启访问注册表权限,所以需要设置执行策略,打开注册表访问权限。命令如下:
Set-ExecutionPolicy Unrstricted -Scope Currentuser -Force -Confirm:$false
参数解读:命令 Set-ExecutionPolicy 后接所需执行策略的值(可选:Restricted,Allsigned, Remotesigned,Unrestricted,Bypass,Undefined),我图方便,直接设置成了Unrestricted。
-Confirm:因为window为安全起见,设置执行策略默认会弹出提示行,要求用户对执行指令进行确认,将此参数设置为false则可直接执行命令,不会进行询问。记得false前加$。(Tips:ps脚本中定义变量均是以$开头的)。
检查软件是否已在目标计算机上安装:
这里有两种方式:
1. 通过WMI查询,慢,特别慢。
Get-WmiObject win32_product
2. 查询注册表实现,这是我在网上down的代码,自己试着修改了一下,加一些判断条件实现我需要的功能:
# 定义一个函数
Function Get-Software {
[OutputType('System.Software.Inventory')]
[Cmdletbinding()]
Param(
[Parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[String[]]$Computername=$env:COMPUTERNAME
)
Begin {
}
Process {
$InstalledState = $false
ForEach ($Computer in $Computername){
If (Test-Connection -ComputerName $Computer -Count 1 -Quiet) {
$Paths = @("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall","SOFTWARE\\Wow6432node\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
ForEach($Path in $Paths) {
Write-Verbose "Checking Path: $Path"
# Create an instance of the Registry Object and open the HKLM base key
Try {
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer,'Registry64')
} Catch {
Write-Error $_
Continue
}
# Drill down into the Uninstall key using the OpenSubKey Method
Try {
$regkey=$reg.OpenSubKey($Path)
# Retrieve an array of string that contain all the subkey names
$subkeys=$regkey.GetSubKeyNames()
# Open each Subkey and use GetValue Method to return the required values for each
ForEach ($key in $subkeys){
Write-Verbose "Key: $Key"
$thisKey=$Path+"\\"+$key
Try {
$thisSubKey=$reg.OpenSubKey($thisKey)
# Prevent Objects with empty DisplayName
$DisplayName = $thisSubKey.getValue("DisplayName")
If ($DisplayName -AND $DisplayName -notmatch '^Update for|rollup|^Security Update|^Service Pack|^HotFix') {
$Date = $thisSubKey.GetValue('InstallDate')
If ($Date) {
Try {
$Date = [datetime]::ParseExact($Date, 'yyyyMMdd', $Null)
} Catch{
Write-Warning "$($Computer): $_ <$($Date)>"
$Date = $Null
}
}
# Create New Object with empty Properties
$Publisher = Try {
$thisSubKey.GetValue('Publisher').Trim()
}
Catch {
$thisSubKey.GetValue('Publisher')
}
$Version = Try {
#Some weirdness with trailing [char]0 on some strings
$thisSubKey.GetValue('DisplayVersion').TrimEnd(([char[]](32,0)))
}
Catch {
$thisSubKey.GetValue('DisplayVersion')
}
$UninstallString = Try {
$thisSubKey.GetValue('UninstallString').Trim()
}
Catch {
$thisSubKey.GetValue('UninstallString')
}
$InstallLocation = Try {
$thisSubKey.GetValue('InstallLocation').Trim()
}
Catch {
$thisSubKey.GetValue('InstallLocation')
}
$InstallSource = Try {
$thisSubKey.GetValue('InstallSource').Trim()
}
Catch {
$thisSubKey.GetValue('InstallSource')
}
$HelpLink = Try {
$thisSubKey.GetValue('HelpLink').Trim()
}
Catch {
$thisSubKey.GetValue('HelpLink')
}
$Object = [pscustomobject]@{
Computername = $Computer
DisplayName = $DisplayName
Version = $Version
InstallDate = $Date
Publisher = $Publisher
UninstallString = $UninstallString
InstallLocation = $InstallLocation
InstallSource = $InstallSource
HelpLink = $thisSubKey.GetValue('HelpLink')
EstimatedSizeMB = [decimal]([math]::Round(($thisSubKey.GetValue('EstimatedSize')*1024)/1MB,2))
}
$Object.pstypenames.insert(0,'System.Software.Inventory')
# 进行软件名匹配,我这里用的模糊匹配
If($DisplayName -match "软件名") {
$InstalledState = $True
Write-Output $Object
}
} Catch {
Write-Warning "$Key : $_"
}
}Catch {}
} Catch {}
$reg.Close()
} Catch {}
}
}
If(InstalledState -eq $True) {
$State = Read-Host "检测到此电脑已经安装**,是否跳过此步骤(Y/N)? "
While($State -ne "n" -and $State -ne "N" -and $State -ne "y" -and $State -ne "Y") {
$State = Read-Host "输入有误,请重新输入(Y/N): "
if($State -eq "n" -or $State -eq "N" -or $State -eq "y" -or $State -eq "Y"){
break
}
}
If($State -eq "n" -or $State -eq "N"){
# 执行安装***的函数
Write-Host "正在安装**"
}
Elseif($State -eq "y" -or $State -eq "Y"){
Write-Host "不在安装**"
}
}
Else {
# 直接执行安装**函数
Write-Host "正在安装**"
}
}
}
}
# 执行该函数
Get-Software
语法啥的就不细琐了,因为我也不会,比如后边的if判断我觉得应该可以精简,但本着能用就行的原则,暂时就先这样了,如果有有明白的大佬欢迎指正。
安装软件命令,我这里采用开启新线程的方式安装软件。
Start-Process -FilePath $安装包路径 -ArgumentList "arg1", "arg2",...
参数解读: -ArgumentList: 后接一些配置参数,以英文逗号分隔,我用到的为 : /S:以静默方式安装软件。还可以指定安装路径("\D=$安装路径"),但是我没有弄明白。
3。执行cmd批处理命令:
说白了就是执行一个里面有从cmd指令的.bat文件,与安装软件的过程类似,开启一个新线程,打开对应文件路径并执行即可。
总结
经过几天的接触,觉得power shell的确很强大,但是就自己的工作内容来看,我对powershell脚本的使用并不多,故并没有投入太多精力取进行系统的学习,只是针对性的根据自己的需求对部分命令进行了简单的了解,后续如果有需要,关于这方面的内容还会继续更,写这篇帖子算是学习笔记,记录一下自己的学习过程。
参考链接:
(68条消息) PowerShell快速高效地获取安装的软件列表_零点零一的博客-CSDN博客
PowerShell 删除文件夹 | D栈 - Delft Stack
(68条消息) 使用 PowerShell 收集已安装的软件_allway2的博客-CSDN博客_powershell获取安装的软件