我正在研究一个脚本,以测试目标目录中是否存在文件,如果为false,则执行应用程序安装。
目标是测试文件是否存在,如果存在,则通过日志中止原因。如果该文件不存在,则应执行应用程序安装程序。
我首先尝试使用New-Item创建虚拟文件来创建目录和虚拟文件。
New-Item -ItemType Directory -Force -Path "C:\temp"
New-Item -Path "C:\temp\vistaupdated.txt" -ItemType "file" -Value "Updated"
# Test if computer is updated
$file = Get-Content "C:\temp\vistaupdated.txt"
$containsWord = $file | %{$_ -match "Updated"}
if ($containsWord -contains $false) { ###start running the install stuff
但是,如果文件与Object-NotFound不存在,则会出现此错误。然后,我决定转换策略并使用Test-Path
:
$file = Test-Path -Path "C:\temp\vistaupdated.txt"
if ($file -eq $false) { ###start running the install stuff
在这种情况下,我相信$file
的评估结果为False,因此执行安装。执行后,我得到的只是脚本路径的返回:
PS C:\users\me\desktop> $filetest = Test-Path -Path "C:\temp\vistaupdated.txt" PS C:\users\me\desktop> $filetest False PS C:\users\me\desktop> C:\Users\me\Desktop\vistaupdate.ps1
上面对PS1文件的引用未执行。仅当我以管理员身份通过ISE运行脚本时,才会返回此内容。如果对控制台执行相同操作,则输出为空白,无需任何操作。
# Test if computer is updated
$file = Test-Path -Path "C:\temp\vistaupdated.txt"
if ($file -eq $False) {
#package repository
$VistaInsPath = "\\apps\shared\me\vista\6.16.0"
#package installation command
$VistaInsEXE = "VistaClient.6.16.0.896"
#package installation parameters
$VistaInsParam = "/s /v/qn"
#logging
$logFile = "\\apps\shared\me\vista\6.16.0\log\vista_install.log"
#timestamp for logging
function Get-TimeStamp {
return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
}
#main function
function Vista-Install {
$errFlag = $false
try {
$cmdLine = "$VistaInsPath$VistaInsEXE"
Start-Process -FilePath $cmdLine -ArgumentList $VistaInsParam -Wait
} catch {
$(Get-TimeStamp) + "[" + $env:COMPUTERNAME +"]" + "[" + $env:USERNAME +"]" + "Error has occurred: " + $_.Exception.Message | Out-File $logFile -Append
$error.Clear()
$errFlag = $true
}
#if no error, notify success
if (-not $errFlag) {
$(Get-TimeStamp) + "[" + $env:COMPUTERNAME +"]" + "[" + $env:USERNAME +"]" + "Completed Successfully" | Out-File $logFile -Append
}
# Place dummy file to tag computer as updated
New-Item -ItemType Directory -Force -Path "C:\temp"
New-Item -Path "C:\temp\vistaupdated.txt" -ItemType "file" -Value "Updated"
}
} else {
$(Get-TimeStamp) + "[" + $env:COMPUTERNAME +"]" + "[" + $env:USERNAME +"]" + "Computer Already Updated. Aborting" | Out-File $logFile -Append
}
如果Test-Path
为False,则安装程序应在第一个if语句中启动。相反,脚本会吐出脚本本身的路径并退出。
答案 0 :(得分:1)
正如@lit在问题注释中所指出的那样,您永远不会调用函数Vista-Install
,因此,您的代码实际上什么也不做就不足为奇了。而且,您无论如何都不应在嵌套作用域中定义函数(或$Vista*
和$LogFile
变量)。 else
分支中的代码将无法找到您当前拥有的Get-TimeStamp
或$LogFile
。
允许我提出一些改进建议:
您的日志记录代码具有很多冗余信息。与其定义仅用于生成时间戳的函数,还不如定义一个将日志消息作为参数并完全封装日志的函数。
$cmdLine = "$VistaInsPath$VistaInsEXE"
将组合目录路径和文件名而没有路径分隔符,从而导致路径不正确。可以在变量之间加上反斜杠:
$cmdLine = "$VistaInsPath\$VistaInsEXE
或者(更好)使用@Theo建议的Join-Path
cmdlet:
$cmdLine = Join-Path $VistaInsPath $VistaInsEXE
直接将Test-Path
置于if
条件下。无需先将结果分配给变量。
变量$errFlag
是毫无意义的。只需将日志语句放在Start-Process
之后。如果引发异常,则代码将转到catch
块,而不会到达该语句。
我假设仅在安装没有引发错误的情况下才希望创建文件vistaupdated.txt
,因此代码也应放在try
块中。
New-Item
输出该项目的对象。您可能想抑制这种情况。
函数Vista-Install
也没有多大意义,因为它只会安装一个特定的程序。由于开始的代码很少,因此我将其删除并将代码直接放在“ then”分支中。但是 if 如果您希望它成为一个函数,则应该对其进行适当的命名和参数化:将程序和参数作为参数传递(最好以Start-Process
的参数命名,因此您可以简单地{{3 }} splat变量),并使用符合$PSBoundParameters
的名称:
function Install-Program {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true, Position=0)]
[string]$FilePath,
[Parameter(Mandatory=$false, Position=1)]
[string]$ArgumentList = @()
)
try {
Start-Process @PSBoundParameters
...
} catch {
...
}
}
Install-Program -FilePath (Join-Path $VistaInsPath $VistaInsEXE) -ArgumentList $VistaInsParam
简化代码:
$VistaInsPath = '\\apps\shared\me\vista\6.16.0'
$VistaInsEXE = 'VistaClient.6.16.0.896'
$VistaInsParam = '/s', '/v', '/qn'
$logFile = '\\apps\shared\me\vista\6.16.0\log\vista_install.log'
function Write-Log {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false)]
[string]$Message = ''
)
"[{0:MM/dd/yy HH:mm:ss}]`t[{1}\{2}]`t{3}" -f (Get-Date), $env:COMPUTERNAME, $env:USERNAME, $Message |
Out-File $script:LogFile -Append
}
if (-not (Test-Path -Path 'C:\temp\vistaupdated.txt')) {
$cmdLine = Join-Path $VistaInsPath $VistaInsEXE
try {
Start-Process -FilePath $cmdLine -ArgumentList $VistaInsParam -Wait
New-Item -Path 'C:\temp' -Type Directory -Force | Out-Null
New-Item -Path 'C:\temp\vistaupdated.txt' -Type File -Value 'Updated' | Out-Null
Write-Log 'Completed successfully.'
} catch {
Write-Log ('Error has occurred: {0}' -f $_.Exception.Message)
}
} else {
Write-Log 'Computer already updated. Aborting.'
}
可以为翻转“ then”和“ else”分支建立参数以避免出现否定条件:
if (Test-Path -Path 'C:\temp\vistaupdated.txt') {
Write-Log 'Computer already updated. Aborting.'
} else {
$cmdLine = ...
...
}
或直接退出脚本(如果文件存在)以完全避免else
分支:
if (Test-Path -Path 'C:\temp\vistaupdated.txt') {
Write-Log 'Computer already updated. Aborting.'
exit
}
$cmdLine = ...
...