This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Usage Examples

Here you can find practical examples of how to use the module in real-world scenarios. These examples are designed to help you understand how to apply the module’s functionality.

These are examples with a little more depth and context. If you want to just the usage of the commands from the module, check out the command reference.

1 - Practical usage in a Domain Environment (GPO-driven collection and conversion)

This example demonstrates how to implement a GPO-driven workflow for collecting and converting DNS debug logs on domain controllers.

This document outlines a practical, end-to-end example of running DNSServer.DebugLogParser in an Active Directory domain environment, focused on converting Windows DNS Server debug logs on domain controllers.

This example is accompanied by a ZIP archive, which provide the policy artifacts used to implement the workflow described here.
The most relevant artifacts are backup manifest, GPO report, Files.xml, Set-DNSServerDebugLogging.ps1, and ScheduledTasks.xml.

Scenario

  • Multiple domain controllers (DCs) host the DNS Server role.
  • DNS debug logging is enabled and configured consistently on each DC via a scheduled task (writing log files to C:\Administration\Logs\DNSServer).
  • A centrally managed process converts logs into CSV for:
    • security analytics
    • operational reporting
    • troubleshooting
    • compliance/retention

Target outcomes

  • Consistent conversion settings across all DCs
  • Predictable output location and naming
  • Optional compression to reduce storage footprint
  • Optional statistics outputs for quick daily rollups
  • Minimal host-side risk, with explicit rerun and cleanup considerations

Suggested architecture

Collection model: local convert + central pull

  1. Each DC writes DNS debug logs to disk with rollover enabled.
  2. Each DC converts rotated *.log files into a data CSV and statistics CSVs, then compresses the outputs into *.zip on a schedule (Task Scheduler).
  3. Outputs are written next to the log files so the pipeline stays simple.
  4. A central server collects the *.zip outputs, for example via file share ingestion, scheduled copy, SIEM forwarder, or an agent-based collector.

This model minimizes network reads of large raw log files and keeps parsing close to the data.

GPO workflow

The workflow is implemented through Group Policy (computer configuration) to ensure consistent settings across all domain controllers.

Reference implementation included in this repository (GPO report):

  • Archive/report name: T0-C-Analytics-DNSDebugLogging
  • Backup ID: {2B6F16BC-0E7C-4787-83D7-2854FED882EE}
  • GPO link target: corp.company.com/Domain Controllers
  • Item filter (used for both file deployment and scheduled tasks): only applies if C:\Windows\System32\dns.exe exists

1) Prerequisites (folders + module)

The provided backup assumes these folders already exist. Add separate GPP items if you want the deployment to create them automatically:

  • C:\Administration\Scripts
  • C:\Administration\Logs\DNSServer

The provided backup also assumes Convert-DNSDebugLogFile is already available on the DCs. The conversion task starts Windows PowerShell 5.1 with -NoProfile and does not import the module explicitly, so the module must be installed in a machine-wide Windows PowerShell module path that is visible to LocalSystem. Recommended approaches:

  • Install DNSServer.DebugLogParser on the DCs. For example, from PowerShell Gallery (if policy allows).
  • Deploy the module via internal repo / file share so it is discoverable in $env:PSModulePath
  • Add an explicit Import-Module to the task action if you want deterministic loading behavior

2) Deploy the debug logging configuration script (GPP Files)

The GPO deploys the script:

  • Source (in SYSVOL via GPP): %GptPath%\Preferences\Files\Set-DNSServerDebugLogging.ps1
  • Target (on each DC): C:\Administration\Scripts\Set-DNSServerDebugLogging.ps1

This is implemented in the GPP Files preference item in Files.xml.

3) Scheduled task: configure DNS debug logging

The GPO creates a scheduled task named Set-DNSServerDebugLogging.

  • Security context in the supplied backup: SYSTEM with logon type S4U
  • Trigger in the supplied backup: daily (start boundary 2025-03-01T00:00:01)
  • Action in ScheduledTasks.xml:
    • powershell.exe -ExecutionPolicy RemoteSigned -command " & { C:\Administration\Scripts\Set-DNSServerDebugLogging.ps1 }"
    • Working directory: C:\Administration\Scripts

The linked Set-DNSServerDebugLogging.ps1 script configures DNS debug logging via Get-DnsServerDiagnostics / Set-DnsServerDiagnostics and (notably):

  • Enables logging to file + rollover
  • Writes to: C:\Administration\Logs\DNSServer\DnsDebugLog_<COMPUTERNAME>.<Domain>_.log
  • Uses a 10 MB rollover size per file
  • Captures primarily query-related activity (queries + notifications + updates + question transactions) and excludes full packet logging

4) Scheduled task: convert rotated debug logs to compressed CSV

The GPO creates a scheduled task named Convert-DNSDebugLogs.

  • Security context in the supplied backup: SYSTEM with logon type InteractiveToken
  • Trigger in the supplied backup: daily (start boundary 2026-01-01T00:30:00)
  • Working directory: C:\Administration\Logs\DNSServer
  • Action in ScheduledTasks.xml (formatted for readability):
Get-ChildItem .\*.log |
  Sort-Object lastwritetime, Name -Descending |
  Select-Object -Skip 1 |
  Convert-DNSDebugLogFile `
    -ComputerName $env:COMPUTERNAME `
    -Delimiter ';' `
    -OutputType Both `
    -ContextFilter Packet `
    -OutputCulture sv-SE `
    -CompressOutput

Design notes:

  • Select-Object -Skip 1 intentionally avoids processing the newest (active) log file.
  • That means current data is exported only after rollover; on low-volume DCs, the active log may stay unprocessed for more than a day.
  • Because Convert-DNSDebugLogFile defaults -OutputFile to “same folder, same name, .csv”, outputs land next to the *.log inputs.
  • With -CompressOutput, each processed log produces a *.zip and the intermediate CSVs are removed.
  • Unless you archive or delete processed *.log files, later runs will reprocess every non-active log again.
  • The task throws if $Error.Count -gt 0 to signal a failed run.

5) Central ingestion

Options (pick one):

  • File share ingestion: DC writes (or copies) C:\Administration\Logs\DNSServer\*.zip to \\fileserver\share\dns\$env:COMPUTERNAME\... (grant share and NTFS rights to the DC computer accounts or the Domain Controllers group if the task runs as SYSTEM)
  • Pull model: central job reads \\dc\C$\Administration\Logs\DNSServer\*.zip (least preferred; requires admin shares)
  • Agent forwarder: SIEM / log pipeline that ships the *.zip outputs

Operational considerations

  • Least privilege: tasks run as SYSTEM; ensure the local folders are writable and that any UNC targets grant access to the computer account if used.
  • Signing policy: both tasks use -ExecutionPolicy RemoteSigned; sign or unblock the deployed script and module according to your policy.
  • Disk usage: -CompressOutput helps significantly, but this workflow does not remove source logs; plan retention and cleanup.
  • Re-processing behavior: unless you archive or delete processed logs, the conversion task will process every non-active *.log file again on later runs. This is simple and robust, but it can overwrite outputs and create duplicate downstream ingestion if your collector does not deduplicate.
  • Multi-DC consolidation: -ComputerName $env:COMPUTERNAME is included so consolidated datasets remain traceable.
  • Validation: header validation remains enabled because the task does not use -SkipHeaderValidation (recommended).

Validate and adapt (using the ZIP)

Use the ZIP archive as the reference implementation, then align the following aspects to your environment:

  • Target scope: which DCs / OUs receive the policy
  • Execution identity: confirm both scheduled tasks use the intended logon type (S4U vs InteractiveToken) or normalize them to your standard
  • Folder creation: decide whether C:\Administration\Scripts and C:\Administration\Logs\DNSServer are pre-staged elsewhere or should be created by additional GPP items
  • Paths: confirm C:\Administration\Scripts and C:\Administration\Logs\DNSServer match your standards
  • Retention: decide whether to keep raw logs and for how long (especially if enabling cleanup options)
  • Ingestion: confirm where CSV/ZIP outputs are written and how they are collected centrally

If you want to validate the exact GPO configuration without importing it, the authoritative sources in this repo are:

2 - Scheduled Task Example

This example demonstrates how to create a Windows Scheduled Task that runs a PowerShell script to process DNS debug logs daily.

This script creates a Windows Scheduled Task that runs daily at 2:00 AM. It imports the module and processes all the log file in the folder where the script is executed (in this example “C:\Administration\Logs\DNS”). The process does compress the output into ZIP-files and removes the original to maintain hygiene.

$actionParams = @{
    Execute = "powershell.exe"
    Argument = '-ExecutionPolicy RemoteSigned -Command "Import-Module DNSServer.DebugLogParser; Get-ChildItem .\*.log | Sort-Object lastwritetime, Name -Descending | Convert-DNSDebugLogFile -ComputerName $env:COMPUTERNAME -Delimiter \";\" -OutputType Both -ContextFilter Packet -OutputCulture sv-SE -CompressOutput"'
    WorkingDirectory = "C:\Administration\Logs\DNS"
}
$Action = New-ScheduledTaskAction @actionParams

$Trigger = New-ScheduledTaskTrigger -Daily -At "2:00AM"

Register-ScheduledTask -TaskName "Process DNS Logs" -Action $Action -Trigger $Trigger -Description "Convert DNS debug logs to CSV daily"

3 - Security Analysis Workflow with SQL Server

Convert DNS debug logs to CSV with DNSServer.DebugLogParser, import the result into SQL Server, and run a simple detection query for suspicious TXT record activity.

This example shows a practical workflow for security analytics: parse a DNS debug log with Convert-DNSDebugLogFile, import the generated CSV into SQL Server, and run a query that highlights unusually high volumes of TXT record lookups.

For best interoperability, this example writes timestamps in an ISO-like format by using -OutputCulture 'sv-SE'.

Required modules

This example uses the following PowerShell modules:

  • DNSServer.DebugLogParser
  • SqlServer

Install them if needed:

Install-Module -Name DNSServer.DebugLogParser -Scope CurrentUser
Install-Module -Name SqlServer -Scope CurrentUser

Scenario

Use this workflow when you want to move parsed DNS debug log data into SQL Server so you can:

  • search large datasets efficiently
  • build repeatable detection queries
  • correlate activity across multiple DNS servers
  • retain normalized data for later investigation

Output of the conversion step

Convert-DNSDebugLogFile does not write directly to SQL Server. It first creates a CSV file. That CSV file is the dataset imported into the database.

In this example:

  • input log: C:\Administration\Logs\DNS\dns.log
  • generated CSV: C:\Administration\Logs\DNS\dns.csv
  • destination table: dbo.DNSQueries

Create the target table

Run the following statement once in SQL Server to create the target table.

IF OBJECT_ID('dbo.DNSQueries', 'U') IS NULL
BEGIN
    CREATE TABLE dbo.DNSQueries (
        DateTime      datetime2(0)   NOT NULL,
        ThreadId      int            NULL,
        Context       nvarchar(20)   NULL,
        PacketId      int            NULL,
        Protocol      nvarchar(10)   NULL,
        Direction     nvarchar(10)   NULL,
        ClientIP      nvarchar(64)   NULL,
        Xid           nvarchar(16)   NULL,
        Type          nvarchar(16)   NULL,
        Opcode        nvarchar(16)   NULL,
        FlagsHex      nvarchar(16)   NULL,
        FlagsChar     nvarchar(16)   NULL,
        ResponseCode  nvarchar(32)   NULL,
        QuestionType  nvarchar(32)   NULL,
        QuestionName  nvarchar(512)  NULL,
        Information   nvarchar(max)  NULL,
        Details       nvarchar(max)  NULL,
        ComputerName  nvarchar(256)  NULL
    );
END;

Convert the log and import the CSV

The following PowerShell example performs the full workflow:

  1. imports the required modules
  2. converts the DNS debug log to CSV
  3. loads the generated CSV
  4. bulk imports the rows into SQL Server
# Requires -Modules DNSServer.DebugLogParser, SqlServer

Import-Module -Name DNSServer.DebugLogParser -ErrorAction Stop
Import-Module -Name SqlServer -ErrorAction Stop

$logPath = 'C:\Administration\Logs\DNS\dns.log'
$csvPath = 'C:\Administration\Logs\DNS\dns.csv'
$serverInstance = 'SQLServer'
$databaseName = 'DNSLogs'
$delimiter = ';'

$createTableSql = @'
IF OBJECT_ID('dbo.DNSQueries', 'U') IS NULL
BEGIN
    CREATE TABLE dbo.DNSQueries (
        DateTime      datetime2(0)   NOT NULL,
        ThreadId      int            NULL,
        Context       nvarchar(20)   NULL,
        PacketId      int            NULL,
        Protocol      nvarchar(10)   NULL,
        Direction     nvarchar(10)   NULL,
        ClientIP      nvarchar(64)   NULL,
        Xid           nvarchar(16)   NULL,
        Type          nvarchar(16)   NULL,
        Opcode        nvarchar(16)   NULL,
        FlagsHex      nvarchar(16)   NULL,
        FlagsChar     nvarchar(16)   NULL,
        ResponseCode  nvarchar(32)   NULL,
        QuestionType  nvarchar(32)   NULL,
        QuestionName  nvarchar(512)  NULL,
        Information   nvarchar(max)  NULL,
        Details       nvarchar(max)  NULL,
        ComputerName  nvarchar(256)  NULL
    );
END
'@

Convert-DNSDebugLogFile `
    -InputFile $logPath `
    -ComputerName 'DNS01' `
    -OutputType CSV `
    -OutputFile $csvPath `
    -Delimiter $delimiter `
    -OutputCulture 'sv-SE'

$rows = Import-Csv -Path $csvPath -Delimiter $delimiter

if (-not $rows) {
    throw "The generated CSV file '$csvPath' does not contain any rows."
}

$dataTable = [System.Data.DataTable]::new()
foreach ($columnName in $rows[0].PSObject.Properties.Name) {
    $null = $dataTable.Columns.Add($columnName, [string])
}

foreach ($row in $rows) {
    $dataRow = $dataTable.NewRow()
    foreach ($column in $dataTable.Columns) {
        $columnName = $column.ColumnName
        $dataRow[$columnName] = $row.$columnName
    }

    $null = $dataTable.Rows.Add($dataRow)
}

$connectionString = "Server=$serverInstance;Database=$databaseName;Integrated Security=True"
$connection = [System.Data.SqlClient.SqlConnection]::new($connectionString)

try {
    $connection.Open()

    $command = $connection.CreateCommand()
    $command.CommandText = $createTableSql
    $null = $command.ExecuteNonQuery()

    $bulkCopy = [System.Data.SqlClient.SqlBulkCopy]::new($connection)
    $bulkCopy.DestinationTableName = 'dbo.DNSQueries'

    foreach ($column in $dataTable.Columns) {
        $null = $bulkCopy.ColumnMappings.Add($column.ColumnName, $column.ColumnName)
    }

    $bulkCopy.WriteToServer($dataTable)
}
finally {
    $connection.Dispose()
}

Query for suspicious TXT record activity

Once the data is in SQL Server, you can search for clients that issue unusually high numbers of TXT record queries.

SELECT
    ComputerName,
    ClientIP,
    QuestionName,
    COUNT(*) AS QueryCount
FROM dbo.DNSQueries
WHERE QuestionType = 'TXT'
GROUP BY
    ComputerName,
    ClientIP,
    QuestionName
HAVING COUNT(*) > 100
ORDER BY QueryCount DESC;

If you prefer to run the query from PowerShell, use Invoke-Sqlcmd from the SqlServer module:

$query = @'
SELECT
    ComputerName,
    ClientIP,
    QuestionName,
    COUNT(*) AS QueryCount
FROM dbo.DNSQueries
WHERE QuestionType = 'TXT'
GROUP BY
    ComputerName,
    ClientIP,
    QuestionName
HAVING COUNT(*) > 100
ORDER BY QueryCount DESC;
'@

Invoke-Sqlcmd `
    -ServerInstance 'SQLServer' `
    -Database 'DNSLogs' `
    -Query $query

Why TXT queries are interesting

High volumes of TXT record lookups can be worth reviewing because they may indicate:

  • DNS tunneling
  • data exfiltration over DNS
  • abuse of TXT records by malware or tooling
  • unusually noisy or misconfigured clients

This query is only a starting point. In production, you should tune the threshold and add filters that match your environment.

Operational notes

  • Import-Csv reads the full file into memory. For very large log exports, consider a streaming approach instead of building a full DataTable.
  • Keep -ComputerName in the conversion step so records remain attributable after central ingestion.
  • Use a consistent delimiter and culture during export and import.
  • Validate retention, indexing, and access control in SQL Server before using this workflow for long-term storage.