DocView Capture by DocView.AI3 Nov 2026 09:42

C# export scripts

To run a script on a timetable instead of for each batch (for example to zip the day's exports), use a scheduled task.

When the built-in export destinations (folder, SFTP, SQL insert, REST) are not enough, you can write your own export in C#. A C# export script can copy files, call a web service, write to a database or run any .NET code. It is compiled with Roslyn and run by the DocView Worker once per batch.

Important: C# export scripts are not sandboxed. They run inside the DocView Worker process with the rights of the DocView Worker's service account: files, network shares, databases and web services. Only give the permission to write them to people you trust with server access.

Before you start

  • You need the permission Admin.CSharpScripts ("Write C# export scripts"). Only the Administrator role has it by default. The same permission is needed to import a Batch Setup file that contains a C# script destination. See Users, roles and permissions.
  • The installation must allow C# scripts. The DocView Worker setting Export:CSharpScripts:Enabled is true by default. When it is false, batches that reach a C# script destination fail with a clear message. See the configuration reference.

Add a C# script destination

  1. Open the Batch Setup and work on a draft version.
  2. Open the Output & export tab.
  3. Under Export destinations, choose C# script in the Add destination list, type a Name and click Add.
  4. Open the new destination.
  5. Write the script in C# script. A new destination starts with a working example.
  6. Under Parameters, add any values the script needs, for example TargetFolder.
  7. Set Time limit per step (seconds): 5 to 3600, default 300.
  8. Click Test to compile the script, then save.

Test only compiles the script and lists the methods it overrides. It never runs your code. Compiling happens on the web server; running happens on the DocView Worker.

How the script runs

You write the body of a class that derives from ExportScript. You can put using lines at the top. Override the methods you need:

Method When it runs
BatchExportStart(ExportScriptContext context) Once per batch, before the documents.
DocumentExport(ExportScriptContext context, ExportedDocument document) Once per document, in document order.
BatchExportEnd(ExportScriptContext context) Once per batch, after the documents.
BatchExportFailed(ExportScriptContext context, string error) When the export of the batch failed. Use it to undo or clean up.

The order is: BatchExportStart, DocumentExport for each document, then BatchExportEnd.

Before your script runs, DocView Capture renders every output file of the batch (PDF or TIFF images, XML, CSV or JSON data files) into a private work folder. Your script copies or moves them from there. The work folder is deleted after the export.

If any method throws an exception, calls context.Fail(...), or takes longer than the time limit, the export stops. BatchExportFailed runs, and the batch goes to the exception queue with the message, where a supervisor can retry it.

Note: DocView Capture cannot undo what your script already did outside DocView Capture. Write BatchExportFailed so that a retry is safe, for example by removing files the script wrote.

What the script can use

ExportScriptContext

Member Type Meaning
BatchId Guid The batch id.
BatchName string The batch name.
BatchClass string The Batch Setup's name.
BatchFields IReadOnlyDictionary<string, string?> Batch field values by name.
Documents IReadOnlyList<ExportedDocument> All exported documents. Rejected documents are left out.
BatchFiles IReadOnlyList<ExportedFile> Files for the whole batch, for example one data file per batch.
WorkFolder string The private folder with every output file of the batch.
Parameters IReadOnlyDictionary<string, string> The destination's Parameters. Names are not case-sensitive.
Items IDictionary<string, object?> Anything you want to keep between methods.
CancellationToken CancellationToken Signalled when the DocView Worker stops or the time limit is reached. Check it in long loops.
Log(message) method Writes a line to the DocView Worker log.
Warn(message) method Writes a warning line to the DocView Worker log.
Fail(message) method Stops the export of the batch with this message.

ExportedDocument

Member Type Meaning
Number int The document number in the batch.
ClassKey / ClassName string? The document class key and name.
PageCount int Number of pages.
Fields IReadOnlyDictionary<string, string?> Field values by field name.
Tables IReadOnlyDictionary<string, IReadOnlyList<IReadOnlyDictionary<string, string?>>> Table rows (line items) by table name; each row maps column names to values.
Files IReadOnlyList<ExportedFile> This document's output files.

ExportedFile

Member Meaning
Name The path the output settings gave the file, for example Invoices/invoice_1.pdf.
FullPath Where the file is now, inside WorkFolder.
ContentType The MIME type, for example application/pdf.

Namespaces and references

These namespaces are imported for you: System, System.IO, System.Linq, System.Text, System.Text.Json, System.Collections.Generic, System.Net.Http, System.Threading, System.Threading.Tasks, System.Globalization and System.Xml.Linq.

The script can also use System.Diagnostics.Process, System.Data.Common and Microsoft.Data.SqlClient (add the using line).

Example: copy files named by invoice number

This is close to the example every new destination starts with.

// Parameters on the destination: TargetFolder = \\fileserver\finance\invoices

public override void BatchExportStart(ExportScriptContext context)
{
    var target = context.Parameters.TryGetValue("TargetFolder", out var folder) ? folder : @"C:\DocViewExport";
    Directory.CreateDirectory(target);
    context.Items["target"] = target;
    context.Log($"Exporting {context.BatchName} ({context.Documents.Count} documents) to {target}");
}

public override void DocumentExport(ExportScriptContext context, ExportedDocument document)
{
    var target = (string)context.Items["target"]!;
    var invoice = document.Fields.TryGetValue("InvoiceNumber", out var number) && !string.IsNullOrWhiteSpace(number)
        ? number
        : $"document-{document.Number}";

    foreach (var file in document.Files)
    {
        var destination = Path.Combine(target, invoice + Path.GetExtension(file.Name));
        if (File.Exists(destination))
        {
            context.Fail($"{destination} already exists.");
        }

        File.Copy(file.FullPath, destination);
    }
}

public override void BatchExportEnd(ExportScriptContext context)
{
    // A marker file that other systems wait for.
    File.WriteAllText(Path.Combine((string)context.Items["target"]!, context.BatchName + ".done"), DateTime.Now.ToString("s"));
}

public override void BatchExportFailed(ExportScriptContext context, string error)
{
    context.Warn("Export failed: " + error);
}

Example: post line items to a web service

private static readonly HttpClient Http = new();

public override void DocumentExport(ExportScriptContext context, ExportedDocument document)
{
    var payload = new
    {
        batch = context.BatchName,
        invoice = document.Fields.GetValueOrDefault("InvoiceNumber"),
        lines = document.Tables.GetValueOrDefault("LineItems")
    };

    using var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
    using var response = Http.PostAsync(context.Parameters["Endpoint"], content, context.CancellationToken).GetAwaiter().GetResult();
    if (!response.IsSuccessStatusCode)
    {
        context.Fail($"The web service answered {(int)response.StatusCode} for document {document.Number}.");
    }
}

The methods are synchronous. Call asynchronous APIs with .GetAwaiter().GetResult() and pass context.CancellationToken.

Good practice

  • Use Parameters for folders, addresses and customer codes, so one script serves several destinations and Batch Setups.
  • Keep secrets out of the script. Scripts are exported with the Batch Setup file.
  • Make retries safe. Check whether a file or record already exists before you create it.
  • Log what you do with context.Log, so support can follow an export in the DocView Worker log.
  • Order destinations so that irreversible ones, such as calls to other systems, come last.
  • Test on a test system first. Test against a sample batch on the Output & export tab shows the file names and data files your script will receive, without writing or sending anything. Then export a real batch on the test system.

Troubleshooting

Message Cause
"The C# script does not compile: line N: …" A compiler error. Line numbers are your script's own lines.
"The script compiles, but it overrides none of …" Method names or signatures do not match. Use public override void.
"… took longer than N seconds." A method passed the Time limit per step. Raise it, or make the script faster.
"C# export scripts are switched off on this installation …" Export:CSharpScripts:Enabled is false on the DocView Worker.

Still stuck? support@docview.ai · +44 7886 864921

Made with DocView Capture by DocView.AI · www.docview.ai