---
title: Using Editor.CommandAsync to chain multiple commands involving user input
description: "# Motivation You might want to chain two or more AutoCAD/Civil 3D commands that involve user interaction — for example, generating tables where the user needs to click **“OK”** or **“Cancel”** in a dialog box. # Editor.Command According to [this…"
url: "https://civilwhiz.com/docs/using-editor-commandasync-to-chain-multiple-commands-involving-user-input/"
updated: "2025-10-06"
category: API
---

# Using Editor.CommandAsync to chain multiple commands involving user input

# Motivation

You might want to chain two or more AutoCAD/Civil 3D commands that involve user interaction — for example, generating tables where the user needs to click **“OK”** or **“Cancel”** in a dialog box.

# Editor.Command

According to [this post on TheSwamp](https://www.theswamp.org/index.php?topic=49124.0), the `Editor.Command()` method should do the job. In theory, it should wait for user input before proceeding to the next command.

```csharp
[CommandMethod(nameof(ConsecutiveCommand))]
public void ConsecutiveCommand()
{
    Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument
        .Editor.Command("AeccAddNetworkPipeTable");
    Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument
        .Editor.Command("AeccAddNetworkStructTable");
}
```

In other words, the above `ConsecutiveCommand` should first present the user with the dialog box for adding a Network Pipe Table (`_AeccAddNetworkPipeTable`).

The user can configure the settings and click **OK**, and only after that should the next dialog box (`_AeccAddNetworkStructTable`) appear.

## What actually happens

In practice, the first command (`_AeccAddNetworkPipeTable`) runs correctly, but the second command (`_AeccAddNetworkStructTable`) is ignored — as if it never existed.

The reason for this behavior isn’t immediately obvious.

# Solution: Editor.CommandAsync

The solution is to use `Editor.CommandAsync`, as explained in [this Autodesk forum post](https://forums.autodesk.com/t5/net-forum/unable-to-call-sequential-commands-together/m-p/13835928/highlight/true#M85849).

You’ll need to call `CommandAsync` within a loop to ensure that each command completes before the next one runs.

Here’s a wrapper class that encapsulates the mechanism:

```csharp
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.ApplicationServices.Core;
using Autodesk.AutoCAD.EditorInput;
using System;
using System.Threading.Tasks;
using Application = Autodesk.AutoCAD.ApplicationServices.Core.Application;

public class CommandSequenceRunner
{
    private readonly Editor _editor;

    public CommandSequenceRunner(Editor editor)
    {
        _editor = editor ?? throw new ArgumentNullException(nameof(editor));
    }

    /// <summary>
    /// Runs AutoCAD commands sequentially, waiting only for
    /// interactive commands that remain active in CMDNAMES.
    /// </summary>
    public async Task RunAsync(params string[] commands)
    {
        for (int i = 0; i < commands.Length; i++)
        {
            string cmd = commands[i];
            if (string.IsNullOrWhiteSpace(cmd))
                continue;

            await _editor.CommandAsync(cmd);

            // Wait only if the command remains active (interactive)
            string baseName = GetCommandBaseName(cmd);
            if (IsCommandStillRunning(baseName))
            {
                try
                {
                    while (IsCommandStillRunning(baseName))
                        await _editor.CommandAsync(Editor.PauseToken);
                }
                catch
                {
                    break;
                }
            }
        }
    }

    private static bool IsCommandStillRunning(string name)
        => GetActiveCmdNames().Contains(name, StringComparison.OrdinalIgnoreCase);

    private static string GetActiveCmdNames()
        => (string)Application.GetSystemVariable("CMDNAMES");

    private static string GetCommandBaseName(string cmd)
    {
        var first = cmd.Split(' ', '\t')[0];
        return first.TrimStart('.', '_');
    }
}
```

And here’s how to use it:

```csharp
var ed = Application.DocumentManager.MdiActiveDocument.Editor;
var runner = new CommandSequenceRunner(ed);

await runner.RunAsync(
    "AeccAddNetworkPipeTable",
    "AeccAddNetworkStructTable");
```

 [![](https://civilwhiz.com/wp-content/uploads/2025/02/someoneme.jpg)](https://civilwhiz.com/author/civilwhiz/)[Ngu Soon Hui](https://civilwhiz.com/author/civilwhiz/)

My passion is in [sharing knowledge](/about/) — Civil 3D or otherwise– with the world.

I’m also the [benevolent dictator for life](https://mes100.com/about-ngu-soon-hui/) at MES Innovation Sdn Bhd.
