usr/lib/Get-LoadOrder.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Set-Alias -Name loadord -Value Get-LoadOrder
function Get-LoadOrder {
  [CmdletBinding()]param([Parameter()][Switch]$AsTable)

  begin {
    $root = 'HKLM:\SYSTEM\CurrentControlSet'
    $type = 'Boot', 'System', 'Automatic' # launching types
    $group = (Get-ItemProperty "$root\Control\ServiceGroupOrder").List
    $items = ($rk = Get-Item "$root\Services").GetSubKeyNames().ForEach{
      if (($start = ($sub = $rk.OpenSubkey($_)).GetValue('Start')) -lt 3) {
        [PSCustomObject]@{
          Name = $_
          Group = $sub.GetValue('Group')
          Start = $start
          Tag   = $sub.GetValue('Tag')
          Image = $sub.GetValue('ImagePath')
        }
      }
      $sub.Dispose()
    }
    $rk.Dispose()
    $order = @{} # approximate launch order
    ($rk = Get-Item "$root\Control\GroupOrderList").GetValueNames().ForEach{
      $order[$_] = @()
      $value = $rk.GetValue($_)
      for ($i = 0; $i -lt $value.Length; $i += 3) {
        $order[$_] += [BitConverter]::ToUInt16($value[$i..($i + 3)], 0)
        $i++
      }
      # remove tags counter
      $order[$_] = $order[$_][1..($order[$_].Length - 1)]
    }
    $rk.Dispose()

    function private:Get-Objects([String]$Value) {
      process {
        $scope = $items.Where{$_.Start -eq $type.IndexOf($Value)}
        $parts = $scope | Group-Object -Property Group
        $parts = foreach ($i in $(foreach ($g in $group) {
          $parts.Where{$_.Name -eq $g}
        })) {
          if ($i.Count -gt 1) {
            $cast = $i.Group.Where{$_.Tag}
            $($(foreach ($o in $order[$i.Name]) {
              $i.Group.Where{$_.Tag -eq $o}
            }), $cast.Where{
              $_.Tag -notin $order[$i.Name]
            }, $i.Group.Where{!$_.Tag}).ForEach{$_}
          }
          else { $i.Group }
        }
        $parts += $scope.Where{$_.Group -notin $group}
        foreach ($p in $parts) {
          [PSCustomObject]@{
            StartType = $Value
            Group = $p.Group
            Tag = $p.Tag
            ServiceOrDevice = $p.Name
            ImagePath = $p.Image
          }
        }
      }
    }
  }
  process {}
  end {
    $type = $type.ForEach{Get-Objects $_}
    $AsTable ? (Format-Table -InputObject $type -AutoSize) : $type
  }
}

Export-ModuleMember -Alias loadord -Function Get-LoadOrder