---
title: Batch log and status message writing
summary: Writes status, error, and named-stream diagnostic output for batch applications, opening and tracking file-backed log streams as needed.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Presentation.ConsoleApplication
reference_type: package
operation_id: OP-CA-004
trigger: Downstream batch application code calls WriteStatusMsg, WriteErrorMsg, or WriteAppLogMsg
---

# Batch log and status message writing

`clsBatchBase` gives batch applications a small set of output methods so status and error text goes to the correct destination — standard output, standard error, or one of up to five environment-variable-configured log files — without each application managing `StreamWriter` instances itself.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CA-004 |
| **Trigger** | Downstream batch application code calls `WriteStatusMsg`, `WriteErrorMsg`, or one of the `WriteAppLogMsg` overloads |
| **Inputs** | Message text (`String`); optionally a `BatchStreams` target (`StandardFile`, `File0`…`File4`) |
| **Outputs** | Text written to `Console.Out`, `Console.Error`, or an open file stream; for file streams, an opened/updated `System.IO.StreamWriter` tracked in the instance's internal log table |
| **Primary components** | `clsBatchBase.WriteStatusMsg`, `clsBatchBase.WriteErrorMsg`, `clsBatchBase.WriteAppLogMsg` (both overloads) |
| **Entry point** | `Presentation\SAIF.Presentation.ConsoleApplication\clsBatchBase.vb` |

## Steps

1. **Write a status message (`WriteStatusMsg`).** Writes the given text to `Console.Out` via `Console.WriteLine`. Used internally by `WriteBatchHeader`/`WriteBatchFooter` as part of the [console application execution lifecycle](console-application-lifecycle.md).
2. **Write an error message (`WriteErrorMsg`).** Writes the given text to `Console.Error` via `Console.Error.WriteLine`.
3. **Write a console-only application-log message (`WriteAppLogMsg(AppLogMsg)`).** Writes the given text directly to `Console.Out`; no file or stream is involved.
4. **Write a stream-targeted application-log message (`WriteAppLogMsg(AppLogMsg, LogFile)`).** Resolves the target from the `BatchStreams` enum value's upper-cased name (`LogNo`):
   - **If `LogNo = "STANDARDFILE"`:** unconditionally opens a **new** `IO.StreamWriter` at `{CurrentDirectory}\{AppName}.log`, replacing any previously tracked writer for this stream, then writes and flushes the message ([BR-006](../business-rules.md#br-006-standardfile-batch-log-stream-is-recreated-on-every-write)).
   - **If `LogNo` is any other stream name (`File0`…`File4`):**
     - Reads the environment variable named `LogNo`.
     - If that environment variable is empty/unset: throws `Exception("Log stream " & LogNo & " is not a valid environment variable or file.")` ([BR-001](../business-rules.md#br-001-batch-log-stream-must-resolve-to-a-valid-file)).
       - On failure: the exception propagates uncaught out of `WriteAppLogMsg` (the internal `Try`/`Catch` re-throws via a bare `Throw`).
     - If the environment variable is set and no `StreamWriter` has been opened yet for this stream (the tracked value is still its placeholder empty string): opens a new `IO.StreamWriter` at the path named by the environment variable and tracks it.
     - If a `StreamWriter` was already opened for this stream in a prior call: reuses it without reopening.
     - Writes the message to the resolved `StreamWriter` and flushes it immediately.
5. **Streams remain open until teardown.** Any `StreamWriter` opened by step 4 stays open (to allow further appends) until `clsBatchBase.Uninitialize()` flushes and closes it as part of the [console application execution lifecycle](console-application-lifecycle.md).

## Process flow

The following diagram visualizes how `WriteAppLogMsg(AppLogMsg, LogFile)` resolves and writes to its target stream.

```mermaid
flowchart TD
	Start([WriteAppLogMsg called<br>with message and LogFile]) --> IsStd{LogFile is<br>StandardFile?}
	IsStd -->|Yes| NewStd[Always open a new StreamWriter<br>at CurrentDirectory AppName.log]
	IsStd -->|No| EnvCheck{Environment variable<br>for stream is set?}
	EnvCheck -->|No| ThrowErr([Throw: not a valid<br>environment variable or file])
	EnvCheck -->|Yes| Opened{StreamWriter already<br>opened for this stream?}
	Opened -->|No| NewNamed[Open new StreamWriter<br>at env-var path]
	Opened -->|Yes| ReuseNamed[Reuse existing StreamWriter]
	NewStd --> Write[Write line and flush]
	NewNamed --> Write
	ReuseNamed --> Write
	Write --> End([Stream stays open<br>until Uninitialize])
```

## Failure and edge-case behavior

- Writing to a non-`StandardFile` batch log stream whose environment variable is unset or empty throws an exception rather than silently discarding the message ([BR-001](../business-rules.md#br-001-batch-log-stream-must-resolve-to-a-valid-file)).
- Repeated writes to the `StandardFile` stream each open a brand-new `StreamWriter` over the same path instead of reusing the one from the previous call, unlike the named (`File0`…`File4`) streams, which are opened once and reused ([BR-006](../business-rules.md#br-006-standardfile-batch-log-stream-is-recreated-on-every-write)).
- `WriteErrorMsg` writes to `Console.Error` only — it never writes to a file-backed stream, even when the application also has batch log streams configured.
- The internal log table only tracks streams that were pre-registered during `Initialize()` (names matching `FILE?`) or the `StandardFile` slot; a `BatchStreams` value with no corresponding pre-registered environment variable still throws per [BR-001](../business-rules.md#br-001-batch-log-stream-must-resolve-to-a-valid-file) when first written to.*

> **Note:** Statements marked with `*` were inferred from code structure, naming
> conventions, or contextual evidence where direct confirmation was not available
> in source artifacts.

## Related documentation

- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources

- `Presentation\SAIF.Presentation.ConsoleApplication\clsBatchBase.vb`
