Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure IIS website is completely stopped in Powershell?

Tags:

powershell

iis

I've got a Powershell script that stops an IIS website and corresponding app pool and then deletes the app logs (log4net logs). Here is the script snippet:

stop-website -name "MyWebsite"
stop-webapppool -name "MyWebsite"
del c:\inetpub\MyWebsite\logs\*.*

The problem is stop-website and stop-webapppool seem to return before the website is completely shutdown which results in the delete failing saying the file is being used by another process:

del : Cannot remove item C:\inetpub\MyWebsite\logs\App.log: The process cannot access the file 'C:\inetpub\MyWebsite\logs\App.log' because it is being used by another process.

If I add a 10 second sleep between the stop commands and the del command then the logs are deleted successfully. This is very hackish though and not reliable. Is there a way to force the stop-website/stop-webapppool commands to not return until the website/apppool is completely stopped?

Thanks.


Implemented solution from the below link. I will wait ~60 seconds and then kill the IIS process if it hasn't stopped.

https://greenfinch.ie/blog/powershellscript.html

        "Stopping IIS site [$name]" >> $logFile
        stop-website -name $name

        "Stopping app pool [$name]" >> $logFile
        stop-webapppool -name $name

        $sleepTime = 5
        $processId = $TRUE
        while ($processId)
        {
            $processId = Get-WmiObject -Class win32_process -filter "name='w3wp.exe'" |
                            ?{ ($_.CommandLine).Split("`"")[1] -eq $name } |
                            %{ $_.ProcessId }

            if ($sleepTime -gt 60)
            {
                "Waited [$sleepTime] sec for process [$processId] to stop and it is still running. Killing it." >> $logFile
                Stop-Process $processId
                break
            }

            if ($processId)
            {
                "App pool [$name] is running with process ID: [$processId]. Sleeping for [$sleepTime] sec and then checking again." >> $logFile
                Start-Sleep -s $sleepTime
                $sleepTime = $sleepTime + 10
            }
        }
like image 408
user1574808 Avatar asked May 09 '16 16:05

user1574808


2 Answers

You can use these two commands to check the status of the website/app, say after 10 seconds, then use an If statement to delete logs only when the status returned is stopped

Get-WebsiteState -name "MyWebsite"
Get-WebAppPoolState -name "MyWebsite"

This loop should help you too

$currentRetry = 0;
$success = $false;
do{
    $status = Get-WebAppPoolState -name "MyWebsite"
    if ($status -eq "Stopped"){
         <....your code here....>
            $success = $true;
        }
        Start-Sleep -s 10
        $currentRetry = $currentRetry + 1;
    }
while (!$success -and $currentRetry -le 4)

Updated Apr 24, 2019

Based on comment and current cmdlet document, it appears the return type is indeed an object. Thus presumably can be handled as commented or the line snippet below. Author no longer have access to Windows Server environment therefore did not directly modify original answer nor able to test the update

if ($status.Value -eq "Stopped")
like image 74
Kai Zhao Avatar answered Oct 23 '22 22:10

Kai Zhao


The simplest way to stop the app pool and get it into Stopped state is to use appcmd.exe. It will return when the app pool is really stopped or you'll get an error

Just do this on PowerShell:

& $env:windir\system32\inetsrv\appcmd.exe stop apppool /apppool.name:"YourAppPoolName"

When your AppPool is correctly stooped you'll get this message:

"YourAppPoolName" successfully stopped

like image 30
CodeNotFound Avatar answered Oct 23 '22 22:10

CodeNotFound