VBScript (6.0)
This assessment applies the coupling account — coupling as access to a shared resource, and the coupling floor [1], [2] — and the knowledge-embodiment theorem [3]; the language is assessed against its official reference [4].
1 Assessment
This page assesses VBScript in five parts: core coupling — what the language’s own constructs force; ecosystem coupling — what the surrounding platform, tooling, and community cost; engineering readiness — whether the artifact can be reproduced, verified, observed, worked in quickly, connected to other languages, and governed openly; the profile — the unscored facts a score cannot express; and the scoring detail — the mechanism marks and the arithmetic behind every score. A ✅ bullet marks a construct that helps. A ⚠️ or ❌ bullet marks a cost; the scoring model does not price every cost named here.
Core coupling 40/100 · Ecosystem coupling 39/100 · Engineering readiness 57/100
1.1 Core coupling
1.1.1 Type
- ❌ A variable has no declared type:
Dim xdeclares a name, and the value it holds is aVariantwhose subtype is decided at the assignment, so the operator resolves the operands when the statement runs and+adds or concatenates according to the values it receives (T1) - ❌ There is no namespace: Every global variable and procedure lives in one flat global scope, so two included scripts share it (T6)
- ❌ There is no module boundary: A script file exports nothing and imports nothing explicitly, and
ExecuteGlobalor a.wsfinclude writes into the same global scope (T11) - ✅ The subtype is inspectable:
VarType,IsNumeric,IsDate,IsArray, andIsObjectlet a script ask what a variant holds - ✅
NullandEmptyare distinct values with their own tests:IsNullandIsEmptyseparate a true null from an uninitialised variant - ✅
Class, added in version 5.0, groups state with behaviour: A class declaresPrivatefields andPublicproperty procedures, withClass_InitializeandClass_Terminate
1.1.2 Construction
- ❌ A global variable appears at its first assignment: Without
Option Explicit,x = 1at file scope creates a global, so state appears wherever a name is first used (C1) - ✅
Option Explicitrequires a declaration: With it, an undeclared name is an error instead of a new variable - ✅
SubandFunctionscope their own locals: ADiminside a procedure belongs to that procedure - ✅ A class validates and cleans up in its two lifecycle methods:
Class_Initializeruns at creation andClass_Terminateat release - ✅ A
.wsffile combines several scripts: A Windows Script File includes more than one script file, and the procedures of one are callable from another - ⚠️
ExecuteGlobaldefines a global at run time: A generated statement can create a name that no declaration lists
1.1.3 Memory
- ✅ The script engine owns the memory: There is no allocate, free, or pointer operation in the language
- ✅ A COM object is released by reference count: The object is freed when its last reference goes out of scope, and
Class_Terminateruns at that point - ✅ No pointer type and no address exist: A value can never name a memory location
- ✅ A class instance is collected by the engine: The script states no lifetime for a class object
- ⚠️ A reference cycle between script and COM objects is not reclaimed: The engine’s counter cannot release a cycle, and the process must end to reclaim it
- ⚠️ Repeated string concatenation in a loop reallocates: A long string built with
&is copied at each step, and the language has no string builder
1.1.4 Error
- ❌ There is no structured error path: The language has no
tryand nocatch, onlyOn Error Resume Nextand theErrobject (Er1) - ❌
On Error Resume Nextdiscards a failure by default: The next statement runs regardless, and the failure is invisible unlessErr.Numberis tested - ✅ The
Errobject makes a failure a value:Err.Number,Err.Description,Err.Source, andErr.Raiselet a handler read and create a failure - ✅
On Error GoTo 0ends the suppressed mode: Error handling returns to the default at that statement - ⚠️ A host error names its provider: An ADO, WMI, or file-system failure carries a provider-specific number and source, so a handler is bound to that provider
- ⚠️ An unhandled failure ends the script: There is no caller frame to unwind to, and the default action is to stop
1.1.5 Concurrency
- ✅ The language has no shared-memory concurrency: A script runs single-threaded in its host, so there is no race to guard
- ✅ A script can start another process:
WScript.Shell.Runlaunches a program, andExecreturns a stream of its output - ✅ The host delivers an event to the script on its own thread: A callback is serialised onto the host’s thread, so the script never observes a concurrent invocation of itself
- ⚠️ The host decides the threading model: Windows Script Host, Internet Explorer, and classic ASP each run a script differently, and the host’s apartment model governs a COM call
- ⚠️ A session-scoped object is shared across requests: In classic ASP,
Sessionstate is visible to more than one request, and nothing in the language partitions it - ⚠️ A long-running script blocks its host thread: The language has no yield and no cancellation
1.1.6 Platform
- ❌ The engine is Windows-only:
vbscript.dllis the only implementation, and it ships with Windows, so a script runs on no other platform (P1) - ❌ Every capability arrives through COM: File access, WMI, ADO, and the shell are COM objects such as
Scripting.FileSystemObjectandADODB.Connection, so a script depends on the registered object model - ✅ A
.vbsfile needs no build step: The host runs the text as written - ✅ The host is part of the operating system:
cscript.exeandwscript.exeare installed with Windows - ⚠️ The host decides which objects exist: Windows Script Host, Internet Explorer, and classic ASP present different object models to the same language
- ⚠️ A
.wsffile states its own includes: A multi-file script needs theJobattributes and the<script src=...>elements that name its parts
1.1.7 Trade-offs (not coupling)
- Hosted scripting is the purpose of the language: VBScript is designed to be embedded in a host, so the dependence on the host is a scope decision
- The classic Visual Basic surface is a familiarity trade: The BASIC syntax is easy to read, and one value type keeps the engine simple, at the cost of the type system
- A suppressed error is sometimes deliberate:
On Error Resume Nextaround one statement is a chosen tactic - The language is meant for short programs: A page of automation is the design point, not a system
- A fixed parameter list is a deliberate omission: The language cannot pass a variable number of arguments, so a variadic call is written as an array parameter
- The deprecation is a lifecycle decision: Microsoft’s removal plan is a product decision rather than a language mechanism
1.2 Ecosystem coupling
1.2.1 Performance
- ⚠️ The compiled form does not survive the process: The engine compiles the script at load rather than ahead of time, so a fresh host pays the parse again
- ⚠️ A variant costs at every operation: An operation reads the subtype tag and converts the operands before it acts
- ✅ The engine is an in-process library: The host loads it once, so a script starts with no separate runtime to launch
- ✅ The engine compiles the file before it runs: The host parses and compiles the script once at start, and a page host can keep the compiled script for later requests
- ⚠️ A COM call dominates a data-heavy script: The crossing into ADO, WMI, or a file-system object is where the time goes
- ⚠️ String handling is the common trap: Concatenation in a loop and a repeated
RegExpreplace on a large string cost far more than the control flow
1.2.2 Ecosystem
- ❌ The language is proprietary and discontinued: It exists in one vendor’s product, and Microsoft announced the deprecation in October 2023 (Ec4)
- ❌ The ecosystem is legacy and frozen: The language has gained no feature since version 5.5 (2000), when the engine moved to sustaining engineering, so the tool field is historical (Ec3)
- ✅ The runtime tooling is part of Windows:
cscriptandwscriptare installed with the operating system - ✅ A large body of published scripts exists: Administrative scripts, examples, and books from the 2000s are widely available
- ✅ The migration targets are named and documented: Microsoft points to PowerShell and JavaScript and describes the path
- ⚠️ Many environments block the script host: A security policy or a mail filter commonly disables or rejects a
.vbsfile
1.2.3 Evolution
- ❌ The language is discontinued: Microsoft announced the deprecation in October 2023 with removal planned after 2027, so no further version is expected (V3)
- ✅ The remaining life is long and published: The phased plan keeps the language available as an on-demand feature for years, so an existing script keeps running
- ✅ The language does not change under a script: An existing script’s meaning is fixed, which makes a migration predictable
- ✅ A successor covers each use: PowerShell replaces the administration role and JavaScript replaces the browser and page role
- ⚠️ New code has no reason to choose it: The direction of the platform is removal, not extension
1.2.4 Domain
- ❌ The domain is Windows administration and COM: The useful work is expressed through WMI, ADO, the file-system object, and the shell, and none of that exists off Windows (D1)
- ✅ Administrative automation fits it well: A short script drives WMI and the registry directly
- ✅ Classic ASP and HTML Applications were real hosting domains: A server page and an
.htafile both used VBScript with the full object model - ✅ Test automation still uses it: UFT One and similar tools keep a VBScript dialect for their test scripts
- ⚠️ PowerShell has replaced it for administration: The same task is now written in PowerShell
- ⚠️ An embedded operator interface is a narrow remaining use: A few industrial and point-of-sale systems still run a VBScript engine for local automation
1.2.5 Learning
- ✅ The syntax is small:
If ... Then ... End If,Sub,Function, andFor Eachare the surface - ✅ The curve is gentle for a Visual Basic programmer: The classic Visual Basic surface carries over almost unchanged
- ✅ The reference is complete: Microsoft’s VBScript Language Reference documents every statement and function
- ✅ The error model is easy to start with:
On Error Resume Nextand theErrobject are a few lines - ⚠️ The real subject is COM: The object model beneath the language is the large part of the work
- ⚠️ The error model is easy to misuse: It requires a discipline that the language does not enforce
1.2.6 Syntax
- ✅ The keywords are words:
If,Then,Else,End If,For Each, andNext - ✅ A line is a statement: Statement boundaries are lines, and
:separates two statements on one line - ✅ Line continuation is explicit:
_continues a statement on the next line - ✅ A block closes with its keyword pair:
End If,End Sub,End Function,Loop, andNexteach close their own construct - ⚠️ The language is case-insensitive:
myValueandMyValuename the same variable, so a rename is not caught by the case - ⚠️
Dimmay be omitted: WithoutOption Explicit, a name is declared by its first use, so a typo reads as a new variable
1.2.7 Testing
- ❌ There is no test framework in the language or the host: A check is a script that compares values and reports the result (G1)
- ✅ A test is a
.vbsfile run bycscript: The same engine runs the test and the code under test - ✅ A harness is only a few lines:
WScript.Echowith a comparison gives a report, and a failing check can callErr.Raise - ✅
cscript //Xstarts the script debugger: A step-through debugger is available where the Windows debugging tools are installed - ⚠️ A test suite is the programmer’s own: There is no runner, no fixture loader, and no report format
- ⚠️ A type error appears only in the test run: Nothing checks a value’s use before the line executes
1.2.8 Security
- ❌ Untrusted input can become code:
Execute,ExecuteGlobal, andEvalevaluate text, so a value built from input can run as a statement (Q3) - ❌ Script malware is a known, historical class: The ILOVEYOU worm spread as a
.vbsattachment, and the file extension is still commonly blocked - ❌ The file-system object grants the user’s own rights:
Scripting.FileSystemObjectcan read or overwrite any file the invoking user can - ✅ A script runs without elevation by default: It holds the privileges of the invoking user and no more
- ⚠️ The usual mitigation is policy: A mail filter, an attachment block, or a group-policy restriction, rather than a language feature
- ⚠️ Correct quoting must be uniform: An injection that forms a valid statement is not distinguishable from a legitimate one by the engine
1.3 Engineering readiness
1.3.1 Reproducibility
- ✅ No charged mechanism in this dimension.
1.3.2 Supply chain
- ⚠️ Published packages carry no signed provenance by default.
1.3.3 Observability
- ⚠️ No stable tracing and metrics standard.
- ⚠️ The standard library has no structured logging.
1.3.4 Feedback
- ⚠️ No fast in-editor analysis.
1.3.5 Interop
- ⚠️ No maintained portable target.
1.3.6 Governance
- ⚠️ One vendor decides the language’s direction.
- ⚠️ The specification is not public.
1.4 Profile
Unscored, and kept separate from every score on purpose. The profile records what a mechanism price cannot express: what a running program costs, how well a coding model and an agent work in the language, and whether a safety-critical path exists.
1.4.1 Energy and cost
What this axis asks: what does a running program cost in energy and time?
1.4.2 AI and agent readiness
What this axis asks: how well does a coding model and an agent work in this language?
- ❌ Sparse training data: models write it unreliably [7].
1.4.3 Safety certification
What this axis asks: is there a certified or standards-qualified path to a safety-critical system?
- ⚠️ No certified or standards-qualified path for safety-critical systems.
1.5 Scoring detail
1.5.1 Core coupling Dimensions
| Dimension | Mechanism | Description | Present | Cost |
|---|---|---|---|---|
| Type | T1 |
dynamic no static check | ✅ | −15 |
T2 |
weak static | — | 0 | |
T3 |
dynamic/duck dispatch | — | 0 | |
T4 |
no sum types | — | 0 | |
T5 |
no generics | — | 0 | |
T6 |
no namespaces | ✅ | −8 | |
T7 |
type erasure/reflection | — | 0 | |
T8 |
operator overloading | — | 0 | |
T9 |
inheritance required for polymorphism | — | 0 | |
T10 |
no null-safety | — | 0 | |
T11 |
no module boundary | ✅ | −8 | |
T12 |
no effect tracking | ✅ | −8 | |
T13 |
async/sync colouring | — | 0 | |
T14 |
unchecked foreign boundary | ✅ | −4 | |
| Type subtotal | −15 (−43) | |||
| Construction | C1 |
global mutable state by default | ✅ | −15 |
C2 |
no immutability by default | — | 0 | |
C3 |
constructors coupled to allocation | — | 0 | |
C4 |
no constructor/validation | — | 0 | |
| Construction subtotal | −15 | |||
| Memory | M1 |
manual deallocation | — | 0 |
M2 |
GC non-deterministic pauses | — | 0 | |
M3 |
no RAII | — | 0 | |
M4 |
no ownership model | — | 0 | |
| Memory subtotal | 0 | |||
| Error | Er1 |
no structured path | ✅ | −15 |
Er2 |
unchecked exceptions only | — | 0 | |
Er3 |
errors ignored/non-exhaustive | — | 0 | |
Er4 |
no composable result type | — | 0 | |
| Error subtotal | −15 | |||
| Concurrency | K1 |
GIL/no parallel | — | 0 |
K2 |
shared mutable state default | — | 0 | |
K3 |
manual sync no race detection | — | 0 | |
K4 |
no structured concurrency | — | 0 | |
K5 |
no primitives | — | 0 | |
| Concurrency subtotal | 0 | |||
| Platform | P1 |
cannot function outside one vendor/domain | ✅ | −15 |
P2 |
single-vendor but other uses | — | 0 | |
P3 |
legacy/discontinued platform | — | 0 | |
| Platform subtotal | −15 |
Core Dimensions score: 40/100 — total cost = −60 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).
1.5.2 Ecosystem coupling Dimensions
| Dimension | Mechanism | Description | Present | Cost |
|---|---|---|---|---|
| Performance | R1 |
interpreted no AOT/JIT | — | 0 |
R2 |
GC pauses | — | 0 | |
R3 |
JIT warmup | — | 0 | |
| Performance subtotal | 0 | |||
| Ecosystem | Ec1 |
no package manager | — | 0 |
Ec2 |
fragmented tooling | — | 0 | |
Ec3 |
small/niche/discontinued | ✅ | −8 | |
Ec4 |
proprietary | ✅ | −8 | |
Ec5 |
platform-locked tooling | — | 0 | |
Ec6 |
monoculture | — | 0 | |
Ec7 |
legacy burden | — | 0 | |
| Ecosystem subtotal | −15 (−16) | |||
| Evolution | V1 |
breaking changes | — | 0 |
V2 |
frozen | — | 0 | |
V3 |
discontinued | ✅ | −15 | |
V4 |
glacial standards | — | 0 | |
| Evolution subtotal | −15 | |||
| Domain | D1 |
domain/vendor lock-in | ✅ | −15 |
D2 |
poor domain fit | — | 0 | |
D3 |
framework forces architecture | — | 0 | |
| Domain subtotal | −15 | |||
| Learning | L1 |
steep | — | 0 |
L2 |
large surface/multi-paradigm | — | 0 | |
L3 |
sparse docs | — | 0 | |
| Learning subtotal | 0 | |||
| Syntax | S1 |
verbose | — | 0 |
S2 |
inconsistent | — | 0 | |
S3 |
punctuation-heavy | — | 0 | |
| Syntax subtotal | 0 | |||
| Testing | G1 |
weak tooling | ✅ | −8 |
G2 |
poor debugging | — | 0 | |
G3 |
runtime-only errors | — | 0 | |
| Testing subtotal | −8 | |||
| Security | Q1 |
memory-unsafe | — | 0 |
Q2 |
dynamic/weak typing risk | — | 0 | |
Q3 |
known vulnerability/injection | ✅ | −8 | |
| Security subtotal | −8 |
Meta Dimensions score: 39/100 — total cost = −61 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).
1.5.3 Engineering readiness Dimensions
| Dimension | Mechanism | Description | Present | Cost |
|---|---|---|---|---|
| Reproducibility | Y1 |
build not reproducible | — | 0 |
Y2 |
dependencies not pinned | — | 0 | |
| Reproducibility subtotal | 0 | |||
| Supply chain | Y3 |
no signed provenance | ✅ | −8 |
Y4 |
registry without namespacing | — | 0 | |
| Supply chain subtotal | −8 | |||
| Observability | Y5 |
no stable tracing standard | ✅ | −8 |
Y6 |
no structured logging | ✅ | −4 | |
| Observability subtotal | −12 | |||
| Feedback | Y7 |
slow build | — | 0 |
Y8 |
no fast in-editor analysis | ✅ | −4 | |
| Feedback subtotal | −4 | |||
| Interop | Y9 |
no foreign-function interface | — | 0 |
Y10 |
no portable target | ✅ | −4 | |
| Interop subtotal | −4 | |||
| Governance | Y11 |
single-vendor governance | ✅ | −8 |
Y12 |
closed specification | ✅ | −8 | |
| Governance subtotal | −15 (−16) |
Readiness Dimensions score: 57/100 — total cost = −43 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).
Verdict: VBScript holds the lowest pair of scores in this group, and the losses concentrate in its defaults and its dependence. A variable is a Variant with no declared type, an undeclared name becomes a global, an error is a mode the caller must enable, and every useful capability arrives through a COM object that exists only on Windows. What the language does provide is a tiny readable syntax, a host that is already installed, lifecycle methods on a class, and Option Explicit to require a declaration. Main strengths: a gentle learning curve, direct WMI and ADO automation, a .wsf file that packages a multi-file script, and a simple way to restrict a script through the Windows Script Host. Main weaknesses: no structured error path, no namespace and no module boundary, a proprietary and discontinued implementation, a domain locked to Windows and COM, weak tooling, and an injection surface that made it a malware vehicle.
The formal development. The definitions, theorems, and proofs behind this page are published in:
- On the Nature of Coupling: All Coupling as Shared Resource Access — Zenodo, 2026 — doi:10.5281/zenodo.21925122
- Coupling as a Consequence of Cohesion: Decomposition, the Coupling Floor, and Domain-Imposed Coupling — Zenodo, 2026 — doi:10.5281/zenodo.21925201
- On the Nature of Cohesion: Cohesion as Correctness Relative to a Partitioning Rule — Zenodo, 2026 — doi:10.5281/zenodo.21703193