Return Value 1191 for the Win32Shutdown Method in PowerShell

Problem:

When I run the following cmdlet, where ck-acer is a remote computer in a homegroup; it works fine.

        $os=Get-WmiObject -Class Win32_OperatingSystem -ComputerName ck-acer
        $os.Win32Shutdown(0) # 0=Logoff, 1=ShutDown, 2= Restart, 8=PowerOff

But when I log on again and change the parameter value to 1, the cmdlet does not shutdown the remote PC as expected. It returns a value of 1191. The same thing for the value 2 or 8.

Reason:

1191 indicates the system shutdown cannot be initiated because there are other users logged on to the computer.

See http://www.mathemainzel.info/files/w32errcodes.html for more return values

Solution 1:

Run logoff first, then other action (do not logon again!). For example, the cmdlets below will shutdown the remote machine ck-acer

        $os=Get-WmiObject -Class Win32_OperatingSystem -ComputerName ck-acer
        $os.Win32Shutdown(0)
        $os.Win32Shutdown(1)

Solution 2 - Implementing the -force parameter:

    Function Set-ComputerState
    {
   [CmdletBinding(SupportsShouldProcess = $True,
      ConfirmImpact = 'High')]
   param (
   [Parameter(Mandatory = $True,
      ValueFromPipeline = $True)]
   [string[]]$ComputerName,
   [Parameter(Mandatory = $True)]
   [ValidateSet("LogOff","Shutdown","Restart","PowerOff")]
   [string]$Action,
   [switch]$Force
   )

            Begin {
            Write-Verbose "Starting Set-Computerstate"

            #set the state value
            Switch ($Action) {
            "LogOff"   { $Flag=0}
            "ShutDown" { $Flag=1}
            "Restart"  { $Flag=2}
            "PowerOff" { $Flag=8}
            }
            if ($Force) {
                Write-Verbose "Force enabled"
                $Flag+=4
            }
        } #Begin

        
        Process {
            Foreach ($computer in $Computername) {
                Write-Verbose "Processing $computer"
                $os=Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer

                if ($PSCmdlet.ShouldProcess($computer)) {
                    Write-Verbose "Passing flag $flag"
                    $os.Win32Shutdown($flag)
                }

            } #foreach
    
        } #Process

        End {
            Write-Verbose "Ending Set-Computerstate"

        } #end

    }
        
        ## Test it
        Set-ComputerState –computername ck-acer –Action shutdown –Force -verbose