Guest User

Untitled

a guest
May 21st, 2018
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.56 KB | None | 0 0
  1. #requires -Version 4.0 -Modules PoshRSJob
  2. Using Namespace System.Collections.Generic
  3. Using Namespace System.Text.RegularExpressions
  4.  
  5. Set-StrictMode -Version Latest
  6.  
  7. function Search-KBPhysicalDriveSerialNumber {
  8. <#
  9. .SYNOPSIS
  10. Searches for physical drives matching one or more specified serial numbers.
  11. .DESCRIPTION
  12. The Search-KBPhysicalDriveSerialNumber cmdlet searches for physical drives on remote computers that match specified one or more serial number regular expressions.
  13. .PARAMETER ComputerName
  14. Specifies single or multiple computers.
  15. .PARAMETER SerialNumber
  16. Specifies one or more serial number regular expressions that will be used to match serial numbers of physical drives against.
  17. .PARAMETER Timeout
  18. Determines how long the client computer waits for the session connection to be established.
  19. .EXAMPLE
  20. Search-KBPhysicalDriveSerialNumber -Computer 'WORKSTATION' -SerialNumber '15351740', '11GDT5UWT'
  21.  
  22. This cmdlet searches computer with name 'WORKSTATION' for physical drives that match serial number regular expressions of '15351740' and '11GDT5UWT'.
  23. #>
  24. [CmdletBinding()]
  25. [OutputType('KBPhysicalDriveSerialNumber')]
  26. param(
  27. [Parameter(Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
  28. [Alias('CN', '__SERVER')]
  29. [ValidateNotNullOrEmpty()]
  30. [String[]]$ComputerName = $env:COMPUTERNAME,
  31.  
  32. [ValidateNotNullOrEmpty()]
  33. [String[]]$SerialNumber = '.*',
  34.  
  35. [ValidateRange(0, 300)]
  36. [Int]$Timeout = 0
  37. )
  38.  
  39. begin {
  40. $computers = [List[String]]::new()
  41.  
  42. try {
  43. $driveSerialNumberRegex = [Regex]::new(($SerialNumber -join '|'), [RegexOptions]::IgnoreCase)
  44. } catch [System.Management.Automation.MethodInvocationException] {
  45. Write-Error -Message ("Invalid SerialNumber RegEx pattern: {0}" -f $_.Exception.InnerException.Message) -ErrorAction Stop
  46. }
  47. }
  48.  
  49. process {
  50. $computers.AddRange($ComputerName)
  51. }
  52.  
  53. end {
  54. try {
  55. $jobBatch = ([Guid]::NewGuid()).Guid
  56. $cpuCount = [Int]($env:NUMBER_OF_PROCESSORS) * 4
  57.  
  58. [Void]$PSBoundParameters.Remove('SerialNumber')
  59. [Void]$PSBoundParameters.Remove('ComputerName')
  60. [Void]$PSBoundParameters.Remove('Timeout')
  61.  
  62. $jobsPool = $computers | Start-RSJob -Name {$_} -Batch $jobBatch -Throttle $cpuCount -VariablesToImport @('Timeout') -ScriptBlock {
  63. #Code inside ScriptBlock has to be compatible with PS 2.0 in order to support Windows 2003 and XP
  64. $diskDriveProperty = @{Property = 'DeviceID', 'Caption', 'Size'; Filter = "Size > 0"}
  65. $diskDriveSelect = @{Property = 'DeviceID', 'Caption', 'Size'}
  66. $diskDriveSort = @{Property = 'DeviceID'}
  67.  
  68. $physicalMediaProperty = @{Property = 'Tag', 'SerialNumber'; Filter = "Tag LIKE '%PHYSICALDRIVE%' AND SerialNumber LIKE '%[a-z0-9]%'"}
  69. $physicalMediaSelect = @{Property = 'Tag', 'SerialNumber'}
  70.  
  71. Invoke-Command -ComputerName $_ -HideComputerName -SessionOption (New-PSSessionOption -OpenTimeout $Timeout) -ScriptBlock {
  72.  
  73. $physicalDriveCollection = New-Object -TypeName 'PSObject' -Property @{
  74. PhysicalDrive = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
  75. Status = 'Success'
  76. }
  77.  
  78. try {
  79. if (Get-Command -Name Get-CimInstance -CommandType Cmdlet -ErrorAction SilentlyContinue) {
  80. $diskDrive = Get-CimInstance -ClassName 'Win32_DiskDrive' @using:diskDriveProperty -ErrorAction Stop | Select-Object @using:diskDriveSelect | Sort-Object @using:diskDriveSort
  81. $physicalMedia = Get-CimInstance -ClassName 'Win32_PhysicalMedia' @using:physicalMediaProperty -ErrorAction Stop | Select-Object @using:physicalMediaSelect
  82. } else {
  83. $diskDrive = Get-WmiObject -Class 'Win32_DiskDrive' @using:diskDriveProperty -ErrorAction Stop | Select-Object @using:diskDriveSelect | Sort-Object @using:diskDriveSort
  84. $physicalMedia = Get-WmiObject -Class 'Win32_PhysicalMedia' @using:physicalMediaProperty -ErrorAction Stop | Select-Object @using:physicalMediaSelect
  85. }
  86.  
  87. foreach ($disk in $diskDrive) {
  88. foreach ($media in $physicalMedia) {
  89. if ($disk.DeviceID -eq $media.Tag) {
  90. $physicalDriveCollection.PhysicalDrive.Add((New-Object -TypeName 'PSObject' -Property @{
  91. ComputerName = $env:COMPUTERNAME
  92. DeviceID = $disk.DeviceID -replace '\\\\\.\\'
  93. Caption = $disk.Caption
  94. Size = $disk.Size
  95. SerialNumber = $media.SerialNumber.Trim()
  96. }))
  97. }
  98. }
  99. }
  100. } catch {
  101. $physicalDriveCollection.Status = ('Error: {0}' -f $_.Exception.Message.Trim())
  102. }
  103.  
  104. #Output data
  105. $physicalDriveCollection
  106. } -ErrorAction SilentlyContinue | Select-Object -Property * -ExcludeProperty RunspaceID
  107. }
  108.  
  109. $driveCollection, $errorCollection = @(Wait-RSJob -Batch $jobBatch -ShowProgress | Receive-RSJob).Where({$_.Status -eq 'Success'}, 'Split')
  110.  
  111. $failedJobs = @(@($jobsPool).Where({$_.HasErrors}) | Select-Object -ExpandProperty Name)
  112.  
  113. if (($PSBoundParameters.ContainsKey('Verbose')) -and ($failedJobsCount = $failedJobs.Count) -gt 0) {
  114. Write-Verbose ("RSJob execution errors [{0}/{1}]:" -f $failedJobsCount, @($jobsPool).Count)
  115. $failedJobs.ForEach({Write-Verbose $_})
  116. }
  117.  
  118. Show-KBErrorCollection -ErrorCollection $errorCollection @PSBoundParameters
  119.  
  120. Remove-RSJob -Batch $jobBatch -Force
  121.  
  122. $foundDrives = [List[PSObject]]::new()
  123.  
  124. foreach ($driveSet in $driveCollection) {
  125. foreach ($drive in $driveSet.PhysicalDrive) {
  126. if ($driveSerialNumberRegex.IsMatch($drive.SerialNumber)) {
  127. $drive.PSObject.TypeNames.Insert(0, 'KBPhysicalDriveSerialNumber')
  128. $foundDrives.Add($drive)
  129. }
  130. }
  131. }
  132.  
  133. $foundDrives
  134. } catch {
  135. Write-Error -ErrorRecord $_ -ErrorAction $ErrorActionPreference
  136. }
  137. }
  138. }
Add Comment
Please, Sign In to add comment