| [ Web Proxy ] |
| Viewing: https://docs.psscriptbuilder.com/cmdlets/../../tutorials/building-your-first-project/ | [Back] [Original] |
This tutorial walks you through building a complete PSScriptBuilder project from scratch. You
will create the source files, configure PSScriptBuilder, write a template and a build script,
and run your first build. By the end, you have a single deployable .ps1 generated from
multiple source files with all dependencies automatically resolved.
If you already have an existing project and want to adopt PSScriptBuilder, see Migrating to PSScriptBuilder instead.
Prerequisites: PSScriptBuilder installed see Installation.
A small HR project with two enums, three classes, and one function enough to demonstrate dependency resolution and multi-collector builds. The final project structure looks like this:
HRTools/
psscriptbuilder.config.json
Build-HRTools.ps1
src/
Enums/
Department.ps1
EmploymentStatus.ps1
Classes/
Address.ps1
Person.ps1
Employee.ps1
Public/
New-Employee.ps1
build/
Templates/
HRTools.ps1.template
Output/
Create the project folder and all subdirectories:
New-Item -ItemType Directory -Path "HRTools\src\Enums",
"HRTools\src\Classes",
"HRTools\src\Public",
"HRTools\build\Templates",
"HRTools\build\Output"
Set-Location HRTools
Each source file contains exactly one component. PSScriptBuilder discovers the files automatically file names do not need to match class or enum names, but it is good practice.
class Address {
[string] $Street
[string] $City
[string] $PostalCode
[string] $Country
Address([string] $street, [string] $city, [string] $postalCode, [string] $country) {
$this.Street = $street
$this.City = $city
$this.PostalCode = $postalCode
$this.Country = $country
}
}
class Person {
[string] $FirstName
[string] $LastName
Person([string] $firstName, [string] $lastName) {
$this.FirstName = $firstName
$this.LastName = $lastName
}
}
Employee inherits from Person and references Address, Department, and EmploymentStatus.
PSScriptBuilder detects these dependencies automatically and ensures that all prerequisites appear
before Employee in the output regardless of the order files are on disk.
class Employee : Person {
[Address] $Address
[Department] $Department
[EmploymentStatus] $Status
[DateTime] $HireDate
[decimal] $Salary
Employee(
[string] $firstName,
[string] $lastName,
[Address] $address,
[Department] $department,
[DateTime] $hireDate,
[decimal] $salary
) : base($firstName, $lastName) {
$this.Address = $address
$this.Department = $department
$this.Status = [EmploymentStatus]::Active
$this.HireDate = $hireDate
$this.Salary = $salary
}
}
Function New-Employee {
[CmdletBinding()]
[OutputType([Employee])]
param(
[Parameter(Mandatory)]
[string] $FirstName,
[Parameter(Mandatory)]
[string] $LastName,
[Parameter(Mandatory)]
[Address] $Address,
[Parameter(Mandatory)]
[Department] $Department,
[Parameter(Mandatory)]
[DateTime] $HireDate,
[Parameter(Mandatory)]
[decimal] $Salary
)
return [Employee]::new($FirstName, $LastName, $Address, $Department, $HireDate, $Salary)
}
Run the following cmdlet from the project root to generate psscriptbuilder.config.json:
The generated file contains all required fields pre-filled with sensible defaults. The two
fields you will use most are build.templatePath and build.outputPath both already point
to the build\Templates and build\Output directories you created in step 1.
For a full explanation of all fields, see the Configuration Guide.
The template defines the structure of the generated output file. Each {{Token}} placeholder
is replaced with the collected and dependency-ordered source code of the corresponding collector.
Create build/Templates/HRTools.ps1.template:
{{ENUM_DEFINITIONS}}
{{CLASS_DEFINITIONS}}
{{FUNCTION_DEFINITIONS}}
The placeholders map to the collectors you will configure in the next step:
| Placeholder | Collector type |
|---|---|
{{ENUM_DEFINITIONS}} |
Enum |
{{CLASS_DEFINITIONS}} |
Class |
{{FUNCTION_DEFINITIONS}} |
Function |
For a full explanation of placeholder syntax and the three validation modes, see the Templates Guide.
Create Build-HRTools.ps1 at the project root. The build script sets the project root,
configures the collectors, and invokes the build:
using module PSScriptBuilder
Set-PSScriptBuilderProjectRoot -Path $PSScriptRoot
$config = Get-PSScriptBuilderConfiguration
$contentCollector = New-PSScriptBuilderContentCollector |
Add-PSScriptBuilderCollector -Type Enum -IncludePath 'src\Enums' |
Add-PSScriptBuilderCollector -Type Class -IncludePath 'src\Classes' |
Add-PSScriptBuilderCollector -Type Function -IncludePath 'src\Public'
$buildParams = @{
ContentCollector = $contentCollector
TemplatePath = Join-Path $config.Build.TemplatePath 'HRTools.ps1.template'
OutputPath = Join-Path $config.Build.OutputPath 'HRTools.ps1'
}
Invoke-PSScriptBuilderBuild @buildParams | Format-PSScriptBuilderBuildResult
Set-PSScriptBuilderProjectRoot tells PSScriptBuilder where to resolve relative paths from.
$PSScriptRoot is the directory of the currently running script always the correct value
when calling this from a build script.
Get-PSScriptBuilderConfiguration reads psscriptbuilder.config.json and returns a typed
object. Using $config.Build.TemplatePath and $config.Build.OutputPath means you only
need to update the config file if the directories change not the build script.
From the project root:
Expected output:
Build Summary
Output : ...\build\Output\HRTools.ps1
Size : 2.14 KB
Time : 312.45 ms
Components
Enums : 2
Classes : 3
Functions : 1
Total : 6
The generated build/Output/HRTools.ps1 contains all components in the correct load order:
enums first, then classes in dependency order (Address and Person before Employee), then
functions. You did not specify any ordering PSScriptBuilder resolved it automatically from
the AST.
| Web Proxy Viewer | New URL | Original Page |