diff --git a/src/TcBlack.sln b/src/TcBlack.sln
index 9f629b8..3d9323c 100644
--- a/src/TcBlack.sln
+++ b/src/TcBlack.sln
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcBlackCoreTests", "TcBlack
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcBlackCore", "TcBlackCore\TcBlackCore.csproj", "{434C7A68-C27F-4F46-977E-2F60441FEB64}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcBlackExtension", "TcBlackExtension\TcBlackExtension.csproj", "{DE482F7D-9E9D-481C-A9B7-871D7ED05212}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -135,64 +137,6 @@ Global
{87DFDA93-482C-4C04-ABF1-50E23F24F85D}.Release|TwinCAT RT (x64).Build.0 = Release|Any CPU
{87DFDA93-482C-4C04-ABF1-50E23F24F85D}.Release|TwinCAT RT (x86).ActiveCfg = Release|Any CPU
{87DFDA93-482C-4C04-ABF1-50E23F24F85D}.Release|TwinCAT RT (x86).Build.0 = Release|Any CPU
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|Any CPU.ActiveCfg = Debug|TwinCAT RT (x64)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|Any CPU.ActiveCfg = Release|TwinCAT RT (x64)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86)
- {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|Any CPU.ActiveCfg = Debug|TwinCAT RT (x64)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|Any CPU.Build.0 = Debug|TwinCAT RT (x64)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|Any CPU.ActiveCfg = Release|TwinCAT RT (x64)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|Any CPU.Build.0 = Release|TwinCAT RT (x64)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86)
- {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|Any CPU.ActiveCfg = Debug|TwinCAT RT (x64)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|Any CPU.Build.0 = Debug|TwinCAT RT (x64)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|Any CPU.ActiveCfg = Release|TwinCAT RT (x64)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|Any CPU.Build.0 = Release|TwinCAT RT (x64)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86)
- {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86)
{D86EFF5A-952E-42BD-AEB4-605F02ED336C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D86EFF5A-952E-42BD-AEB4-605F02ED336C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D86EFF5A-952E-42BD-AEB4-605F02ED336C}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|Any CPU
@@ -233,6 +177,84 @@ Global
{434C7A68-C27F-4F46-977E-2F60441FEB64}.Release|TwinCAT RT (x64).Build.0 = Release|Any CPU
{434C7A68-C27F-4F46-977E-2F60441FEB64}.Release|TwinCAT RT (x86).ActiveCfg = Release|Any CPU
{434C7A68-C27F-4F46-977E-2F60441FEB64}.Release|TwinCAT RT (x86).Build.0 = Release|Any CPU
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|Any CPU.ActiveCfg = Debug|TwinCAT RT (x64)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|Any CPU.ActiveCfg = Release|TwinCAT RT (x64)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86)
+ {0AB6833F-593B-4E68-AC63-B575821ACF23}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|Any CPU.ActiveCfg = Debug|TwinCAT RT (x64)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|Any CPU.Build.0 = Debug|TwinCAT RT (x64)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|Any CPU.ActiveCfg = Release|TwinCAT RT (x64)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|Any CPU.Build.0 = Release|TwinCAT RT (x64)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86)
+ {BDD00A0B-9FFE-4A2C-B504-1A16BFE106B2}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|Any CPU.ActiveCfg = Debug|TwinCAT RT (x64)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|Any CPU.Build.0 = Debug|TwinCAT RT (x64)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|Any CPU.ActiveCfg = Release|TwinCAT RT (x64)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|Any CPU.Build.0 = Release|TwinCAT RT (x64)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86)
+ {7CF85DA4-8F2E-4244-BC74-2C56883E6551}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86)
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|TwinCAT RT (x64).Build.0 = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Debug|TwinCAT RT (x86).Build.0 = Debug|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|TwinCAT OS (ARMT2).Build.0 = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|TwinCAT RT (x64).ActiveCfg = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|TwinCAT RT (x64).Build.0 = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|TwinCAT RT (x86).ActiveCfg = Release|Any CPU
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}.Release|TwinCAT RT (x86).Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/TcBlack/TcDeclaration.cs b/src/TcBlack/TcDeclaration.cs
new file mode 100644
index 0000000..154f948
--- /dev/null
+++ b/src/TcBlack/TcDeclaration.cs
@@ -0,0 +1,58 @@
+namespace TcBlack
+{
+ public struct TcDeclaration
+ {
+ public TcDeclaration(
+ string name,
+ string allocation,
+ string dataType,
+ string initialization,
+ string comment
+ )
+ {
+ Name = name;
+ Allocation = allocation;
+ DataType = dataType;
+ Initialization = initialization;
+ Comment = comment;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null || GetType() != obj.GetType())
+ {
+ return false;
+ }
+
+ var other = (TcDeclaration)obj;
+ return
+ Name == other.Name
+ && Allocation == other.Allocation
+ && DataType == other.DataType
+ && Initialization == other.Initialization
+ && Comment == other.Comment
+ ;
+ }
+
+ public static bool operator==(TcDeclaration obj1, TcDeclaration obj2)
+ {
+ if (obj1 == null)
+ {
+ return obj2 == null;
+ }
+
+ return obj1.Equals(obj2);
+ }
+
+ public static bool operator !=(TcDeclaration obj1, TcDeclaration obj2)
+ {
+ return !(obj1 == obj2);
+ }
+
+ public string Name { get; }
+ public string Allocation { get; }
+ public string DataType { get; }
+ public string Initialization { get; }
+ public string Comment { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/TcBlackCore/TcBlackCore.csproj b/src/TcBlackCore/TcBlackCore.csproj
index c04fd67..4897cf5 100644
--- a/src/TcBlackCore/TcBlackCore.csproj
+++ b/src/TcBlackCore/TcBlackCore.csproj
@@ -30,6 +30,12 @@
prompt
4
+
+ true
+
+
+ TcBlackCoreSign.pfx
+
@@ -54,5 +60,8 @@
+
+
+
\ No newline at end of file
diff --git a/src/TcBlackExtension/FormatStructuredText.cs b/src/TcBlackExtension/FormatStructuredText.cs
new file mode 100644
index 0000000..caebef5
--- /dev/null
+++ b/src/TcBlackExtension/FormatStructuredText.cs
@@ -0,0 +1,113 @@
+using System;
+using System.ComponentModel.Design;
+using EnvDTE;
+using Microsoft.VisualStudio.Shell;
+using Task = System.Threading.Tasks.Task;
+using TcBlackCore;
+using TCatSysManagerLib;
+
+namespace TcBlackExtension2
+{
+ ///
+ /// Command handler
+ ///
+ internal sealed class FormatStructuredText
+ {
+ ///
+ /// Command ID.
+ ///
+ public const int CommandId = 0x0100;
+
+ ///
+ /// Command menu group (command set GUID).
+ ///
+ public static readonly Guid CommandSet =
+ new Guid("2331eac3-39e5-4347-b678-a146d49c0a07");
+
+ ///
+ /// VS Package that provides this command, not null.
+ ///
+ private readonly AsyncPackage package;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Adds our command handlers for menu (commands must exist in the command table file)
+ ///
+ /// Owner package, not null.
+ /// Command service to add command to, not null.
+ private FormatStructuredText(AsyncPackage package, OleMenuCommandService commandService)
+ {
+ this.package = package ?? throw new ArgumentNullException(nameof(package));
+ commandService = commandService ??
+ throw new ArgumentNullException(nameof(commandService));
+
+ var menuCommandID = new CommandID(CommandSet, CommandId);
+ var menuItem = new MenuCommand(Execute, menuCommandID);
+ commandService.AddCommand(menuItem);
+ }
+
+ ///
+ /// Gets the instance of the command.
+ ///
+ public static FormatStructuredText Instance
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the service provider from the owner package.
+ ///
+ private IAsyncServiceProvider ServiceProvider
+ {
+ get
+ {
+ return this.package;
+ }
+ }
+
+ ///
+ /// Initializes the singleton instance of the command.
+ ///
+ /// Owner package, not null.
+ public static async Task InitializeAsync(AsyncPackage package)
+ {
+ // Switch to the main thread - the call to AddCommand in FormatStructuredText's constructor requires
+ // the UI thread.
+ await ThreadHelper.JoinableTaskFactory
+ .SwitchToMainThreadAsync(package.DisposalToken);
+
+ OleMenuCommandService commandService = await package.GetServiceAsync(
+ (typeof(IMenuCommandService))) as OleMenuCommandService;
+ Instance = new FormatStructuredText(package, commandService);
+ }
+
+ ///
+ /// This function is the callback used to execute the command when the menu item is clicked.
+ /// See the constructor to see how the menu item is associated with this function using
+ /// OleMenuCommandService service and MenuCommand class.
+ ///
+ /// Event sender.
+ /// Event args.
+ private void Execute(object sender, EventArgs e)
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+
+ DTE dte = Package.GetGlobalService(typeof(DTE)) as DTE;
+ if (dte.ActiveWindow.ProjectItem.Object is ITcPlcDeclaration)
+ {
+ ITcPlcDeclaration declaration =
+ (ITcPlcDeclaration)dte.ActiveWindow.ProjectItem.Object;
+
+ uint indents = 0;
+ string text = declaration.DeclarationText;
+ Global.indentation = text.Contains("\t") ? "\t" : " ";
+ Global.lineEnding = "\r\n";
+ string formatedCode = new CompositeCode(text)
+ .Tokenize()
+ .Format(ref indents);
+ declaration.DeclarationText = formatedCode;
+ }
+ }
+ }
+}
diff --git a/src/TcBlackExtension/FormatStructuredTextPackage.cs b/src/TcBlackExtension/FormatStructuredTextPackage.cs
new file mode 100644
index 0000000..8836112
--- /dev/null
+++ b/src/TcBlackExtension/FormatStructuredTextPackage.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Microsoft.VisualStudio.Shell;
+using Task = System.Threading.Tasks.Task;
+
+namespace TcBlackExtension2
+{
+ ///
+ /// This is the class that implements the package exposed by this assembly.
+ ///
+ ///
+ ///
+ /// The minimum requirement for a class to be considered a valid package for Visual Studio
+ /// is to implement the IVsPackage interface and register itself with the shell.
+ /// This package uses the helper classes defined inside the Managed Package Framework (MPF)
+ /// to do it: it derives from the Package class that provides the implementation of the
+ /// IVsPackage interface and uses the registration attributes defined in the framework to
+ /// register itself and its components with the shell. These attributes tell the pkgdef creation
+ /// utility what data to put into .pkgdef file.
+ ///
+ ///
+ /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file.
+ ///
+ ///
+ [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
+ [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About
+ [ProvideMenuResource("Menus.ctmenu", 1)]
+ [Guid(FormatStructuredTextPackage.PackageGuidString)]
+ [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")]
+ public sealed class FormatStructuredTextPackage : AsyncPackage
+ {
+ ///
+ /// FormatStructuredTextPackage GUID string.
+ ///
+ public const string PackageGuidString = "f0d2f155-5908-42b2-a15d-9e628c6f43b4";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public FormatStructuredTextPackage()
+ {
+ // Inside this method you can place any initialization code that does not require
+ // any Visual Studio service because at this point the package object is created but
+ // not sited yet inside Visual Studio environment. The place to do all the other
+ // initialization is the Initialize method.
+ }
+
+ #region Package Members
+
+ ///
+ /// Initialization of the package; this method is called right after the package is sited, so this is the place
+ /// where you can put all the initialization code that rely on services provided by VisualStudio.
+ ///
+ /// A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down.
+ /// A provider for progress updates.
+ /// A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method.
+ protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress)
+ {
+ // When initialized asynchronously, the current thread may be a background thread at this point.
+ // Do any initialization that requires the UI thread after switching to the UI thread.
+ await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
+ await FormatStructuredText.InitializeAsync(this);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/TcBlackExtension/FormatStructuredTextPackage.vsct b/src/TcBlackExtension/FormatStructuredTextPackage.vsct
new file mode 100644
index 0000000..18fa199
--- /dev/null
+++ b/src/TcBlackExtension/FormatStructuredTextPackage.vsct
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/TcBlackExtension/Properties/AssemblyInfo.cs b/src/TcBlackExtension/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1153f7a
--- /dev/null
+++ b/src/TcBlackExtension/Properties/AssemblyInfo.cs
@@ -0,0 +1,32 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TcBlackExtension")]
+[assembly: AssemblyDescription("Visual Studio Extension to Format TwinCAT Structured Text")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TcBlackExtension")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.1.0.0")]
diff --git a/src/TcBlackExtension/TcBlackExtension.csproj b/src/TcBlackExtension/TcBlackExtension.csproj
new file mode 100644
index 0000000..e27ff33
--- /dev/null
+++ b/src/TcBlackExtension/TcBlackExtension.csproj
@@ -0,0 +1,215 @@
+
+
+
+
+ 15.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+ true
+
+
+
+ false
+
+
+
+
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ {DE482F7D-9E9D-481C-A9B7-871D7ED05212}
+ Library
+ Properties
+ TcBlackExtension
+ TcBlackExtension
+ v4.6.1
+ true
+ true
+ true
+ true
+ true
+ false
+ Program
+ $(DevEnvDir)devenv.exe
+ /rootsuffix Exp
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+ Menus.ctmenu
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+ False
+
+
+ ..\packages\Microsoft.VisualStudio.CoreUtility.15.0.26228\lib\net45\Microsoft.VisualStudio.CoreUtility.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Imaging.15.0.26228\lib\net45\Microsoft.VisualStudio.Imaging.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.14.3.25408\lib\net20\Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.dll
+ True
+
+
+ ..\packages\Microsoft.VisualStudio.OLE.Interop.7.10.6071\lib\Microsoft.VisualStudio.OLE.Interop.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.15.0.15.0.26228\lib\Microsoft.VisualStudio.Shell.15.0.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.Framework.15.0.26228\lib\net45\Microsoft.VisualStudio.Shell.Framework.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.Interop.7.10.6071\lib\Microsoft.VisualStudio.Shell.Interop.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.Interop.10.0.10.0.30319\lib\Microsoft.VisualStudio.Shell.Interop.10.0.dll
+ True
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.Interop.11.0.11.0.61030\lib\Microsoft.VisualStudio.Shell.Interop.11.0.dll
+ True
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.Interop.12.0.12.0.30110\lib\Microsoft.VisualStudio.Shell.Interop.12.0.dll
+ True
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime.14.3.25407\lib\Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime.dll
+ True
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.Interop.8.0.8.0.50727\lib\Microsoft.VisualStudio.Shell.Interop.8.0.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Shell.Interop.9.0.9.0.30729\lib\Microsoft.VisualStudio.Shell.Interop.9.0.dll
+
+
+ ..\packages\Microsoft.VisualStudio.TextManager.Interop.7.10.6070\lib\Microsoft.VisualStudio.TextManager.Interop.dll
+
+
+ ..\packages\Microsoft.VisualStudio.TextManager.Interop.8.0.8.0.50727\lib\Microsoft.VisualStudio.TextManager.Interop.8.0.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Threading.15.0.240\lib\net45\Microsoft.VisualStudio.Threading.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Utilities.15.0.26228\lib\net46\Microsoft.VisualStudio.Utilities.dll
+
+
+ ..\packages\Microsoft.VisualStudio.Validation.15.0.82\lib\net45\Microsoft.VisualStudio.Validation.dll
+
+
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ VSPackage
+
+
+
+
+ {434c7a68-c27f-4f46-977e-2f60441feb64}
+ TcBlackCore
+
+
+
+
+
+
+
+ {3C49D6C3-93DC-11D0-B162-00A0248C244B}
+ 3
+ 3
+ 0
+ primary
+ False
+ True
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TcBlackExtension/VSPackage.resx b/src/TcBlackExtension/VSPackage.resx
new file mode 100644
index 0000000..64d18ff
--- /dev/null
+++ b/src/TcBlackExtension/VSPackage.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ FormatStructuredText Extension
+
+
+ FormatStructuredText Visual Studio Extension Detailed Info
+
+
\ No newline at end of file
diff --git a/src/TcBlackExtension/packages.config b/src/TcBlackExtension/packages.config
new file mode 100644
index 0000000..422d9ae
--- /dev/null
+++ b/src/TcBlackExtension/packages.config
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TcBlackExtension/source.extension.vsixmanifest b/src/TcBlackExtension/source.extension.vsixmanifest
new file mode 100644
index 0000000..8cb7608
--- /dev/null
+++ b/src/TcBlackExtension/source.extension.vsixmanifest
@@ -0,0 +1,21 @@
+
+
+
+
+ TcBlackExtension
+ Empty VSIX Project.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/TcBlackExtension/stylesheet.css b/src/TcBlackExtension/stylesheet.css
new file mode 100644
index 0000000..d5e9c71
--- /dev/null
+++ b/src/TcBlackExtension/stylesheet.css
@@ -0,0 +1,129 @@
+body {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ color: #1E1E1E;
+ font-size: 13px;
+ font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+ line-height: 1.45;
+ word-wrap: break-word;
+}
+
+/* General & 'Reset' Stuff */
+
+
+.container {
+ width: 980px;
+ margin: 0 auto;
+}
+
+section {
+ display: block;
+ margin: 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ margin: 0;
+}
+
+/* Header,
+ header - container
+ h1 - project name
+ h2 - project description
+*/
+
+#header {
+ color: #FFF;
+ background: #68217a;
+ position:relative;
+}
+#hangcloud {
+ width: 190px;
+ height: 160px;
+ background: url("../images/bannerart03.png");
+ position: absolute;
+ top: 0;
+ right: -30px;
+}
+h1, h2 {
+ font-family: "Segoe UI Light", "Segoe UI", Helvetica, Arial, sans-serif;
+ line-height: 1;
+ margin: 0 18px;
+ padding: 0;
+}
+#header h1 {
+ font-size: 3.4em;
+ padding-top: 18px;
+ font-weight: normal;
+ margin-left: 15px;
+}
+
+#header h2 {
+ font-size: 1.5em;
+ margin-top: 10px;
+ padding-bottom: 18px;
+ font-weight: normal;
+}
+
+
+#main_content {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+}
+
+
+h1, h2, h3, h4, h5, h6 {
+ font-weight: bolder;
+}
+
+#main_content h1 {
+ font-size: 1.8em;
+ margin-top: 34px;
+}
+
+ #main_content h1:first-child {
+ margin-top: 30px;
+ }
+
+#main_content h2 {
+ font-size: 1.4em;
+ font-weight: bold;
+}
+p, ul {
+ margin: 11px 18px;
+}
+
+#main_content a {
+ color: #06C;
+ text-decoration: none;
+}
+ul {
+ margin-top: 13px;
+ margin-left: 18px;
+ padding-left: 0;
+}
+ ul li {
+ margin-left: 18px;
+ padding-left: 0;
+ }
+#lpanel {
+ width: 620px;
+ float: left;
+}
+#rpanel ul {
+ list-style-type: none;
+ width: 300px;
+}
+ #rpanel ul li {
+ line-height: 1.8em;
+ }
+#rpanel {
+ background: #e7e7e7;
+ width: 360px;
+ float: right;
+}
+
+#rpanel div {
+ width: 300px;
+}