---
title: "PowerShell Tool-Building 101: Building a Computer Inventory Report"
description: "Join me on an exciting journey as we build a powerful PowerShell tool for generating computer inventory reports! From CSV files to CIM queries and error handling, we'll walk you through each step as we go. Let's script our way to success!"
canonical: "https://adamtheautomator.com/powershell-tools-csv-cim/"
---

# PowerShell Tool-Building 101: Building a Computer Inventory Report

> Join me on an exciting journey as we build a powerful PowerShell tool for generating computer inventory reports! From CSV files to CIM queries and error handling, we'll walk you through each step as we go. Let's script our way to success!

Source: https://adamtheautomator.com/powershell-tools-csv-cim/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![PowerShell Tool-Building 101: Building a Computer Inventory Report](https://adamtheautomator.com/wp-content/uploads/2026/08/26258_featured_image.webp)

# PowerShell Tool-Building 101: Building a Computer Inventory Report

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)30 May 20243 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[PowerShell](/tag/powershell/)

Table of Contents

*   [Step 1: Reading and Processing a CSV File](#step-1-reading-and-processing-a-csv-file)
*   [Step 2: Adding a Connection Check](#step-2-adding-a-connection-check)
*   [Step 3: Processing Each Computer](#step-3-processing-each-computer)
*   [Step 4: Creating the Output Object](#step-4-creating-the-output-object)
*   [Step 5: Processing All Computers](#step-5-processing-all-computers)
*   [Step 6: Adding CIM Query](#step-6-adding-cim-query)
*   [Step 7: Refactoring Using the Pipeline](#step-7-refactoring-using-the-pipeline)
*   [Step 8: Saving Output to CSV](#step-8-saving-output-to-csv)
*   [Step 9: Adding Error Handling](#step-9-adding-error-handling)

PowerShell tool-building is an essential part of learning to go from a copy/paste scripter to someone that can build real, reusable scripts. As an example of a tool-building methodology, let’s build a simple computer inventory report tool that will walk you through the process of building a simple yet effective tool using PowerShell.

We’ll start with reading data from a CSV file, then query computer details using CIM, and finally output the results into a structured format. Let’s get started!

## Step 1: Reading and Processing a CSV File

First, we need to set up our environment. We’ll create a sample CSV file containing a computer name and deparment that computer may be in. I’ll also create a blank script called Start-ComputerInventoryReport.ps1.

```
# Sample CSV content
@'
ComputerName,Department
PC1,HR
PC2,Finance
'@ | Set-Content -Path C:computers.csv

Set-Content -Path C:Start-ComputerInventoryReport.ps1 -Value ''
```

Next, open up C:Start-ComputerInventoryReport.ps1 in your favorite editor and let’s get scripting!

First, read the computers into a CSV file. You should see each CSV row.

```
$computers = Import-Csv -Path C:computers.csv
$computers
```

This will import our CSV file and store the data in the `$computers` variable.

## Step 2: Adding a Connection Check

I always recommend starting small; start with a single object and then build upon that. So start working with a single computer and get all of the code down.

Since our script will query remote computers, it’s a good practice to check if the computer is online before proceeding:

```
Test-Connection -ComputerName $computers[0].ComputerName -Count 1 -Quiet
```

This command will return `True` if the machine is online and `False` otherwise.

## Step 3: Processing Each Computer

To handle multiple computers, we’ll use a `foreach` loop:

```
foreach ($computer in $computers) {
    Write-Host "Processing the [$($computer.ComputerName)] computer."
}
```

For now, let’s focus on a single computer by temporarily adjusting our loop:

```
foreach ($computer in $computers[0]) {
    Write-Host "Processing the [$($computer.ComputerName)] computer."
}
```

## Step 4: Creating the Output Object

We want to gather the `ComputerName`, `Department`, and `IsOnline` properties. Let’s create a hashtable and convert it to a custom object:

```
foreach ($computer in $computers[0]) {
    $output = @{
        ComputerName = $computer.ComputerName
        Department   = $computer.Department
        IsOnline     = $null
    }
    [pscustomobject]$output
}
```

Now, populate the `IsOnline` property using the `Test-Connection` command:

```
foreach ($computer in $computers[0]) {
    $output = @{
        ComputerName = $computer.ComputerName
        Department   = $computer.Department
        IsOnline     = $null
    }

    $isOnline = Test-Connection -ComputerName $computer.ComputerName -Count 1 -Quiet
    $output.IsOnline = $isOnline
    [pscustomobject]$output
}
```

## Step 5: Processing All Computers

Finally, remove the temporary single computer focus and process all computers:

```
foreach ($computer in $computers) {
    $output = @{
        ComputerName = $computer.ComputerName
        Department   = $computer.Department
        IsOnline     = $null
    }

    $isOnline = Test-Connection -ComputerName $computer.ComputerName -Count 1 -Quiet
    $output.IsOnline = $isOnline
    [pscustomobject]$output
}
```

## Step 6: Adding CIM Query

Let’s extend our tool to gather additional information such as the manufacturer, model, CPU count, and total RAM from each computer using the CIM class `Win32_ComputerSystem`:

```
foreach ($computer in $computers) {
    $output = @{
        ComputerName = $computer.ComputerName
        Department   = $computer.Department
        IsOnline     = $null
        Manufacturer = $null
        Model        = $null
        CPUCount     = $null
        TotalRAM     = $null
    }

    $isOnline = Test-Connection -ComputerName $computer.ComputerName -Count 1 -Quiet
    $output.IsOnline = $isOnline

    if ($isOnline) {
        $systemInfo = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $computer.ComputerName
        $output.Manufacturer = $systemInfo.Manufacturer
        $output.Model        = $systemInfo.Model
        $output.CPUCount     = $systemInfo.NumberOfProcessors
        $output.TotalRAM     = $systemInfo.TotalPhysicalMemory
    }

    [pscustomobject]$output
}
```

## Step 7: Refactoring Using the Pipeline

To make our tool more flexible, let’s refactor it to accept input from the pipeline. This allows us to use various data sources, not just CSV files:

```
[CmdletBinding()]
param(
    [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
    [string]$ComputerName
)

process {
    $output = @{
        ComputerName = $ComputerName
        IsOnline     = $null
        Manufacturer = $null
        Model        = $null
        CPUCount     = $null
        TotalRAM     = $null
    }

    $isOnline = Test-Connection -ComputerName $ComputerName -Count 1 -Quiet
    $output.IsOnline = $isOnline

    if ($isOnline) {
        $systemInfo = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $ComputerName
        $output.Manufacturer = $systemInfo.Manufacturer
        $output.Model        = $systemInfo.Model
        $output.CPUCount     = $systemInfo.NumberOfProcessors
        $output.TotalRAM     = $systemInfo.TotalPhysicalMemory
    }

    [pscustomobject]$output
}
```

You can now pipe data from various sources:

```
Get-ADComputer -Filter * -SearchBase "OU=IT, DC=contoso, DC=com" |
Select-Object -Property *,@{n='ComputerName';e={$_.Name}} -ExcludeProperty Name |
C:Start-ComputerInventoryReportv4.ps1
```

## Step 8: Saving Output to CSV

Let’s add functionality to save the output to a CSV file:

```
[CmdletBinding()]
param(
    [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
    [string]$ComputerName,

    [Parameter()]
    [string]$OutputFilePath
)

process {
    $output = @{
        ComputerName = $ComputerName
        IsOnline     = $null
        Manufacturer = $null
        Model        = $null
        CPUCount     = $null
        TotalRAM     = $null
    }

    $isOnline = Test-Connection -ComputerName $ComputerName -Count 1 -Quiet
    $output.IsOnline = $isOnline

    if ($isOnline) {
        $systemInfo = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $ComputerName
        $output.Manufacturer = $systemInfo.Manufacturer
        $output.Model        = $systemInfo.Model
        $output.CPUCount     = $systemInfo.NumberOfProcessors
        $output.TotalRAM     = $systemInfo.TotalPhysicalMemory
    }

    $out = [pscustomobject]$output
    if ($PSBoundParameters.ContainsKey('OutputFilePath')) {
        $out | Export-Csv -Path $OutputFilePath -Append
    }
    $out
}
```

## Step 9: Adding Error Handling

Finally, let’s add error handling to make our script more robust:

```
[CmdletBinding()]
param(
    [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
    [string]$ComputerName,

    [Parameter()]
    [string]$OutputFilePath
)

begin {
    $ErrorActionPreference = 'Stop'
}

process {
    try {
        $output = @{
            ComputerName = $ComputerName
            IsOnline     = $null
            Manufacturer = $null
            Model        = $null
            CPUCount     = $null
            TotalRAM     = $null
            Error        = $null
        }

        $isOnline = Test-Connection -ComputerName $ComputerName -Count 1 -Quiet
        $output.IsOnline = $isOnline

        if ($isOnline) {
            $systemInfo = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $ComputerName
            $output.Manufacturer = $systemInfo.Manufacturer
            $output.Model        = $systemInfo.Model
            $output.CPUCount     = $systemInfo.NumberOfProcessors
            $output.TotalRAM     = $systemInfo.TotalPhysicalMemory
        }

        $out = [pscustomobject]$output
    }
    catch {
        $output.Error = $_.Exception.Message
        $out = [pscustomobject]$output
    }
    finally {
        if ($PSBoundParameters.ContainsKey('OutputFilePath')) {
            $out | Export-Csv -Path $OutputFilePath -Append
        }
        $out
    }
}
```

By following these steps, you have built a comprehensive tool for generating a computer inventory report using PowerShell. This tool can read from various sources, query system information, handle errors, and export the results to a CSV file. Happy scripting!

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-tools-csv-cim%2F&text=PowerShell%20Tool-Building%20101%3A%20Building%20a%20Computer%20Inventory%20Report)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-tools-csv-cim%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-tools-csv-cim%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/06/26995-troubleshoot-dns-issues-powershell-codex.webp)

### [Troubleshoot DNS Issues with PowerShell](/troubleshoot-dns-issues-powershell/)

Troubleshoot DNS issues with PowerShell by testing name resolution, DNS client settings, cache entries, and network connectivity in a repeatable workflow.

![](https://adamtheautomator.com/wp-content/uploads/2025/10/image_2025-10-24_095322075.png)

### [Migrating from PowerShell 6 to 7.5: Breaking Changes/New Features](/migrating-powershell-6-to-7-5/)

Migrate from PowerShell Core 6 to 7.5: breaking changes, features, and testing tips.

![](https://adamtheautomator.com/wp-content/uploads/2025/06/featured-image-6.png)

### [How to Add Timeouts to Pester Tests with PowerShell Runspaces](/pester-test-timeout-runspaces/)

Prevent Pester tests from hanging indefinitely using PowerShell runspaces. Learn to handle variable scoping, module loading, TestDrive access, and stream capture challenges with timeout protection.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
