Search code examples
powershelliis

How to ensure IIS website is completely stopped in Powershell?


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
            }
        }

Solution

  • 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")