Powershell:如何找出哪些正在运行的服务不是';操作系统和非MS的t部分

Powershell:如何找出哪些正在运行的服务不是';操作系统和非MS的t部分,powershell,service,Powershell,Service,有没有办法使用Powershell找出哪些运行的服务不是Windows的本机服务?换句话说,这些服务不是Windows操作系统的一部分,也是非Microsoft的。我想了解我们的供应商安装的所有服务。 查找正在运行的服务很容易: Get Service | Where Object{$\uu.Status-eq“Running”}您不能单独使用它Get Service,因为即使它输出的服务信息对象具有.BinaryPathName属性,该属性仅在PowerShell Core中可用,不一定是真正

有没有办法使用Powershell找出哪些运行的服务不是Windows的本机服务?换句话说,这些服务不是Windows操作系统的一部分,也是非Microsoft的。我想了解我们的供应商安装的所有服务。
查找正在运行的服务很容易:


Get Service | Where Object{$\uu.Status-eq“Running”}
您不能单独使用它
Get Service
,因为即使它输出的服务信息对象具有
.BinaryPathName
属性,该属性仅在PowerShell Core中可用,不一定是真正的服务二进制文件
,它通常是由通用
svchost.exe
服务主机托管的DLL

要在所有情况下查找二进制文件路径,您还必须(还)查询注册表中的服务定义。获得文件路径后,可以使用返回的文件信息对象的
Get Item
.VersionInfo
属性提取产品和公司名称等信息

底部的
getservicefileinfo
函数就是这样做的;它允许您运行以下命令:

# Return information about all services that aren't part of Windows.
# (May still include Microsoft services).
Get-ServiceFileInfo | Where ProductName -ne 'Microsoft® Windows® Operating System'

Get-ServiceFileInfo
源代码(PSv5+,但可以调整为适用于较低版本):
#注意:虽然可以在没有提升权限的情况下运行,
#并不是所有的文件信息都可以检索。
#需要-运行管理员
函数Get ServiceFileInfo{
设置StrictMode-版本1
获取每个对象的服务| ForEach{
#仅限PowerShell核心:
#获取服务二进制路径,它可能是也可能不是真正的服务
#可执行文件。
$binaryPath=$\二进制路径名
#Windows PowerShell:
#我们转而尝试从注册表中获取“ImagePath”值。
#注意:即使在PowerShell Core中,似乎也存在获取服务失败的服务
#即使以管理员身份运行,也要进行查询,例如“SshdBroker”
#(发出非终止错误)。
#在这种情况下,也需要从注册表读取数据,
#但是,只有在以管理员身份运行时才能成功。
if(-not$binaryPath){
$binaryPath=尝试{Get-ItemPropertyValue-EA Ignore“HKLM:\SYSTEM\CurrentControlSet\Services\$($\ux.Name)”ImagePath}catch{}
}
#测试svchost.exe,这表明需要在别处查找特定于服务的DLL路径。
if($binaryPath-类似'*\svchost.exe*')){
#从注册表、子项“Parameters”和值“ServiceDLL”获取实际二进制文件(DLL)
#注意:某些服务存在于*2*(多个?)的化身中,如“”“和”\ux”
#只有“”化身具有“ServiceDLL”值,因此我们依赖于此。
foreach($\中的keyName,($\中的keyName-split'\')[0]){
#注意:大多数基于DLL的服务将“ServiceDLL”值存储在“Parameters”子项中,但
#有些在服务的根密钥本身中有。
foreach($keyName\Parameters中的subKeyName,$keyName){
$binaryPath=尝试{Get-ItemPropertyValue-EA Ignore“HKLM:\SYSTEM\CurrentControlSet\Services\$subKeyName”ServiceDLL}catch{}
if($binaryPath){break}
}
}
}
#清理路径:
#*有些值包含“…”,因此我们将其去掉,
#*其他人有争论,所以我们只接受第一个标记。
$binaryPath=if($binaryPath.StartsWith(“”)){
($binaryPath-split'')[1]
}否则{
#路径/命令行没有或没有以双引号标记开头,这
#可能意味着两件事之一:
#*它是一个基于无引号可执行文件的命令行,可能带有参数。
#*它是一个服务DLL路径-可能在(扩展)路径中有空格。
if(测试路径-LiteralPath$binaryPath-Type叶){
$binaryPath#值作为一个整体是一个文件路径
}否则{
(-split$binaryPath)[0]#值是一个命令行,提取可执行文件
}
}
$FileVersionInfo=if($binaryPath){(获取项-LiteralPath$binaryPath).VersionInfo}
#构造输出对象。
[pscustomobject]@{
名称=$\名称
BinaryPath=if($BinaryPath){$BinaryPath}else{(n/a);“写入错误”无法确定服务“$($.Name)”的二进制路径。请尝试以管理员身份运行。“”
ProductName=$FileVersionInfo.ProductName
FileDescription=$FileVersionInfo.FileDescription
CompanyName=$FileVersionInfo.CompanyName
}
}
}

我不知道这个问题的答案。我可以告诉你,不管怎样,我都将如何处理。我将查看从模板或映像部署的新版本上安装的服务,或者以其他方式部署新系统。然后我将新系统的
get service
输出与系统I的输出进行比较n问题。
# Note: While it is possible to run without elevated privileges,
#       not all file information is retrievable then.
#requires -runAsAdministrator

function Get-ServiceFileInfo {

  Set-StrictMode -Version 1

  Get-Service | ForEach-Object {

    # PowerShell Core only:
    # Get the service binary path, which may or may not be the true service 
    # executable.
    $binaryPath = $_.BinaryPathName
    
    # Windows PowerShell:
    # We fall back on trying to obtain the "ImagePath" value from the registry.
    # Note: Even in PowerShell Core there appear to be services that Get-Service fails 
    #       to query even when running as admin, such as "SshdBroker"
    #       (a non-terminating error is issued).
    #       Reading from the registry is needed in that case too, 
    #       but, only succeeds when running as admin.
    if (-not $binaryPath) {
      $binaryPath = try { Get-ItemPropertyValue -EA Ignore "HKLM:\SYSTEM\CurrentControlSet\Services\$($_.Name)" ImagePath } catch { }
    }
    
    # Test for svchost.exe, which indicates the need to look for the service-specific DLL path elsewhere.
    if ($binaryPath -like '*\svchost.exe *') {
      # Get the actual binary (DLL) from the registry, subkey "Parameters", value "ServiceDLL"
      # NOTE: Some services exist in *2* (multiple?) incarnations, as "<name>"" and "<name>_<num>"
      #       Only the "<name>" incarnation has the "ServiceDLL" value, so we fall back on that.
      foreach ($keyName in $_.Name, ($_.Name -split '_')[0]) {
        # NOTE: Most DLL-based services store the "ServiceDLL" value in the "Parameters" subkey, but
        #       some have it in the service's root key itself.
        foreach ($subKeyName in "$keyName\Parameters", $keyName) {
          $binaryPath = try { Get-ItemPropertyValue -EA Ignore "HKLM:\SYSTEM\CurrentControlSet\Services\$subKeyName" ServiceDLL } catch { }
          if ($binaryPath) { break }
        }
      }
    }
    
    # Sanitize the path:
    # * Some values have enclosing "...", so we strip them, 
    # * others have arguments, so we only take the first token.
    $binaryPath = if ($binaryPath.StartsWith('"')) {
      ($binaryPath -split '"')[1]
    } else {
      # The path / command line isn't or doesn't start with a double-quoted token, which
      # can mean one of two things:
      #  * It is a command line based on an unquoted executable, possibly with arguments.
      #  * It is a service DLL path - possibly with spaces in the (expanded) path.
      if (Test-Path -LiteralPath $binaryPath -Type Leaf) {
        $binaryPath # Value as a whole is a file path
      } else {
        (-split $binaryPath)[0] # Value is a command line, extract executable
      }
    }

    $FileVersionInfo = if ($binaryPath) { (Get-Item -LiteralPath $binaryPath).VersionInfo }

    # Construct the output object.        
    [pscustomobject] @{
      Name = $_.Name
      BinaryPath = if ($binaryPath) { $binaryPath } else { '(n/a)'; Write-Error "Failed to determine binary path for service '$($_.Name)'. Try running as admin." }
      ProductName = $FileVersionInfo.ProductName
      FileDescription = $FileVersionInfo.FileDescription
      CompanyName = $FileVersionInfo.CompanyName
    }
    
  }

}