Function that will determined if a computer is laptop or Desktop

Hi all,

I found i function that does as written in the subject and tried to customize it to my needs with no luck.

I’m trying to run it on a specific OU in my domain. When i run it with only one computer name it runs ok, but on the OU it returns errors.

Any help will be appreciated.

Here is the original script which works fine:

Function Detect-Laptop
{
Param( [string]$computer = “some computer name” )
$isLaptop = $false
#The chassis is the physical container that houses the components of a computer. Check if the machine's chasis type is 9.Laptop 10.Notebook 14.Sub-Notebook
if(Get-WmiObject -Class win32_systemenclosure -ComputerName $computer | Where-Object { $_.chassistypes -eq 9 -or $_.chassistypes -eq 10 -or $_.chassistypes -eq 14})
{ $isLaptop = $true }
#Shows battery status , if true then the machine is a laptop.
if(Get-WmiObject -Class win32_battery -ComputerName $computer)
{ $isLaptop = $true }
$isLaptop
}
If(Detect-Laptop) { “it's a laptop” }
else { “it's not a laptop”}

 

Now my customize script:

Function Detect-Laptop
{
Param( $computer )
$isLaptop = $false
#The chassis is the physical container that houses the components of a computer. Check if the machine's chasis type is 9.Laptop 10.Notebook 14.Sub-Notebook
if(Get-WmiObject -Class win32_systemenclosure -ComputerName $computer | Where-Object { $_.chassistypes -eq 9 -or $_.chassistypes -eq 10 -or $_.chassistypes -eq 14})
{ $isLaptop = $true }
#Shows battery status , if true then the machine is a laptop.
if(Get-WmiObject -Class win32_battery -ComputerName $computer)
{ $isLaptop = $true }
$isLaptop
}
$SourceOU = "OU=OldComputers,DC=******,DC=local"
$Computers = Get-ADComputer -Filter * -SearchBase $SourceOU -Properties OperatingSystem
foreach ($CompOS in $Computers)
{

If(Detect-Laptop $CompOS.Name) { “$CompOS it's a laptop” }
else { “$CompOS it's not a laptop”}


This is the error i’m getting:

 

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:6 char:4

  • if(Get-WmiObject -Class win32_systemenclosure -ComputerName $computer | Where-Ob …
  • CategoryInfo : InvalidOperation: (:slight_smile: [Get-WmiObject], COMException
  • FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:9 char:4

  • if(Get-WmiObject -Class win32_battery -ComputerName $computer)
  • CategoryInfo : InvalidOperation: (:slight_smile: [Get-WmiObject], COMException
  • FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

When you do this on only one computer, are you only doing it on your local computer? Are you able to successfully run this on only one remote computer?

‘RPC’ is Remote Procedure Call. The most likely problem is that your firewall is blocking your information requests, so it works on your computer but not when you try to query other computers. More information here. It might be as simple as starting the necessary remote services.

@dady Would be glad if you could format the code with below instruction. (you would have noticed this post in the first page of the forum)

https://powershell.org/forums/topic/read-me-before-posting-youll-be-glad-you-did/

You’re using -filter * in your AD query. This will return every computer object in your searchbase and some of those computers will, inevitably, be switched off.

I would test to see if the computer is on before attempting to query the machine and also wrap the WMI query in a try/catch block to handle any errors if the computer is on but unable to process the query for some reason.

Example:

foreach ($computer in $computers) {

    if (Test-Connection $computer -Count 1 -Quiet) {

        try {

            Get-WmiObject Win32_ComputerSystem -ComputerName $computer -ErrorAction Stop

        } #end try

        catch {

            Write-Output "$computer is on but WMI Query failed" | Out-File c:\temp\errorlog.txt -Append -NoClobber

        } #end catch

    } #end if

    else {

        Write-Output "$computer did not respond to ping" | Out-File c:\temp\errorlog.txt -Append -NoClobber

    } #end else

} #end foreach

Try this…

Clear-Host

Function Detect-Laptop
{
    Param( $computer )
    $isLaptop = $false
    <#
    The chassis is the physical container that houses the components of a computer. 
    Check if the machine's chasis type is 9.Laptop 10.Notebook 14.Sub-Notebook
    #>

    if (Get-WmiObject -Class win32_systemenclosure -ComputerName $computer | 
        Where-Object { $_.chassistypes -eq 9 -or $_.chassistypes -eq 10 -or $_.chassistypes -eq 14 })
    {  $isLaptop = $true }

    # Shows battery status , if true then the machine is a laptop.
    if (Get-WmiObject -Class win32_battery -ComputerName $computer)
    { $isLaptop = $true }
}

$SourceOU = (Get-ADOrganizationalUnit -Filter * ).DistinguishedName[0]
$Computers = Get-ADComputer -Filter '*' -SearchBase $SourceOU -Properties OperatingSystem


foreach ($CompOS in $Computers)
{
    If (Test-Connection -ComputerName $CompOS.Name -Quiet -Count 1)
    {
        If (Detect-Laptop $CompOS.Name) 
        { "$($CompOS.Name) it's a laptop" }
        else { "$($CompOS.Name) it's not a laptop" }
    }
    Else {Write-Warning -Message "$($CompOS.Name) is offline or not reachable."}
}

# Results

DC01 it's not a laptop

Thanks all.

I did the changes and now its working.