← Back to list

SIF: A Clear Start and the Simplest Hello World

Seeing what really happens when SIF runs your Hello World

Sergey Solomentsev · 2025-10-28 02:04 · 0 claps · 7.7 min read
#sitecore #automation #powershell #software-design #installation
Open on Medium ↗

SIF: A Clear Start and the Simplest Hello World

Introduction

If you’ve ever tried to install or automate something in Sitecore, chances are you’ve met the Sitecore Installation Framework — or SIF. It’s the engine that powers Sitecore setup and configuration, handling dozens of steps behind a single PowerShell command.

For many developers, SIF feels like a black box — a mix of PowerShell scripts and mysterious JSON files full of Tasks, Parameters, and Modules. But what is it really? And how does it actually decide what to do?

In this article — the first in a small series where we’ll unpack SIF step by step — we’ll take a practical look at what’s going on under the hood. We’ll start with a minimal, working example — a Hello World configuration — to understand how SIF reads, interprets, and runs its instructions.

Once you see how it works at the simplest level, everything else in SIF becomes much easier to follow. And as we go deeper in the next parts, we’ll discover that SIF can automate far more than just installing Sitecore.

So let’s start simple — no installations, no complex setups — just one small JSON file that says: Hello world!

✅ Prerequisites

You’ll need:

  • PowerShell 5.1+
  • Sitecore Install Framework (SIF) 2.0 or later
  • Administrative privileges to run installation commands

💡 The Simplest Example — “Hello world!”

Here’s the smallest possible JSON configuration that SIF can understand:

{
  "Settings": {
    "AutoRegisterExtensions": true
  },
  "Tasks": {
    "Greet": {
      "Type": "WriteOutput",
      "Params": {
        "InputObject": "Hello world!"
      }
    }
  }
}

Let’s call it HelloWorld.json and run:

Install-SitecoreConfiguration -Path .\HelloWorld.json

You’ll see something like this:

************************************
                         Sitecore Install Framework
                               Version - 2.4.0
                    ************************************

Configuration          : C:\SIF\HelloWorld.json
WhatIf                 : False
WorkingDirectory       : C:\SIF
InformationAction      : Continue
Debug                  : SilentlyContinue
WarningAction          : Continue
ErrorAction            : Stop
AutoRegisterExtensions : True
Verbose                : SilentlyContinue

[----------------------------- Greet : WriteOutput -----------------------]
Hello world!
[TIME] 00:00:00

That’s it — you’ve just run your very first SIF configuration 🎉

It might look simple, but this tiny JSON already demonstrates how SIF thinks:

  • it registers all powershell commands as tasks automatically (thanks to AutoRegisterExtensions),
  • it runs a task called Greet (you can choose any name),
  • and that task uses the **WriteOutput** type — that literally runs PowerShell’s Write-Output -InputObject “Hello world!” under the hood.

🔍 What actually happens under the hood

So what really happens when you set "AutoRegisterExtensions": true?

When SIF starts, it first registers all available task types and functions before executing any tasks.

If you take a look at the module sources (you can find them in your PowerShell modules folder, usually under C:\Program Files\WindowsPowerShell\Modules\SitecoreInstallFramework\), you’ll see something like this in RegistrationHandler.ps1, around line 124:

Get-Command | ForEach-Object {
    $shortname = $_.Name -Replace '-', ''
    $taskTypes[$shortname] = @($_.Name)
}

That line literally scans all available PowerShell commands and registers them internally — so later, when your JSON says "Type": "WriteOutput", SIF already knows that it maps directly to the PowerShell command Write-Output.

This is why the tiny JSON created above works without any explicit imports — SIF auto-loads and maps everything for you on startup.

🧱 Hello World — the real SIF way

Let’s make our “Hello world” example a bit smarter. Instead of always printing Hello world!, let’s allow the user to pass a name — just like a parameter in a script.

Here’s the new JSON for your HelloWorld.json:

{
  "Settings": {
    "AutoRegisterExtensions": true
  },
  "Parameters": {
    "Name": {
      "Type": "string",
      "DefaultValue": "world"
    }
  },
  "Tasks": {
    "Say": {
      "Type": "WriteOutput",
      "Params": {
        "InputObject": "[concat('Hello ', parameter('Name'), '!')]"
      }
    }
  }
}

Now, if we run this command:

Install-SitecoreConfiguration -Path .\HelloWorld.json -Name "Developer"

We’ll get:

Hello Developer!

And if you don’t pass the -Name parameter, it will use the default value — "world" — so you’ll still see Hello world!.

🧠 What’s happening here

Let’s unpack what changed:

Parameters section

This is where you define inputs that your JSON can accept. Each parameter has a type and an optional default value. Think of it like function arguments in code — but for configuration.

"Parameters": {
  "Name": {
    "Type": "string",
    "DefaultValue": "world"
  }
}

That means: If the user doesn’t specify -Name, SIF will quietly use "world".

The parameter() function

When SIF executes the task, it automatically evaluates expressions wrapped in [ ... ]. Inside those brackets, you can call functions — like parameter() — to reference a value dynamically.

So this line:

"InputObject": "[parameter('Name')]"

…means: “Insert the value of the Name parameter here.”

The concat() function

You can also do basic string operations right in the JSON. This expression:

"[concat('Hello ', parameter('Name'), '!')]"

literally builds a string by combining three parts: 'Hello ' , the parameter value, '!'

Result: “Hello Developer!”

🔁 Variables and Reuse

As your configurations grow, you’ll quickly notice some patterns: you start repeating the same expressions again and again — concatenating paths, checking conditions, or building strings from parameters.

That’s where variables come in. They work like computed properties in C# or Vue — values that are calculated dynamically when you access them. Instead of writing the same logic inside every task, you define it once in a Variables section and reuse it anywhere in your configuration.

Let’s extend our “Hello World” example a bit and make it smarter. This time, we’ll greet the user differently depending on the time of day.

Here’s the new JSON for your HelloWorld.json:

{
  "Settings": {
    "AutoRegisterExtensions": true
  },
  "Parameters": {
    "Name": {
      "Type": "string",
      "DefaultValue": "world"
    },
    "Hour": {
      "Type": "int",
      "DefaultValue": "21"
    }
  },
  "Variables" : {
    "IsMorning": "[validaterange(0,11,parameter('Hour'))]",
    "Greeting": "[if(variable('IsMorning'),'Good morning','Good afternoon')]",
    "Phrase": "[concat(variable('Greeting'), ', ', parameter('Name'), '!')]"
  },
  "Tasks": {
    "Say": {
      "Type": "WriteOutput",
      "Params": {
        "InputObject": "[variable('Phrase')]"
      }
    }
  }
}

Run it with:

Install-SitecoreConfiguration -Path .\HelloVariable.json -Name "Alex" -Hour 5

You’ll see something like:

Good morning, Alex!

🧠 What’s happening here

  1. Parameters Two parameters are defined: Name — the name used in the greeting. Hour — a number representing the current hour (0–23).
  2. Variables This is where all the logic now lives: IsMorning — checks whether the hour falls within the range 0–11 using the validaterange() function. Greeting — uses an if() expression to choose between “Good morning” and “Good afternoon”. Phrase — concatenates the greeting and name into a final text string. By moving this logic to Variables, our Tasks section becomes much cleaner and reusable. If you ever need to change how the greeting is built, you only modify the variables — not the task itself.
  3. Tasks The Say task simply outputs the computed Phrase to the console.

Why Variables Matter

Variables allow you to encapsulate logic, avoid duplication, and make your configuration more expressive. Instead of hard-coding string operations or conditions in tasks, you can define them once in the Variables section and reuse them anywhere.

🧰 Exploring Built-in Tasks

We’ve already seen that SIF can run PowerShell commands like Write-Output. But SIF also comes with a collection of built-in tasks — ready-made operations designed to handle common setup and deployment actions such as file creation, copying, permissions, and configuration updates.

Example: Using Built-in Tasks

Let’s build a simple configuration that uses two of the built-in SIF tasks — EnsurePath and Copy — to create a folder and copy a file into it.

{
  "Tasks": {
    "CreateFolder": {
      "Type": "EnsurePath",
      "Params": {
        "Exists": "C:\\SIF\\Demo"
      }
    },
    "CopyFile": {
      "Type": "Copy",
      "Params": {
        "Source": "C:\\SIF\\HelloWorld.json",
        "Destination": "C:\\SIF\\Demo\\HelloWorld.json"
      }
    }
  }
}

Run it with:

Install-SitecoreConfiguration -Path .\BuiltInTasks.json

This configuration will ensure that the folder C:\SIF\Demo exists, and then copy the file HelloWorld.json into it. No need for PowerShell scripting — SIF does it all via its own task types.

🔍 What actually happens under the hood

Under the hood, EnsurePath and Copy tasks are just PowerShell functions with custom logic. SIF wraps them into a structured model, allowing it to orchestrate executions predictably, apply validation, handle logging, and manage step dependencies.

Let’s take a closer look at one of them. If you open the SIF module sources (located in your PowerShell modules folder), you’ll find the file:

~\Public\Tasks\Invoke-EnsurePathTask.ps1

Here’s its implementation — with a few comments added for clarity:

# SIF 2.4 function definition
# If you remove the ^Invoke- and Task$ parts, 
# you get the "Type" name for your task to call.
Function Invoke-EnsurePathTask {
    [CmdletBinding(SupportsShouldProcess=$true)]
    param(

        # Folders to be created or cleaned if they already exist
        [string[]]$Clean = @(),

        # Folders to be created without any actions if they exist
        [string[]]$Exists = @()
    )
    foreach($entry in $Clean)
    {
        # Writes informational message to the SIF output
        WriteTaskInfo -MessageData $entry -Tag 'Clean'

        # Cleans folder content if it exists
        if(Test-Path $entry) {
            Write-Verbose "Removing $entry"
            Get-ChildItem $entry | Remove-Item -Recurse

        # If folder doesn’t exist, it will be created in the next loop
        } else {
            $Exists += $entry
        }
    }
    foreach($entry in $Exists)
    {
        # Writes informational message about creating new folders
        WriteTaskInfo -MessageData $entry -Tag 'Create'

        if(-not(Test-Path $entry)) {
            Write-Verbose "Creating $entry"
            New-Item $entry -ItemType Directory | Out-Null
        }
    }
}

This is a good example of how SIF wraps standard PowerShell operations with additional logic and structured input. Each task function follows the same convention — it accepts typed parameters, performs an action, and integrates with the SIF pipeline via helper methods like WriteTaskInfo

Now suppose we have the following JSON:

{
  "Tasks": {
    "UseEnsurePath": {
      "Type": "EnsurePath",
      "Params": {
        "Exists": ["C:\\SIF\\Examples","C:\\SIF\\articles"],
        "Clean": "C:\\SIF\\Demo"
      }
    }
  }
}

And we run it like this:

Install-SitecoreConfiguration -Path .\UseEnsurePath.json

Behind the scenes, the Install-SitecoreConfiguration function locates and calls the corresponding PowerShell function — in this case, Invoke-EnsurePathTask.

To explore all available built-in tasks on your system, run:

Get-SitecoreInstallExtension -Type Task

This will list every task available in your version of the Sitecore Install Framework.

💡 Tip: Open any Invoke-*Task.ps1 file inside the SIF module to see how it’s implemented — it’s the easiest way to learn how to write your own custom task types later.

What’s next

Now you’ve seen how SIF tasks work under the hood — each of them is just a PowerShell function wrapped with structured logic and conventions that make the whole system predictable, composable, and reusable.

In the next part, we’ll go one step further — and create our own custom task. You’ll see how to register it manually and control parameters.

Your move

Open your PowerShell, run Get-SitecoreInstallExtension -Type Task, and take a look at what’s already available in your environment. Pick any task you find interesting — maybe EnsurePath or Copy — and try to build a small JSON example with it.

Experiment, tweak it, and see how SIF reacts. Then come back and tell what you discovered — or share your favorite trick in the comments.


메타데이터
post_id
60291374901d
slug
sif-a-clear-start-and-the-simplest-hello-world-60291374901d
url
https://medium.com/@serg-at/sif-a-clear-start-and-the-simplest-hello-world-60291374901d
canonical_url
https://medium.com/@serg-at/sif-a-clear-start-and-the-simplest-hello-world-60291374901d
author_url
https://medium.com/@serg-at
status
ok
fetched_at
2026-06-15 20:49:54