【问题标题】:Using Powershell to stop a service remotely without WMI or remoting使用 Powershell 在没有 WMI 或远程处理的情况下远程停止服务
【发布时间】:2012-04-26 22:48:50
【问题描述】:

我遇到了这个似乎可以工作的班轮:

stop-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)

谁能解释原因,因为我认为 stop-service 不起作用,除非您使用远程处理或者它发生在本地主机上。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    Get-Service 的输出是一个可以在远程计算机上运行的System.ServiceProcess.ServiceController .NET 类。我不知道它是如何做到这一点的——可能是 DCOM 或 WMI。一旦你从Get-Service 获得了其中一个,它就可以传递给Stop-Service,它很可能只是在这个对象上调用Stop() 方法。这会停止远程机器上的服务。事实上,您也可以这样做:

    (get-service -ComputerName remotePC -Name Spooler).Stop()
    

    【讨论】:

    • 注意:测试了这个方法,它确实调用了远程主机,但在继续脚本之前不会等待服务停止。如果您执行 Stop() 和 Start(),则 Start() 可能会失败,因为服务尚未停止。仅供参考,如果您想在脚本中停止(这超出了这个问题的要求)
    • 我认为只是一个 powershell 问题:是否可以从批处理文件中执行此操作,例如将多台机器的多个行放在一起(如 .bat)
    • 在较新版本(3+?)的 Powershell 中,您可以获得该服务,然后使用其.WaitForStatus method
    • @Hace 如果你是从批处理中完成的。为什么不直接使用 'sc stop ' ?
    【解决方案2】:

    感谢大家对这个问题的贡献,我想出了以下脚本。更改 $SvcName$SvrName 的值以满足您的需要。如果远程服务已停止,此脚本将启动它,如果已启动,则将其停止。它使用酷炫的.WaitForStatus 方法等待服务响应。

    #Change this values to suit your needs:
    $SvcName = 'Spooler'
    $SvrName = 'remotePC'
    
    #Initialize variables:
    [string]$WaitForIt = ""
    [string]$Verb = ""
    [string]$Result = "FAILED"
    $svc = (get-service -computername $SvrName -name $SvcName)
    Write-host "$SvcName on $SvrName is $($svc.status)"
    Switch ($svc.status) {
        'Stopped' {
            Write-host "Starting $SvcName..."
            $Verb = "start"
            $WaitForIt = 'Running'
            $svc.Start()}
        'Running' {
            Write-host "Stopping $SvcName..."
            $Verb = "stop"
            $WaitForIt = 'Stopped'
            $svc.Stop()}
        Default {
            Write-host "$SvcName is $($svc.status).  Taking no action."}
    }
    if ($WaitForIt -ne "") {
        Try {  # For some reason, we cannot use -ErrorAction after the next statement:
            $svc.WaitForStatus($WaitForIt,'00:02:00')
        } Catch {
            Write-host "After waiting for 2 minutes, $SvcName failed to $Verb."
        }
        $svc = (get-service -computername $SvrName -name $SvcName)
        if ($svc.status -eq $WaitForIt) {$Result = 'SUCCESS'}
        Write-host "$Result`: $SvcName on $SvrName is $($svc.status)"
    }
    

    当然,您运行它的帐户需要适当的权限才能访问远程计算机以及启动和停止服务。当对旧的远程机器执行此操作时,您可能首先必须在旧机器上安装 WinRM 3.0。

    【讨论】:

      【解决方案3】:

      根据内置的 Powershell 示例,这是 Microsoft 建议的。经过测试和验证:

      停止:

      (Get-WmiObject Win32_Service -filter "name='IPEventWatcher'" -ComputerName Server01).StopService()
      

      开始:

      (Get-WmiObject Win32_Service -filter "name='IPEventWatcher'" -ComputerName Server01).StartService()
      

      【讨论】:

        【解决方案4】:

        这对我有用,但我用它作为开始。 powershell 输出, 等待服务完成启动几次然后完成,然后远程服务器上的 get-service 显示服务已启动。

        **start**-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)
        

        【讨论】:

          【解决方案5】:

          另一种选择;使用invoke-command:

          cls
          $cred = Get-Credential
          $server = 'MyRemoteComputer'
          $service = 'My Service Name' 
          
          invoke-command -Credential $cred -ComputerName $server -ScriptBlock {
              param(
                 [Parameter(Mandatory=$True,Position=0)]
                 [string]$service
              )
              stop-service $service 
          } -ArgumentList $service
          

          注意:要使用此选项,您需要在远程计算机上安装 PowerShell,并让防火墙允许请求通过,并让 Windows 远程管理服务在目标计算机上运行。您可以通过直接在目标机器上运行以下脚本来配置防火墙(一次性任务):Enable-PSRemoting -force

          【讨论】:

            【解决方案6】:

            你也可以(Get-Service -Name "what ever" - ComputerName RemoteHost).Status = "Stopped"

            【讨论】:

            • 嗯算了。如果再次做get-service,它仍然处于相同的状态。我将它分配给一个变量,因此分配状态属性有效,但它实际上并没有停止远程主机上的服务。对不起
            • 这是一个只读属性:msdn.microsoft.com/en-us/library/…
            • @StéphaneLacasse,我还将它分配给变量$s = (Get-Service -Computername RemoteHost -Name MyService),然后执行$s.Stop()。然后我做了Write-host $($s.Status) 并且服务仍在运行,但是如果我等待 10 秒让服务停止,然后再次执行 $s=(Get-Service ...Write-host $($s.Status),它返回状态为“已停止”跨度>
            【解决方案7】:

            您可以只运行一个 foreach 并启用日志记录。 如果出现问题,控制台会显示,您可以查看日志。

            这样,您就可以单独处理错误。

            我认为这种方式比为验证部分运行测试网络连接效果更好,因为防火墙规则可以创建值 false。

            对于此示例,您使用列 ServerName 定义了一个 csv 文件,使用 servername.contoso.com 填充列

            $ServerList = "$PSScriptRoot\Serverlist.csv"
            
            $Transcriptlog = "$PSScriptRoot\Transcipt.txt"
                
                Start-Transcript -Path $Transcriptlog -Force
                Get-Date -Format "yyyy/MM/dd HH:mm" 
                
                Try 
                 { # Start Try  
                   $ImportServerList = Import-Csv $ServerList -Encoding UTF8 | ForEach-Object { # Start Foreach 
                    New-Object PsObject -Prop @{ # Start New-Object 
                     ServerName = $_.ServerName } # End NewObject 
                      Invoke-Command -ComputerName $_.ServerName -ErrorAction Continue -ScriptBlock  { # Start ScriptBlock  
                       # Disable Service PrintSpooler
                       Get-Service -Name Spooler | Stop-Service -Force 
                
                   } # End ScriptBlock
                  } # End Foreach       
                 } # End Try
                
                Catch
                 { # Start Catch 
                  Write-Warning -Message "## ERROR## " 
                  Write-Warning -Message "## Script could not start ## " 
                  Write-Warning $Error[0]
                 } # End Catch
                
                Stop-Transcript
            

            【讨论】:

              【解决方案8】:

              stop-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)

              由于您的变量而失败 -ComputerName remotePC 需要是变量 $remotePC 或字符串 "remotePC" -Name Spooler(spooler 也是一样)

              【讨论】:

                【解决方案9】:

                据我所知,我现在无法验证,您无法使用 Stop-Service cmdlet 或 .Net 停止远程服务,它不受支持。

                是的,它可以工作,但它会停止本地计算机上的服务,而不是远程计算机上的服务。

                现在,如果上述情况正确,则无需启用远程处理或 wmi,您可以使用 AT 在远程系统上设置计划作业,该作业在本地运行 Stop-Service。

                【讨论】:

                • 我已经验证它确实可以工作并且不会停止本地计算机上的服务。我很惊讶它没有被广为人知/使用。
                猜你喜欢
                • 2022-01-18
                • 1970-01-01
                • 2011-04-23
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-10-25
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多