2010年9月14日 星期二

Powershell - 執行外部命令

Summarize form source :
  1. Use [Diagnostic.Process]::Start a single line
    [Diagnostics.Process]::Start('C:\Vmware\vcbMounter.exe',"-h $host -u $user -p $password -s name:$machine -r $location -t $backuptype")
  2. Parameterize
    $application = 'C:\Vmware\vcbMounter.exe'

    $arguments = "-h {0} -u {1} -p {2} -s name:{3} -r {4} -t {5}" -f ($host, $user, $password, $machine, $location, $backuptype)
    [Diagnostics.Process]::Start('$application','$arguments')
  3. Use & replace [Diagnostic.Process]::Start
    $exe = "C:\Vmware\vcbMounter.exe"

    $host = "server"
    $user = "joe"
    $password = "cleartextpasswordsareanono:-)"
    $machine = "somepc"
    $location = "somelocation"
    $backupType = "incremental"
    & $exe -h $host -u $user -p $password -s "name:$machine" -r $location -t $backupType
  4. Get execution result
    $process = [Diagnostics.Process]::Start('$application','$arguments')

    the process object has a member HasExited that returns $true when the
    process has exited (pretty self explanatory there..)
    
    There is also a ExitCode property that has the exit code of the process.
    
    You could use a do while loop to check for the exit of the process.
    do {...} while (!$process.HasExited)
  5. Use $?, $LASTEXITCODE to get execution result
    $?

           Contains True if last operation succeeded and False otherwise.
    $LASTEXITCODE
           Contains the exit code of the last Win32 executable execution.
    EXAMPLE :
    PS> ping localhost
    Pinging jpsvista1.ntdev.corp.microsoft.com [::1] from ::1 with 32 bytes of data:
    Reply from ::1: time<1ms
    Reply from ::1: time<1ms
    Reply from ::1: time<1ms
    Reply from ::1: time<1ms
    Ping statistics for ::1:
        Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
    Approximate round trip times in milli-seconds:
        Minimum = 0ms, Maximum = 0ms, Average = 0ms
    PS> $lastexitcode

    0
    PS> ping asdfasdf
    Ping request could not find host asdfasdf. Please check the name and try again.
    PS> $lastexitcode
    1
An Example of mine : 1. 可提供將stdout寫到logfile  2.用write-progress 做執行經歷時間的輸出
    function startProcess ([string] $processname, [string] $arguments, [string]$logfile)
    {
    [String]$output=""
    $processStartInfo = New-Object System.Diagnostics.ProcessStartInfo;
    $processStartInfo.FileName = $processname;
    $processStartInfo.WorkingDirectory = (Get-Location).Path;
    if($arguments) { $processStartInfo.Arguments = $arguments }
    $processStartInfo.UseShellExecute = $false;
    if($logfile) {$processStartInfo.RedirectStandardOutput = $true}

    $process = New-Object System.Diagnostics.Process;
    $process.StartInfo=$processStartInfo
    $process.Start() 
    #$process = [System.Diagnostics.Process]::Start($processStartInfo);
    $startTime=get-Date
    $endTime=get-date
    do {
    Start-Sleep -Seconds 1
    $endTime=get-date
    $timeSpan=$endTime - $startTime
    Write-Progress -Activity "Building ... and timespan:" -Status $timeSpan  
    } while (!$process.HasExited)
    if($logfile) {$output=$process.StandardOutput.ReadToEnd() }
    $process.WaitForExit()
    $process.Close()
    if($logfile) {
    $output | Out-File $logfile ;
    "Start  at:$startTime" | Out-File $logfile -Append ;
    "End    at:$endTime" | Out-File $logfile -Append ;
    "Timespan :$timeSpan" | Out-File $logfile -Append ;
    }
    else {
    Write-Host "Start at:$startTime"
    Write-Host "End at:$endTime"
    Write-Host "Timespan : $timeSpan"
    }
    }

    沒有留言: