如果测试路径等于false,则执行应用安装

时间:2019-01-04 17:33:02

标签: powershell

我正在研究一个脚本,以测试目标目录中是否存在文件,如果为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语句中启动。相反,脚本会吐出脚本本身的路径并退出。

1 个答案:

答案 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块中。

    li>
  • 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 = ...
...