Belajar PowerShell - Functions & Script Blocks
Episode 7 of 31

Belajar PowerShell - Functions & Script Blocks

Mengorganisasi kode menjadi fungsi yang dapat dipakai ulang: deklarasi dengan pola Verb-Noun, parameter dengan validasi dan nilai default, advanced function dengan CmdletBinding dan pipeline input, script blocks, cakupan scope, serta praktik terbaik untuk fungsi yang siap dipakai di skrip nyata.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Di episode 6 kalian mengulang proses dengan loop — tapi bagaimana kalau proses itu dibutuhkan di banyak tempat? Menyalin blok kode ke mana-mana adalah resep bencana: satu perbaikan harus diulang di puluhan tempat. Episode 7 menjawabnya dengan functions & script blocks: mengemas logika ke unit bernama yang bisa dipanggil, diberi parameter, dan dipakai ulang.

Bayangkan resep dapur yang ditulis di kartu index. Setiap kali kalian butuh nasi goreng, kalian tidak menulis ulang seluruh resep — kalian mengambil kartunya dan mengikutinya. Fungsi adalah kartu index itu: nama yang memanggil prosedur lengkap.

Mendeklarasikan Fungsi

Deklarasi fungsi dimulai dengan kata kunci function, diikuti nama dan blok kode. Nama mengikuti pola Verb-Noun — kata kerja lalu objek — sehingga penamaannya konsisten seperti cmdlet bawaan.

Deklarasi fungsi dasar
function Get-UptimeRingkas {
    $up = (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
    Write-Output "$($up.Days) hari $($up.Hours) jam"
}

Verb yang disarankan tersedia di daftar verba yang disetujui — cek dengan Get-Verb. New-, Get-, Set-, Remove-, Test-, Invoke-, dan Convert- adalah contoh umum. Verb di luar daftar sah secara sintaks, tapi membuat fungsi kalian tidak terdeteksi sebagai perintah "resmi" oleh tooling.

Memanggil Fungsi dan Nilai Kembalian

Memanggil fungsi sama seperti memanggil cmdlet — cukup nama dan argumen:

Memanggil fungsi
Get-UptimeRingkas

Setiap output yang dihasilkan fungsi menjadi nilai kembaliannya. Penting: semua yang ditulis ke pipeline output menjadi bagian dari hasil — Write-Output eksplisit maupun sekadar expression yang dievaluasi. Write-Host berbeda: ia menulis ke aliran informasi untuk ditampilkan, bukan dikembalikan.

Nilai kembali
function Get-LuasLingkaran {
    param($JariJari)
    [math]::PI * $JariJari * $JariJari
}
$luas = Get-LuasLingkaran -JariJari 7
Write-Host "Luas: $luas"

Parameter: Posisional, Named, Default, Mandatory, Validasi

Blok param di awal fungsi mendeklarasikan parameter. Ada beberapa jenis:

  • Named — dipanggil dengan -Nama. Positional — diisi berdasarkan urutan jika dideklarasikan tanpa atribut khusus.
  • Default — nilai yang dipakai bila pemanggil tidak memberikannya.
  • Mandatory — wajib diisi; PowerShell meminta input bila tidak diberikan.
  • Validasi — atribut yang membatasi nilai: rentang, set, pola, atau tipe.
Parameter dengan validasi
function New-UserEntry {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory, Position = 0)]
        [ValidatePattern("^[a-z0-9_-]+$")]
        [string]$Username,
 
        [ValidateRange(1, 65535)]
        [int]$Port = 8080,
 
        [ValidateSet("aktif", "nonaktif")]
        [string]$Status = "aktif"
    )
    Write-Output "Membuat $Username di port $Port status $Status"
}

Semua konstruksi atribut parameter di atas ditulis di dalam blok kode. Di luar kode, cukup ingat tiga properti parameter yang paling sering dipakai: Mandatory untuk kewajiban, nilai default untuk keringkasan, dan atribut Validate untuk pertahanan input sejak pintu masuk.

Tip

Validasi di parameter adalah tembok pertahanan pertama. ValidateRange memastikan angka masuk akal, ValidateSet memastikan pilihan salah satu dari daftar, dan ValidatePattern memastikan string memenuhi pola. Lebih baik menolak input buruk di awal daripada menanganinya di tengah logika.

Advanced Function: CmdletBinding

Menambahkan atribut [CmdletBinding()] mengubah fungsi biasa menjadi advanced function — fungsi yang berperilaku seperti cmdlet asli:

Advanced function
[CmdletBinding()]
function Test-KoneksiServer {
    param([string]$Hostname)
    $ok = Test-NetConnection -ComputerName $Hostname -Port 443 -InformationLevel Quiet
    Write-Output $ok
}

Keuntungannya langsung terasa: fungsi kini mendukung parameter umum -Verbose, -Debug, -ErrorAction, -Confirm, dan -WhatIf. Perilaku itu didapat tanpa menulis satu baris pun — atribut yang menyatakannya.

SupportsShouldProcess

Untuk fungsi yang mengubah keadaan, nyatakan dukungan konfirmasi dan simulasi:

SupportsShouldProcess
[CmdletBinding(SupportsShouldProcess)]
function Remove-DataDir {
    param([string]$Path)
    if ($PSCmdlet.ShouldProcess($Path, "Hapus folder")) {
        Remove-Item $Path -Recurse -Force
    }
}

Dengan deklarasi ini, pemanggil bisa menjalankan Remove-DataDir -WhatIf untuk simulasi tanpa menjalankan — garis penyelamat di lingkungan produksi. ShouldProcess mengembalikan benar bila aksi diizinkan berjalan, dan salah bila diminta simulasi.

Parameter Set

Beberapa fungsi menerima masukan yang saling eksklusif — misalnya menerima path file atau objek file, bukan keduanya sekaligus. Parameter set membaginya menjadi kelompok:

Parameter set
function Get-FileSummary {
    [CmdletBinding(DefaultParameterSetName = "ByPath")]
    param(
        [Parameter(ParameterSetName = "ByPath", Mandatory)]
        [string]$Path,
 
        [Parameter(ParameterSetName = "ByItem", Mandatory, ValueFromPipeline)]
        [System.IO.FileInfo]$Item
    )
    if ($PSCmdlet.ParameterSetName -eq "ByPath") {
        $Item = Get-Item $Path
    }
    Write-Output "Ukuran $($Item.Name): $($Item.Length)"
}

Setiap parameter milik satu set (ParameterSetName). Pemanggil harus memilih salah satu set — kombinasi antar set akan ditolak dengan pesan yang menjelaskan set mana yang tersedia.

Pipeline Input

Fungsi bisa menerima objek dari pipeline, bukan hanya argumen langsung. Ada dua deklarasi utama:

  • ValueFromPipeline — menerima objek itu sendiri dari pipeline.
  • ValueFromPipelineByPropertyName — menerima objek yang propertinya cocok dengan nama parameter.
Pipeline input
function Get-ProcessInfo {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [string]$Name
    )
    process {
        $p = Get-Process -Name $Name -ErrorAction SilentlyContinue
        if ($p) {
            Write-Output "$Name menggunakan $([math]::Round($p.WS / 1MB, 1)) MB"
        }
    }
}
 
Get-Process pwsh | Get-ProcessInfo
Get-Process -Name pwsh | Select-Object Name | Get-ProcessInfo

Baris pertama mengirim objek Process — parameter $Name mengambil properti Name lewat ValueFromPipelineByPropertyName. Baris kedua menegaskan hal yang sama dari pipeline eksplisit. Keduanya memicu blok process untuk setiap item.

Script Blocks dan Invoke-Command

Script block adalah sekumpulan kode yang disimpan sebagai nilai — diperlakukan seperti data yang bisa dipindahkan dan dijalankan. Salah satu penggunaannya: dikirim ke komputer lain lewat Invoke-Command untuk dijalankan di sana.

Script block lewat Invoke-Command
$block = { Get-Process -Name pwsh }
Invoke-Command -ComputerName server-web -ScriptBlock $block

Script block juga menjadi dasar parameter seperti -ScriptBlock pada ForEach-Object yang kalian pakai di episode 6. Konsepnya sama: kode sebagai nilai, dijalankan nanti atau di tempat lain.

Scope: Local, Script, Global, Private

Setiap variabel lahir di scope tertentu — wilayah visibilitasnya. Scope berfungsi seperti ruangan di rumah: variabel di ruang tamu terlihat dari ruang kerja, tapi tidak sebaliknya.

ScopeJangkauan
LocalBerisi variabel di dalam blok atau fungsi saat ini
ScriptSeluruh file script yang sedang berjalan
GlobalSeluruh sesi PowerShell
PrivateHanya di scope tempat ia dideklarasikan

Fungsi melihat variabel dari scope induknya, tetapi menetapkan variabel di dalam fungsi membuat variabel lokal baru — tidak mengubah yang di luar. Untuk mengubah nilai scope luar secara eksplisit, gunakan prefiks cakupan:

Menulis ke scope lain
$script:hitung = 0
 
function Get-Naikkan {
    $script:hitung++
}
 
Get-Naikkan
Get-Naikkan
Write-Host "Nilai di scope script: $script:hitung"

Tanpa prefiks $script:, fungsi akan membuat $hitung lokal yang hilang saat fungsi selesai — bug klasik yang membingungkan pemula. Aturan praktis: hindari ketergantungan pada variabel global; beri parameter dan terima hasil kembalian.

Best Practices Fungsi

Prinsip yang menjaga fungsi tetap sehat:

  • Single responsibility — satu fungsi mengerjakan satu hal. Nama mengungkapkannya: Get-DiskUsage tidak sekaligus mengirim email.
  • Verb-Noun konsisten — pakai verb yang disetujui agar fungsi kalian terintegrasi dengan tooling.
  • Comment-based help — dokumentasikan fungsi dengan blok komentar berisi SYNOPSIS, DESCRIPTION, PARAMETER, dan EXAMPLE agar Get-Help bekerja.
  • Parameter, bukan variabel global — fungsi yang bergantung pada variabel luar sulit diuji dan dipakai ulang.
  • Error handling — dalam fungsi, gunakan throw untuk kegagalan yang harus menghentikan, dan Write-Error untuk yang bisa dilewati, sesuai materi episode 12.
Comment-based help
function Get-HealthCheck {
    <#
    .SYNOPSIS
    Memeriksa ketersediaan server.
    .PARAMETER Hostname
    Nama atau alamat server.
    .EXAMPLE
    Get-HealthCheck -Hostname web-01
    #>
    param([string]$Hostname)
    Test-NetConnection -ComputerName $Hostname -Port 443 -InformationLevel Quiet
}

Setelah definisi di atas, pemanggil bisa menulis Get-Help Get-HealthCheck dan melihat dokumentasi lengkap — dokumentasi yang menyatu dengan kode.

Penutup

Episode 7 mengubah skrip kalian dari daftar instruksi menjadi kumpulan unit yang bisa dipakai ulang: deklarasi fungsi dengan pola Verb-Noun, nilai kembalian lewat pipeline output, parameter dengan default, mandatory, dan validasi, advanced function dengan CmdletBinding dan dukungan -WhatIf, parameter set untuk input yang saling eksklusif, pipeline input dengan ValueFromPipeline, script block sebagai kode yang bisa dikirim dan dijalankan, scope yang mengatur visibilitas variabel, serta praktik terbaik termasuk comment-based help.

Poin kunci yang dibawa pulang:

  • Nama fungsi mengikuti Verb-Noun; satu fungsi satu tanggung jawab.
  • Semua output fungsi menjadi nilai kembalian; gunakan Write-Host hanya untuk menampilkan.
  • CmdletBinding memberi perilaku cmdlet penuh — termasuk -WhatIf.
  • Parameter set mencegah kombinasi input yang bertentangan.
  • Scope menjaga variabel tetap terlokalisasi; jangan bergantung pada variabel global.
  • Comment-based help menjadikan fungsi terdokumentasi sendiri.

Di episode 8 kita membedah jantung PowerShell: pipeline & object manipulation — bagaimana objek mengalir antargaris, disaring dengan Where-Object, dipilih propertinya dengan Select-Object, diurutkan, dikelompokkan, dan diproses paralel. Sampai jumpa di episode 8!

Belajar PowerShell - Functions & Script Blocks | Belajar PowerShell