Question

%WINDIR%\system32\inetsrv\appcmd.exe set site /site.name:"WebRole_IN_0_CB" /[Path='/'].applicationPool:"ASP.NET v4.0" >>CBLog.log
powershell.exe -command Set-ExecutionPolicy Unrestricted
powershell.exe .\CheckIfSuccessful.ps1

I would like to run the script above and if appcmd.exe can't execute it due the WebSite not yet being up and ready I would get the following error message in the CBLog.log file.

ERROR ( message:Cannot find SITE object with identifier "WebRole_IN_0_CB". )

In the CheckIfSuccessful.ps1 I would like to create a Powershell script to loop, which runs the appcmd command and checks the error again. Then sleeps for 5 seconds and then retries, until it succeeds.

How would I do this in Powershell?

highly appreciated,

UPDATE:

Ok, many thanks for the tip with $lastexitcode, while it looks promising. It seems I have problems with converting single quoates in Powershell: (The below is part of my initial appcmd command)

/[Path='/'].applicationPool:"ASP.NET v4.0"

How do I quote this in powershell? I tried to simplify it so that powershell has less trouble with it, but it seems my command is now wrong, as it says now:

ERROR ( message:Cannot find SITE object with identifier "v4.0". )

 & $Env:WinDir\system32\inetsrv\appcmd.exe set site '/site.name:"WebRole_IN_0_CB"' "/[Path='/'].applicationPool:`"ASP.NET v4.0`"" >CBLog.log
if($lastexitcode -ne '0')
{
    while($lastexitcode -ne '0')
    {
        Start-Sleep -s 5
        & $Env:WinDir\system32\inetsrv\appcmd.exe set site '/site.name:"WebRole_IN_0_CB"' "/[Path='/'].applicationPool:`"ASP.NET v4.0`"" >CBLog.log
    }
}

UPDATE II: I have escaped it properly. But still I get the error message. If I run the appcmd alone after creating that site, the log file is ok with it. Any suggestions please?

Was it helpful?

Solution

The special variable $lastexitcode gives you the exit code of the last native executable (i.e. not cmdlet) that was run. This will have different values depending on the results of the operation. For example, it will be 5 if appcmd encounters access denied. It should be 0 if the last command completed successfuolly.

Make sure you check this variable immediately after you run appcmd and in the same script. If not, you risk getting the exitcode from powershell.exe and not from appcmd.exe

OTHER TIPS

I realize that the original issue has likely longs been resolved, but for the sake of Googlers hitting this question, I wrote a general purpose (advanced) function for retrying shell (cmd) commands. In addition to $LASTEXITCODE it can also parse the error stream (with some tools, the exit code can be a lie).

function Call-CommandWithRetries
{
 [CmdletBinding()]
 param( 
     [Parameter(Mandatory=$True)]
     [string]$Command,
     [Array]$Arguments,
     [bool]$TrustExitCode = $True,
     [int]$RetrySleepSeconds = 10,
     [int]$MaxAttempts = 10,
     [bool]$PrintCommand = $True
 )

 Process
 {
  $attempt = 0
  while ($true)
  {   
   Write-Host $(if ($PrintCommand) {"Executing: $Command $Arguments"} else {"Executing command..."}) 
   & $Command $Arguments 2>&1 | tee -Variable output | Write-Host

   $stderr = $output | where { $_ -is [System.Management.Automation.ErrorRecord] }
   if ( ($LASTEXITCODE -eq 0) -and ($TrustExitCode -or !($stderr)) )
   {
    Write-Host "Command executed successfully"
    return $output
   }

   Write-Host "Command failed with exit code ($LASTEXITCODE) and stderr: $stderr" -ForegroundColor Yellow
   if ($attempt -eq $MaxAttempts)
   {
    $ex = new-object System.Management.Automation.CmdletInvocationException "All retry attempts exhausted"
    $category = [System.Management.Automation.ErrorCategory]::LimitsExceeded
    $errRecord = new-object System.Management.Automation.ErrorRecord $ex, "CommandFailed", $category, $Command
    $psCmdlet.WriteError($errRecord)
    return $output
   }

   $attempt++;
   Write-Host "Retrying test execution [#$attempt/$MaxAttempts] in $RetrySleepSeconds seconds..."
   Start-Sleep -s $RetrySleepSeconds
  }
 }
}

For more information (including full documentation) see https://www.ohadsoft.com/2016/04/invoking-arbitrary-shell-cmd-commands-in-powershell.

In your case you would do something like

$appCmd = [io.path]::combine($env:WINDIR, 'system32', 'inetsrv', 'appcmd.exe')
$appCmdArg = @('set', 'site', '/site.name:"WebRole_IN_0_CB"', '/[Path=''/''].applicationPool:"ASP.NET v4.0"')
$output = Call-CommandWithRetries $appCmd $appCmdArgs
# write $output to log etc
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top