eae-fork

📁 sapiencezk/eae-skills 📅 Jan 22, 2026
8
总安装量
7
周安装量
#35701
全站排名
安装命令
npx skills add https://github.com/sapiencezk/eae-skills --skill eae-fork

Agent 安装分布

claude-code 6
opencode 3
windsurf 2
trae 2
codex 2

Skill 文档

EAE Block Fork – Hybrid Manual/Automated Workflow

Fork function blocks from Schneider Electric standard libraries into your custom library using a hybrid approach that combines the best of manual and automated workflows.

v7.2 ENHANCED – Production-Ready Reliability:

  • Manual fork in EAE GUI → Perfect HMI files (generated by EAE’s designer)
  • Automated finalization → Single-command execution updates ALL references
    • ✅ Root namespace updates
    • ✅ Cross-block references (FB/SubCAT in .fbt files)
    • ✅ HMI cross-references (fully qualified types in Designer.cs)
    • ✅ GUID generation + Registration
    • ✅ Transactional rollback – Automatic recovery from failures (v7.1)
    • ✅ UTF-8 encoding – Works on international Windows systems (v7.1)
    • 🆕 Pre-fork validation – Catches errors before manual fork in GUI (v7.2)
    • 🆕 Better error messages – Contextual help with recovery suggestions (v7.2)
    • 🆕 Resume capability – Gracefully handles interrupted forks (v7.2)
    • 🆕 Dependency auto-detection – Automatically suggests all SubCATs to fork (v7.2)

Why this approach?

  • ✅ Perfect HMI files – EAE’s GUI generates flawless Designer.cs files
  • ✅ Complete automation – One command handles all namespace updates
  • ✅ Cross-reference handling – Automatically updates references between forked blocks
  • ✅ Fast – ~15 seconds per hierarchy (vs 3+ minutes manual editing)
  • ✅ User control – Full visibility in GUI during fork
  • ✅ Failure-safe – Auto-rollback protects your project from corruption
  • 🆕 Resumable – Interrupted forks can be resumed from last successful block

Separation of Concerns:

  • eae-fork (this skill): Finalize manually forked blocks (namespaces, GUIDs, registration)
  • eae-cat: Register CAT blocks in dfbproj AND csproj (when called with --register-only)
  • eae-composite-fb: Register composite blocks in dfbproj (when called with --register-only)
  • eae-basic-fb: Register basic blocks in dfbproj (when called with --register-only)
  • eae-adapter: Register adapters in dfbproj (when called with --register-only)
  • eae-datatype: Register data types in dfbproj (when called with --register-only)

Quick Start

Interactive Guided Workflow – Just tell the skill what you want:

You: Fork AnalogInput into SE.ScadapackWWW

Claude:
  📋 Analyzing AnalogInput...

  This block requires a 3-level hierarchy:
  1. AnalogInputBase (core logic)
  2. AnalogInputBaseExt (extended features)
  3. AnalogInput (full implementation)

  📝 Please fork these blocks in EAE GUI:

  Steps:
  1. Open EAE GUI
  2. Navigate to SE.App2CommonProcess library
  3. For each block, right-click → "Copy Block"
     ☐ AnalogInputBase → SE.ScadapackWWW
     ☐ AnalogInputBaseExt → SE.ScadapackWWW
     ☐ AnalogInput → SE.ScadapackWWW
  4. Reply 'done' when complete

You: done

Claude:
  🔧 Finalizing fork...
  ✓ Validated 3 blocks manually forked
  ✓ Updated namespaces in .fbt files (SE.ScadapackWWW)
  ✓ Updated namespaces in .cs files (15 files)
  ✓ Generated new GUIDs
  ✓ Registered in dfbproj/csproj

  ✅ Fork complete! Blocks ready to use in SE.ScadapackWWW.

What the skill does:

  1. 🔍 Analyzes block hierarchy and dependencies
  2. 📋 Guides you through manual fork in EAE GUI
  3. ⏸️ Waits for your confirmation
  4. 🔧 Executes finalization script – Single command updates everything:
    • Root namespaces in .fbt files
    • Cross-block references (FB/SubCAT elements)
    • HMI namespaces in .cs files
    • HMI cross-references (fully qualified types)
    • New GUIDs for all blocks
    • Project registration (dfbproj/csproj)
  5. ✅ Reports complete summary with counts

Alternative: Manual Finalization

If you’ve already forked in EAE GUI:

/eae-fork --finalize AnalogInput

Triggers

Trigger Description
/eae-fork Primary invocation
fork block from library Natural language
copy block to custom library Alternative phrasing
migrate block namespace Namespace-focused
customize EAE block Customization intent

CRITICAL: Fork Depth Selection

Before forking, ALWAYS ask the user about fork depth:

How deep should the fork go?

1. **Single block only** (Recommended for minor customization)
   - Fork only AnalogInput
   - Uses original library's AnalogInputBaseExt
   - Smallest footprint, easy to maintain

2. **Fork hierarchy** (Base → BaseExt → Full)
   - Fork AnalogInputBase, AnalogInputBaseExt, AND AnalogInput
   - Full control over the entire block chain
   - Best for significant modifications

3. **Fork with all SubCATs**
   - Fork hierarchy PLUS all SubCAT blocks (LimitAlarm, DeviationAlarm, etc.)
   - Maximum customization capability
   - Largest footprint, most maintenance

Which option do you prefer? (1/2/3)

How It Works – Streamlined Workflow (v7.0)

┌─────────────────────────────────────────────────────────────────┐
│      PHASE 1: ANALYZE & GUIDE (Automatic)                        │
├─────────────────────────────────────────────────────────────────┤
│ User: "Fork AnalogInput into SE.ScadapackWWW"                   │
│                                                                  │
│ Skill analyzes:                                                  │
│ 1. Identify block hierarchy (Base → BaseExt → Full)            │
│ 2. Detect dependencies (SubCATs, referenced blocks)             │
│ 3. Determine target library details                             │
│                                                                  │
│ Skill generates guided instructions:                             │
│ • List of blocks to fork (with checkboxes)                      │
│ • Step-by-step EAE GUI instructions                             │
│ • Clear confirmation prompt                                      │
│                                                                  │
│ Output: Checklist for user to follow                             │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│      PHASE 2: MANUAL FORK IN EAE GUI (User)                      │
├─────────────────────────────────────────────────────────────────┤
│ User performs fork using EAE's built-in functionality:           │
│                                                                  │
│ For each block in checklist:                                     │
│ 1. Open EAE GUI                                                  │
│ 2. Navigate to source library (e.g., SE.App2CommonProcess)      │
│ 3. Right-click block → "Copy Block"                             │
│ 4. Select target library (e.g., SE.ScadapackWWW)                │
│ 5. Wait for EAE to generate files                               │
│                                                                  │
│ EAE generates perfect files:                                     │
│ • IEC61499/{Block}/  (all .fbt, .cfg, .xml files)              │
│ • HMI/{Block}/       (perfect Designer.cs files)               │
│                                                                  │
│ ✅ Perfect HMI files (EAE's designer)                            │
│ ✅ All visual properties preserved                               │
│ ✅ No decompilation needed                                       │
│                                                                  │
│ User replies: "done"                                             │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│      PHASE 3: FINALIZE FORK - SINGLE COMMAND (Automatic)         │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│ Command Executed:                                                │
│   python finalize_manual_fork.py \                              │
│       AnalogInputBase AnalogInputBaseExt AnalogInput \          │
│       LimitAlarm DeviationAlarm ROCAlarm \                      │
│       SE.ScadapackWWW                                            │
│                                                                  │
│ What the script does automatically:                              │
│                                                                  │
│ [1/4] VALIDATE MANUAL FORK                                       │
│       • Detect source namespace from existing files              │
│       • Check all blocks forked (IEC61499/ and HMI/)            │
│       • Detect block types (.cfg → CAT, etc.)                   │
│       • Verify file completeness                                │
│                                                                  │
│ [2/4] UPDATE NAMESPACES & CROSS-REFERENCES                       │
│       • Root declarations: Namespace="SE.ScadapackWWW"         │
│       • FB/SubCAT elements: Update refs to forked blocks        │
│       • HMI namespaces: Update Symbols/Faceplates namespaces    │
│       • HMI cross-refs: Update fully qualified type references  │
│       • Generate new GUIDs (12 total: 2 per block)             │
│                                                                  │
│ [3/4] REGISTER IN PROJECT                                        │
│       • Detect block type (CAT/Composite/Basic)                 │
│       • Call registration script for each block                  │
│       • dfbproj entries (Compile/None ItemGroups)               │
│       • csproj entries (CAT HMI files)                          │
│                                                                  │
│ [4/4] REPORT SUMMARY                                             │
│       • Successful: 6/6 blocks                                   │
│       • Cross-references updated: 24                             │
│       • HMI references updated: 18                               │
│                                                                  │
│ Output: "✅ All blocks finalized successfully!"                 │
│                                                                  │
│ Time: ~15 seconds (vs 3+ minutes manual editing)                │
└─────────────────────────────────────────────────────────────────┘

Why This Workflow?

Aspect Manual Fork + Finalize Old Automated Approach
HMI Files ✅ Perfect (EAE-generated) ❌ Decompiled (format issues)
Complexity ✅ Low (simple namespace update) ❌ High (ILSpy, post-processing)
Reliability ✅ 100% (proven EAE workflow) ❌ ~70% (decompilation artifacts)
Speed ✅ ~30 sec/block ⚠️ ~2 min/block
User Control ✅ Full visibility in GUI ⚠️ Black box automation
Maintenance ✅ Easy (140 lines of code) ❌ Hard (500+ lines)

Phase 3 Detail: Registration by Block Type

CAT Blocks (most common):

/eae-cat --register-only {BlockName} {Namespace}
  │
  ├── dfbproj: Add Compile entries for .fbt, _HMI.fbt
  ├── dfbproj: Add None entries for .cfg, .offline.xml, .opcua.xml
  ├── csproj: Add Compile entries for HMI .cs files
  ├── csproj: Add EmbeddedResource entries for .resx, .xml
  └── Folders.xml: Add folder entry

Composite FB:

/eae-composite-fb --register-only {BlockName} {Namespace}
  │
  └── dfbproj: Add Compile entry for .fbt (IEC61499Type=Composite)

Basic FB:

/eae-basic-fb --register-only {BlockName} {Namespace}
  │
  └── dfbproj: Add Compile entry for .fbt (IEC61499Type=Basic)

Adapter:

/eae-adapter --register-only {BlockName} {Namespace}
  │
  └── dfbproj: Add Compile entry for .adp (IEC61499Type=Adapter)

DataType:

/eae-datatype --register-only {BlockName} {Namespace}
  │
  └── dfbproj: Add Compile entry for .dt (IEC61499Type=DataType)

eae-fork Responsibilities (Steps 1-5)

Step 1: Copy IEC61499 Files

Copy from source library to target:

Source Target
Libraries/{Lib}/Files/{Block}/ {Project}/{Target}/IEC61499/{Block}/

IEC61499 Files to copy:

{Block}.fbt              - Main block definition (XML)
{Block}.cfg              - CAT configuration (links to HMI)
{Block}.doc.xml          - Documentation (optional)
{Block}_HMI.fbt          - HMI interface block
{Block}_CAT.offline.xml  - Offline parameters
{Block}_CAT.opcua.xml    - OPC-UA config
{Block}_HMI.offline.xml  - HMI offline parameters
{Block}_HMI.opcua.xml    - HMI OPC-UA config

Step 2: Decompile & Transform HMI Files (CRITICAL)

HMI files must be DECOMPILED from the source library DLL. Standard Schneider Electric libraries ship only compiled HMI DLLs – no source files exist in the Files/ directory for HMI.

Source Target
Libraries/{Lib}-{Ver}/HMI/{Lib}.HMI.dll (DECOMPILE) {Project}/{Target}/HMI/{Block}/

Decompilation Process:

# Use the decompile_hmi.py script
python scripts/decompile_hmi.py SE.App2CommonProcess AnalogInputBase SE.ScadapackWWW ./output

# Or with hierarchy (multiple blocks)
python scripts/decompile_hmi.py SE.App2CommonProcess AnalogInput SE.ScadapackWWW ./output \
    --forked-blocks AnalogInputBase AnalogInputBaseExt AnalogInput

What the decompilation does:

  1. Locates the HMI DLL in C:\ProgramData\Schneider Electric\Libraries\{Lib}-{Ver}\HMI\
  2. Decompiles using ILSpy CLI (ilspycmd)
  3. Finds symbol/faceplate classes in {Lib}.Symbols.{Block}/ and {Lib}.Faceplates.{Block}/ directories
  4. Splits decompiled classes into EAE format: .cnv.cs (main) + .cnv.Designer.cs (InitializeComponent)
  5. Updates namespaces according to the rules below
  6. Creates .cnv.resx and .cnv.xml files

HMI Files to copy (per symbol/faceplate):

{Block}.def.cs                    - Faceplate accessor definitions
{Block}.event.cs                  - Event argument classes
{Block}.Design.resx               - Design resources

{Block}_fpDefault.cnv.cs          - Faceplate implementation
{Block}_fpDefault.cnv.Designer.cs - Designer-generated code
{Block}_fpDefault.cnv.resx        - Faceplate resources

{Block}_fpParameter.cnv.cs        - Parameter faceplate
{Block}_fpParameter.cnv.Designer.cs
{Block}_fpParameter.cnv.resx

{Block}_fpTrend.cnv.cs            - Trend faceplate
{Block}_fpTrend.cnv.Designer.cs
{Block}_fpTrend.cnv.resx

{Block}_sDefault.cnv.cs           - Default symbol
{Block}_sDefault.cnv.Designer.cs
{Block}_sDefault.cnv.resx
{Block}_sDefault.cnv.xml          - Symbol XML (ONLY for symbols)

{Block}_sVertical.cnv.cs          - Vertical symbol
{Block}_sVertical.cnv.Designer.cs
{Block}_sVertical.cnv.resx
{Block}_sVertical.cnv.xml

{Block}_sDisplayPv.cnv.cs         - Display PV symbol
{Block}_sDisplayPv.cnv.Designer.cs
{Block}_sDisplayPv.cnv.resx
{Block}_sDisplayPv.cnv.xml

{Block}_sInstanceName.cnv.cs      - Instance name symbol
{Block}_sInstanceName.cnv.Designer.cs
{Block}_sInstanceName.cnv.resx
{Block}_sInstanceName.cnv.xml

Important: Faceplates (fp*) do NOT have .cnv.xml files. Symbols (s*) DO have .cnv.xml files.

Step 3: Update Namespace & GUID in .fbt Files

<!-- BEFORE (source) -->
<FBType GUID="422cce07-335e-414d-823c-03c2d1ac0ef6"
        Name="AnalogInput" Namespace="SE.App2CommonProcess">

<!-- AFTER (forked) -->
<FBType GUID="a59ec74d-736e-42ab-a3ff-de74c9003156"
        Name="AnalogInput" Namespace="SE.ScadapackWWW">

Sub-block namespace rules:

Block Type Action
Forked blocks (in hierarchy) Update to target namespace
Original library blocks KEEP original namespace
Adapter interfaces KEEP original namespace
DataTypes KEEP original namespace
<!-- MUST Update (forked blocks) -->
<FB Name="analogInputBaseExt" Type="AnalogInputBaseExt"
    Namespace="SE.ScadapackWWW" />

<!-- MUST KEEP (original library blocks) -->
<FB Name="rawPv" Type="aISignal" Namespace="SE.App2Base" />
<FB Name="control" Type="analogInputLogic" Namespace="SE.App2CommonProcess" />
<Adapter Name="IPv" Type="IAnalog" Namespace="SE.App2Base" />

Step 4: Update .cfg File

The .cfg file links the CAT block to its HMI symbols. Update all paths:

<CAT Name="AnalogInputBase"
     CATFile="AnalogInputBase\AnalogInputBase.fbt"
     SymbolDefFile="..\HMI\AnalogInputBase\AnalogInputBase.def.cs"
     SymbolEventFile="..\HMI\AnalogInputBase\AnalogInputBase.event.cs"
     DesignFile="..\HMI\AnalogInputBase\AnalogInputBase.Design.resx"
     DocFile="AnalogInputBase\AnalogInputBase.doc.xml"
     Folder=".SignalProcessing.AnalogInput">

  <HMIInterface Name="IThis" FileName="AnalogInputBase\AnalogInputBase_HMI.fbt">
    <Symbol Name="fpDefault"
            FileName="..\HMI\AnalogInputBase\AnalogInputBase_fpDefault.cnv.cs"
            IsFaceplate="true">
      <DependentFiles>..\HMI\AnalogInputBase\AnalogInputBase_fpDefault.cnv.Designer.cs</DependentFiles>
      <DependentFiles>..\HMI\AnalogInputBase\AnalogInputBase_fpDefault.cnv.resx</DependentFiles>
    </Symbol>
    <Symbol Name="sDefault"
            FileName="..\HMI\AnalogInputBase\AnalogInputBase_sDefault.cnv.cs">
      <DependentFiles>..\HMI\AnalogInputBase\AnalogInputBase_sDefault.cnv.Designer.cs</DependentFiles>
      <DependentFiles>..\HMI\AnalogInputBase\AnalogInputBase_sDefault.cnv.resx</DependentFiles>
      <DependentFiles>..\HMI\AnalogInputBase\AnalogInputBase_sDefault.cnv.xml</DependentFiles>
    </Symbol>
    <!-- More symbols... -->
  </HMIInterface>

  <Plugin Name="Plugin=OfflineParametrizationEditor;..."
          Project="SE.ScadapackWWW"  <!-- UPDATE THIS -->
          Value="AnalogInputBase\AnalogInputBase_CAT.offline.xml" />
</CAT>

Step 5: Update HMI Namespaces (CRITICAL – Complex Rules)

HMI files contain multiple categories of namespace references that require different handling:

Namespace Reference Categories

Category Pattern Action Example
Block-specific (this block) {Lib}.Symbols.{Block}, {Lib}.Faceplates.{Block} UPDATE to target SE.App2CommonProcess.Symbols.AnalogInputBase → SE.ScadapackWWW.Symbols.AnalogInputBase
Cross-block (forked block) {Lib}.Symbols.{OtherForkedBlock} UPDATE if in forked set When forking hierarchy, update AnalogInputBase refs in AnalogInput
Cross-block (not forked) {Lib}.Symbols.{NonForkedBlock} KEEP original Keep SE.App2CommonProcess.Symbols.Motor if Motor not forked
SupportClasses {Lib}.SupportClasses ALWAYS KEEP SE.App2CommonProcess.SupportClasses – contains shared utilities
Base library SE.App2Base.* ALWAYS KEEP SE.App2Base.Faceplates, SE.App2Base.Symbols, etc.
Framework System.*, NxtControl.* ALWAYS KEEP Framework namespaces never change

Example: Using Directives in sDefault.cs

// From AnalogInputBase/sDefault.cs (decompiled)

// KEEP - Framework namespaces
using System;
using NxtControl.GuiFramework;

// KEEP - Base library (SE.App2Base)
using SE.App2Base.Faceplates;
using SE.App2Base.Graphics;
using SE.App2Base.SupportClasses;
using SE.App2Base.Symbols;

// UPDATE - Block-specific (this block is being forked)
using SE.App2CommonProcess.Faceplates.AnalogInputBase;
// → SE.ScadapackWWW.Faceplates.AnalogInputBase

// KEEP - SupportClasses (shared utilities, NOT block-specific)
using SE.App2CommonProcess.SupportClasses;
// Contains: AnalogInputUnit, MotorAppearance, ValveAppearance, etc.

namespace SE.App2CommonProcess.Symbols.AnalogInputBase;
// → namespace SE.ScadapackWWW.Symbols.AnalogInputBase;

Cross-Block References (Hierarchy Forks)

When forking a hierarchy (e.g., AnalogInput → AnalogInputBaseExt → AnalogInputBase), child blocks embed parent symbols:

// From AnalogInput/sDefault.cs (decompiled)

// UPDATE - Cross-block reference (AnalogInputBase IS in the forked set)
using SE.App2CommonProcess.Symbols.AnalogInputBase;
// → SE.ScadapackWWW.Symbols.AnalogInputBase

// Fully qualified type in field declaration
private SE.App2CommonProcess.Symbols.AnalogInputBase.sDefault analogFunction;
// → SE.ScadapackWWW.Symbols.AnalogInputBase.sDefault

// Instantiation
analogFunction = new SE.App2CommonProcess.Symbols.AnalogInputBase.sDefault();
// → new SE.ScadapackWWW.Symbols.AnalogInputBase.sDefault();

SupportClasses – Why They Must Be Preserved

The SupportClasses namespace contains library-wide utility classes shared across all blocks:

SE.App2CommonProcess.SupportClasses/
├── AnalogInputUnit.cs        # Used by AnalogInput symbols
├── AnalogOutputUnit.cs       # Used by AnalogOutput symbols
├── MotorAppearance.cs        # Used by Motor symbols
├── ValveAppearance.cs        # Used by Valve symbols
├── PIDUnit.cs                # Used by PID symbols
├── BitExtensions.cs          # Utility methods
├── DynamicPropertyGrid.cs    # UI helpers
└── ... (60+ shared classes)

These classes are NOT part of any specific block and should NEVER have their references updated.

Files requiring namespace update:

  • {Block}.def.cs – Multiple namespaces (Faceplates and Symbols)
  • {Block}.event.cs – Multiple namespaces
  • {Block}_*.cnv.cs – Single namespace per file (plus cross-block references)

What eae-fork Does vs What eae-cat Does

eae-fork (File Transformation)

Task Description
Copy IEC61499 files .fbt, .cfg, .offline.xml, .opcua.xml
Copy HMI files .def.cs, .event.cs, .cnv.*, .Design.resx
Update namespaces In .fbt and .cs files
Generate new GUIDs For all forked .fbt files
Update .cfg paths SymbolDefFile, SymbolEventFile, etc.

eae-cat (Project Registration)

Task Description
dfbproj registration 3 ItemGroups (None, Compile, Content)
csproj registration Compile, None, EmbeddedResource items
Folders.xml update CAT folder entries
Validation Verify block appears in library browser

Why this separation?

  • eae-fork handles file content transformation (namespace, GUID)
  • eae-cat handles project structure (registration, dependencies)
  • Each skill has clear, testable responsibilities

Commands

Command Description
/eae-fork {Block} from {Lib} to {Target} Fork a block (asks about depth)
/eae-fork --list {Lib} List blocks in source library
/eae-fork --hierarchy {Block} Fork block with Base/BaseExt chain
/eae-fork --with-deps {Block} Fork block with all dependencies
/eae-fork --dry-run Show what would be forked

Scripts

Detect Block Type (Orchestration)

The detect_block_type.py script examines source library files to determine block type for orchestration.

# Basic usage
python scripts/detect_block_type.py <block_name> <library_name>

# Examples
python scripts/detect_block_type.py AnalogInput SE.App2CommonProcess
# Output: Detected CAT block, sub-skill: eae-cat

python scripts/detect_block_type.py MyLogicFB SE.App2Base
# Output: Detected BASIC block, sub-skill: eae-basic-fb

# JSON output for automation
python scripts/detect_block_type.py AnalogInput SE.App2CommonProcess --json

# Verbose output with evidence
python scripts/detect_block_type.py AnalogInput SE.App2CommonProcess --verbose

Detection Logic:

Block Type Detection Criteria
CAT Has .cfg file with <HMIInterface> elements
Composite .fbt with Format="2.0" and <FBNetwork>, no <BasicFB>
Basic .fbt with <BasicFB> element
Adapter Has .adp file
DataType Has .dt file

Exit Codes:

Code Meaning
0 Success – type detected
1 Block not found
2 Unable to determine type

Pre-flight Check

Validate prerequisites before fork operations to catch errors early.

# Basic usage
python scripts/preflight_check.py <block_name> <source_library> <target_library>

# Examples
python scripts/preflight_check.py AnalogInput SE.App2CommonProcess SE.ScadapackWWW

# Allow overwriting existing target block
python scripts/preflight_check.py --allow-overwrite AnalogInput SE.App2CommonProcess SE.ScadapackWWW

# JSON output for automation
python scripts/preflight_check.py --json Motor SE.App2CommonProcess SE.ScadapackWWW

What it checks:

Check Description
Source library Library exists in standard locations
Source block Block folder/files exist in source
Block type Detects CAT/Composite/Basic/Adapter/DataType
Source files Required files present for block type
Target library Target exists in project
Target conflict Block doesn’t already exist in target
dfbproj exists Target has valid dfbproj file

Exit Codes:

Code Meaning
0 Pre-flight passed, ready to fork
1 Error (missing arguments, etc.)
10 Pre-flight failed (prerequisites not met)
11 Target exists (use –allow-overwrite)

Decompile HMI (Primary Script)

The decompile_hmi.py script extracts full HMI functionality from compiled library DLLs.

# Basic usage: decompile HMI for a single block
python scripts/decompile_hmi.py <source_lib> <block_name> <target_namespace> <output_dir>

# Example: Decompile AnalogInputBase HMI
python scripts/decompile_hmi.py SE.App2CommonProcess AnalogInputBase SE.ScadapackWWW \
    "C:\Project\SE.ScadapackWWW\HMI"

# Hierarchy fork: update cross-references between forked blocks
python scripts/decompile_hmi.py SE.App2CommonProcess AnalogInput SE.ScadapackWWW ./output \
    --forked-blocks AnalogInputBase AnalogInputBaseExt AnalogInput

# Use existing decompiled directory (skip re-decompilation)
python scripts/decompile_hmi.py SE.App2CommonProcess AnalogInput SE.ScadapackWWW ./output \
    --decompiled-dir C:\temp\decompiled-hmi

# Keep decompiled files for inspection
python scripts/decompile_hmi.py SE.App2CommonProcess AnalogInput SE.ScadapackWWW ./output \
    --keep-decompiled

Requirements:

  • ILSpy CLI (ilspycmd) – Install with: dotnet tool install -g ilspycmd
  • Python 3.8+
  • Standard library only (no external dependencies)

Output Structure:

{output_dir}/{BlockName}/
├── {BlockName}.def.cs              # Faceplate/symbol partial class definitions
├── {BlockName}.event.cs            # Event argument classes
├── {BlockName}.Design.resx         # Design resources
├── {BlockName}_fpDefault.cnv.cs    # Faceplate main code
├── {BlockName}_fpDefault.cnv.Designer.cs  # InitializeComponent
├── {BlockName}_fpDefault.cnv.resx  # Faceplate resources
├── {BlockName}_sDefault.cnv.cs     # Symbol main code
├── {BlockName}_sDefault.cnv.Designer.cs   # InitializeComponent
├── {BlockName}_sDefault.cnv.resx   # Symbol resources
├── {BlockName}_sDefault.cnv.xml    # Symbol mapping (symbols only)
└── ... (more symbols/faceplates)

Exit Codes:

Code Meaning
0 Success
1 Error (library not found, decompilation failed, etc.)

Fork Block

# Fork files and update namespaces (Steps 1-4 only)
python scripts/fork_block.py fork AnalogInput SE.App2CommonProcess SE.ScadapackWWW

# Fork with hierarchy
python scripts/fork_block.py fork AnalogInput SE.App2CommonProcess SE.ScadapackWWW --hierarchy

# List blocks
python scripts/fork_block.py list SE.App2CommonProcess

Validate Fork (Files Only)

# Validate namespace updates (NOT dfbproj registration)
python scripts/validate_fork.py SE.ScadapackWWW AnalogInput

Namespace Update Rules

MUST Update (Forked Blocks)

<!-- ROOT ELEMENT: Always update -->
<FBType Name="AnalogInput" Namespace="SE.ScadapackWWW">

<!-- SUB-BLOCKS that are ALSO forked: Update -->
<FB Name="analogInputBaseExt" Type="AnalogInputBaseExt"
    Namespace="SE.ScadapackWWW" />

MUST KEEP (Original Library References)

<!-- Blocks from original libraries: Keep namespace -->
<FB Name="rawPv" Type="aISignal" Namespace="SE.App2Base" />

<!-- Adapter interfaces: Always keep original -->
<Adapter Name="IPv" Type="IAnalog" Namespace="SE.App2Base" />

<!-- DataTypes from original libraries: Keep -->
<VarDeclaration Name="Status" Type="Status" Namespace="SE.App2Base" />

Block Hierarchy Pattern

EAE blocks follow a three-tier hierarchy:

BlockBase          → BlockBaseExt         → Block
(core logic)         (extended features)    (complete)

Example:
AnalogInputBase    → AnalogInputBaseExt   → AnalogInput

Anti-Patterns

Avoid Why Instead
Registering in dfbproj from eae-fork Duplicates eae-cat logic Delegate to eae-cat
Creating HMI stubs instead of decompiling Stubs lack visual functionality Use decompile_hmi.py
Changing original library namespace references Breaks adapters Keep original namespaces
Reusing source GUID Conflicts with original Generate new GUID
Not asking about fork depth Wrong blocks forked Always clarify with user
Updating SupportClasses references Breaks shared utilities Keep SE.{Lib}.SupportClasses

Troubleshooting

Issue Cause Solution
Block not visible in library dfbproj not updated Run eae-cat to register
HMI exceptions Missing or invalid HMI files Re-run decompile_hmi.py
Adapter errors Wrong namespace Keep adapter namespaces as SE.App2Base
Build errors Incomplete hierarchy Use --hierarchy flag
ILSpy not found ilspycmd not installed dotnet tool install -g ilspycmd
Empty symbol output Block not in decompiled DLL Check library path and block name
Missing SupportClasses Namespace incorrectly updated Keep SE.{Lib}.SupportClasses as-is

Files Created by eae-fork

IEC61499 Files

File Changes
{Block}.fbt Namespace, new GUID, sub-block references
{Block}.cfg SymbolDefFile, SymbolEventFile, DesignFile, DocFile, Plugin Project=
{Block}.doc.xml Copy as-is
{Block}_HMI.fbt Namespace update, new GUID
{Block}_CAT.offline.xml Copy as-is
{Block}_CAT.opcua.xml Copy as-is
{Block}_HMI.offline.xml Copy as-is
{Block}_HMI.opcua.xml Copy as-is

HMI Files (All copied and namespace-updated)

File Changes
{Block}.def.cs Namespace update (multiple namespaces)
{Block}.event.cs Namespace update (multiple namespaces)
{Block}.Design.resx Copy as-is
{Block}_fp*.cnv.cs Namespace update
{Block}_fp*.cnv.Designer.cs Namespace update
{Block}_fp*.cnv.resx Copy as-is
{Block}_s*.cnv.cs Namespace update
{Block}_s*.cnv.Designer.cs Namespace update
{Block}_s*.cnv.resx Copy as-is
{Block}_s*.cnv.xml Copy as-is

Files NOT created by eae-fork (handled by eae-cat):

  • {Lib}.dfbproj – Project registration entries
  • {Lib}.HMI.csproj – HMI project registration entries
  • General/Folders.xml – CAT folder entries

HMI Decompilation Deep Dive

Why Decompilation is Required

Standard Schneider Electric libraries (SE.App2Base, SE.App2CommonProcess, etc.) ship with:

  • Source files for IEC61499 blocks (.fbt, .cfg, etc.) in Files/ directory
  • Compiled DLLs for HMI components in HMI/ directory
  • No source files for HMI symbols and faceplates

This means to fork a block with full HMI functionality, we must decompile the HMI DLL.

Decompilation Architecture

┌─────────────────────────────────────────────────────────────────────┐
│ Library: C:\ProgramData\Schneider Electric\Libraries\               │
│          SE.App2CommonProcess-25.0.1.5\                             │
├─────────────────────────────────────────────────────────────────────┤
│ Files/AnalogInputBase/        │ HMI/SE.App2CommonProcess.HMI.dll   │
│ ├── AnalogInputBase.fbt       │ (COMPILED - contains all HMI)      │
│ ├── AnalogInputBase.cfg       │                                     │
│ └── ...                       │                                     │
│ (SOURCE AVAILABLE)            │ (MUST DECOMPILE)                    │
└─────────────────────────────────────────────────────────────────────┘
                                          │
                                          ▼ ILSpy Decompile
┌─────────────────────────────────────────────────────────────────────┐
│ Decompiled Output (temp directory):                                  │
│ ├── SE.App2CommonProcess.Symbols.AnalogInputBase/                   │
│ │   ├── sDefault.cs           ← Combined class file                 │
│ │   ├── sVertical.cs                                                │
│ │   ├── sDisplayPv.cs                                               │
│ │   └── sInstanceName.cs                                            │
│ ├── SE.App2CommonProcess.Faceplates.AnalogInputBase/                │
│ │   ├── fpDefault.cs          ← Combined class file                 │
│ │   ├── fpParameter.cs                                              │
│ │   └── fpTrend.cs                                                  │
│ └── (resource files, mappings, etc.)                                │
└─────────────────────────────────────────────────────────────────────┘
                                          │
                                          ▼ Transform & Split
┌─────────────────────────────────────────────────────────────────────┐
│ EAE-Compatible Output:                                               │
│ {Project}/SE.ScadapackWWW/HMI/AnalogInputBase/                      │
│ ├── AnalogInputBase.def.cs            ← Partial class definitions   │
│ ├── AnalogInputBase.event.cs          ← Event arguments             │
│ ├── AnalogInputBase.Design.resx       ← Design resources            │
│ ├── AnalogInputBase_sDefault.cnv.cs   ← Main code (namespace only)  │
│ ├── AnalogInputBase_sDefault.cnv.Designer.cs  ← InitializeComponent │
│ ├── AnalogInputBase_sDefault.cnv.resx         ← Resources           │
│ ├── AnalogInputBase_sDefault.cnv.xml          ← Symbol mapping      │
│ └── ... (more symbols/faceplates)                                   │
└─────────────────────────────────────────────────────────────────────┘

Class File Splitting

ILSpy produces single-file classes. EAE requires split files:

Decompiled (ILSpy output):

// sDefault.cs - COMBINED
using System;
using NxtControl.GuiFramework;

namespace SE.App2CommonProcess.Symbols.AnalogInputBase;

public class sDefault : SEAppLibHMISymbol
{
    private AIFunctionName aIFunctionName;
    private AnalogValue analogValue;

    public sDefault()
    {
        InitializeComponent();
    }

    private void InitializeComponent()
    {
        this.aIFunctionName = new AIFunctionName();
        this.analogValue = new AnalogValue();
        this.aIFunctionName.Location = new Point(0, 0);
        // ... 100+ lines of visual setup
    }
}

EAE format (split):

// AnalogInputBase_sDefault.cnv.cs - MAIN
using NxtControl.GuiFramework;
using SE.App2Base.Symbols;

namespace SE.ScadapackWWW.Symbols.AnalogInputBase
{
    public partial class sDefault : SEAppLibHMISymbol
    {
        public sDefault()
        {
            InitializeComponent();
        }
    }
}
// AnalogInputBase_sDefault.cnv.Designer.cs - DESIGNER
using System.Drawing;
using System.ComponentModel;
using NxtControl.Drawing;
using NxtControl.GuiFramework;

namespace SE.ScadapackWWW.Symbols.AnalogInputBase
{
    partial class sDefault
    {
        private void InitializeComponent()
        {
            this.aIFunctionName = new AIFunctionName();
            this.analogValue = new AnalogValue();
            // ... full visual setup code
        }
    }
}

ILSpy Installation

# Install ILSpy CLI globally
dotnet tool install -g ilspycmd

# Verify installation
ilspycmd --version

# Common install location (Windows)
~/.dotnet/tools/ilspycmd.exe

Manual Decompilation (for Debugging)

# Decompile entire HMI DLL
ilspycmd "C:\ProgramData\Schneider Electric\Libraries\SE.App2CommonProcess-25.0.1.5\HMI\SE.App2CommonProcess.HMI.dll" -p -o C:\temp\decompiled

# Explore output structure
dir /s C:\temp\decompiled\SE.App2CommonProcess.Symbols.*

Related Skills

Skill Relationship
eae-cat CALL AFTER FORK for CAT registration
eae-composite-fb Call after fork for composite registration
eae-basic-fb Call after fork for basic FB registration
eae-se-process Find source blocks to fork
eae-runtime-base Find sub-block types

Changelog

v7.2.0 (Current)

  • MAJOR ENHANCEMENT: Resume capability for interrupted forks
    • NEW: Session state tracking (.eae-fork-state.json) – Tracks completion progress
    • NEW: load_session_state(), save_session_state(), clear_session_state() – Session management
    • NEW: prompt_resume_or_restart() – Interactive resume/restart decision
    • HOW IT WORKS: Saves state after each successful block, allows resume on interruption
    • BENEFIT: Never lose progress on large hierarchies (9+ blocks)
    • USE CASE: System crashes, Ctrl+C interruptions, file access errors – all recoverable
  • MAJOR ENHANCEMENT: Dependency auto-detection
    • NEW: detect_dependencies.py script – Parses .cfg files to find SubCAT dependencies
    • NEW: detect_block_hierarchy() – Detects Base → BaseExt → Full hierarchies
    • NEW: parse_subcats_from_cfg() – Extracts SubCAT Type references from XML
    • HOW IT WORKS: Recursively analyzes .cfg files, builds complete dependency tree
    • BENEFIT: Automatically suggests all blocks to fork (hierarchy + SubCATs)
    • EXAMPLE: MotorVs → detects 3 hierarchy blocks + 6 SubCATs = 9 total blocks
    • USE CASE: python detect_dependencies.py SE.App2CommonProcess MotorVs --include-hierarchy
  • ENHANCEMENT: Pre-fork validation
    • NEW: validate_pre_fork() – Checks source blocks exist BEFORE manual fork
    • BENEFIT: Prevents wasted time in GUI if blocks don’t exist
    • EXIT CODES: 0=ready, 10=validation failed
  • ENHANCEMENT: Better error messages
    • NEW: Custom exception classes (ForkValidationError, NamespaceUpdateError, RegistrationError)
    • NEW: print_helpful_error() – Contextual error messages with recovery suggestions
    • BENEFIT: Clear guidance on fixing errors instead of cryptic stack traces
    • EXAMPLES: File permission errors → suggests closing editors and removing read-only
  • UX IMPROVEMENTS:
    • Clear session ID display on resume prompts
    • Block mismatch detection (prevents resuming wrong fork)
    • Stale session warnings (>24 hours old)
    • Progress display (X/Y blocks completed)
    • Dependency tree visualization (shows SubCAT relationships)
  • TESTED: Validated on MotorVS fork (detected all 9 blocks correctly)

v7.1.0

  • CRITICAL ENHANCEMENT: Transactional rollback protection
    • NEW: ForkTransaction context manager – Automatic backup/restore on failures
    • BENEFIT: Zero risk of project corruption from partial failures
    • HOW IT WORKS: Backs up all blocks before changes, auto-restores on any error
    • IMPACT: Protects against mid-execution crashes, file access errors, etc.
  • CRITICAL FIX: UTF-8 encoding for international Windows systems
    • FIXED: Unicode character errors (✓, ❌, → caused crashes on CP1252 encoding)
    • SOLUTION: Force UTF-8 output + ASCII-safe symbols ([OK], [ERROR], [SUCCESS])
    • BENEFIT: Works reliably on French, German, Chinese, and all non-English Windows
  • DOCUMENTATION: Removed outdated v5.0 workflow section (was confusing)
  • RELIABILITY: 100% failure-safe with automatic recovery
  • TESTED: Validated on MotorVS fork (9 blocks, successful rollback testing)

v7.0.0

  • MAJOR ENHANCEMENT: Fully automated cross-reference handling
    • NEW: update_cross_block_references() – Updates FB/SubCAT Namespace attributes for blocks in forked set
    • NEW: update_hmi_cross_references() – Updates fully qualified type references in HMI Designer.cs files
    • NEW: detect_source_namespace() – Automatically detects source namespace from .fbt files
    • IMPROVED: Workflow now single-command execution (no manual file editing)
    • IMPROVED: Script infers forked blocks from arguments (no –forked-blocks flag needed)
  • PERFORMANCE: ~15 seconds for hierarchy (vs 3+ minutes manual editing in v6.0)
  • RELIABILITY: 100% systematic updates (no missed references)
  • BENEFITS:
    • ✅ Zero manual file editing required
    • ✅ Automatic cross-block reference updates (IEC61499)
    • ✅ Automatic HMI cross-reference updates (Designer.cs)
    • ✅ Clear progress reporting and summary
    • ✅ Maintains all v6.0 benefits (perfect HMI files, simple workflow)

v6.0.0

  • PARADIGM SHIFT: Hybrid manual/automated workflow
    • Manual fork in EAE GUI → perfect HMI files (generated by EAE’s designer)
    • Automated finalization → namespace updates + GUID generation + registration
  • REMOVED: Decompilation complexity
    • Deleted decompile_hmi.py (no longer needed)
    • Deleted generate_hmi_from_reflection.py (experimental, didn’t work)
    • Removed ILSpy CLI dependency
    • Removed pythonnet dependency
  • NEW: finalize_manual_fork.py script
    • Validates manual fork completed in GUI
    • Updates namespaces in .fbt and .cs files
    • Generates new GUIDs
    • Registers block in dfbproj/csproj
    • ~140 lines vs 500+ lines of decompilation code
  • IMPROVED: Reliability
    • ✅ 100% success rate (EAE-generated HMI files)
    • ✅ Simple & maintainable (namespace updates only)
    • ✅ Fast (~30 seconds per block)
    • ✅ User control (full visibility in GUI)
  • BREAKING CHANGE: Workflow now requires manual fork in EAE GUI first
    • Benefit: Perfect HMI files guaranteed
    • Trade-off: User must perform fork in GUI (30 seconds)
    • Net result: Simpler, more reliable overall workflow

v5.1.0

  • CRITICAL FIX: Complete HMI file generation (SUPERSEDED by v6.0)
    • Modified fork_block.py::extract_decompiled_hmi() to call standalone decompile_hmi.py as subprocess
    • Now creates ALL required HMI files: .cnv.cs, .cnv.Designer.cs, .cnv.resx, .cnv.xml, .Design.resx
    • Eliminated code duplication between fork_block.py and decompile_hmi.py
    • Fixed EAE GUI errors “Unable to load Designer.cs/resx” files
  • CRITICAL FIX: Conditional aspmap.xml registration
    • Modified register_dfbproj.py to check if aspmap.xml exists before adding to dfbproj
    • Only SE.App2CommonProcess blocks have aspmap.xml, SE.App2Base blocks don’t
    • Eliminated “Solution Integrity” warnings for missing aspmap.xml files
  • IMPROVED: Files now match manual fork structure exactly
  • TESTED: All symbols and faceplates open correctly in EAE GUI without errors
  • NOTE: This version attempted to solve HMI generation via decompilation – v6.0 takes simpler approach

v5.0.0

  • MAJOR: Automatic orchestration workflow
    • eae-fork now detects block type and automatically calls appropriate registration sub-skill
    • Users no longer need to manually run registration skills after forking
    • Added detect_block_type.py script for block type detection
  • NEW: Block type detection examines source files to determine:
    • CAT (has .cfg with HMIInterface)
    • Composite (FBNetwork, no BasicFB)
    • Basic (has BasicFB)
    • Adapter (has .adp file)
    • DataType (has .dt file)
  • NEW: Orchestration routing to sub-skills:
    • CAT → /eae-cat --register-only
    • Composite → /eae-composite-fb --register-only
    • Basic → /eae-basic-fb --register-only
    • Adapter → /eae-adapter --register-only
    • DataType → /eae-datatype --register-only
  • IMPROVED: Complete workflow in single command

v4.0.0

  • MAJOR: Full HMI decompilation workflow
    • Added decompile_hmi.py script for extracting HMI from compiled DLLs
    • Uses ILSpy CLI (ilspycmd) for decompilation
    • Splits decompiled classes into EAE format (.cnv.cs + .cnv.Designer.cs)
    • Preserves full visual implementation (not stubs)
  • NEW: Decompilation process:
    1. Locate HMI DLL in library folder
    2. Decompile using ILSpy to temp directory
    3. Find symbol/faceplate classes for the target block
    4. Extract InitializeComponent to Designer file
    5. Update namespaces with proper categorization rules
    6. Generate .resx and .cnv.xml files
  • IMPROVED: Cross-block reference handling for hierarchy forks
    • --forked-blocks flag to specify all blocks being forked
    • Updates cross-references only for blocks in forked set
  • REQUIREMENT: ILSpy CLI (dotnet tool install -g ilspycmd)

v3.1.0

  • CRITICAL FIX: Smart HMI namespace handling with proper reference categorization
    • Block-specific namespaces (Symbols/Faceplates.{Block}): UPDATE if block is forked
    • Cross-block references: UPDATE only if referenced block is in forked set
    • SupportClasses: ALWAYS PRESERVE (library-wide shared utilities)
    • Base library (SE.App2Base.*): ALWAYS PRESERVE
    • Framework (System., NxtControl.): ALWAYS PRESERVE
  • ENHANCED: Cross-block reference handling for hierarchy forks
    • When forking AnalogInput hierarchy, AnalogInput’s reference to AnalogInputBase.sDefault is properly updated
    • Fully qualified type references and instantiations are updated
  • DOCUMENTED: Comprehensive namespace reference categories with examples
  • IMPROVED: Better logging of preserved library references

v3.0.0

  • CRITICAL FIX: HMI files must be COPIED from source, not generated
    • Insight from manual fork analysis in EAE GUI
    • HMI files contain complete implementations with designer code
  • EXPANDED: eae-fork now handles Steps 1-5:
    • Step 1: Copy IEC61499 files
    • Step 2: Copy HMI files (NEW – from source library)
    • Step 3: Update namespaces in .fbt files
    • Step 4: Update .cfg file (expanded: all path attributes)
    • Step 5: Update HMI namespaces in .cs files
  • DOCUMENTED: Complete file list from manual fork analysis
    • IEC61499 files: 8 file types
    • HMI files: Up to 28 files per block (varies by symbols/faceplates)
  • DOCUMENTED: Detailed .cfg file structure with all required attributes
  • CLARIFIED: eae-cat handles project registration only (dfbproj, csproj, Folders.xml)

v2.1.0

  • Clear separation of concerns between eae-fork and eae-cat
  • Removed dfbproj registration from eae-fork (delegated to eae-cat)

v2.0.0

  • Added fork depth user interaction question
  • Added dfbproj registration (now moved to eae-cat)
  • Added HMI file generation (now moved to eae-cat)

v1.0.0

  • Initial release
  • Basic file copy and namespace update