im in the process of automating my workflow for indicator development, opening ninjatrader exporting and creating the ob dll is time consuming and i currently have a large batch of indicators to go through and build, is there a command-line way to generate the cs file to go with the .dll ? or do you have something where i can point the .cs file at and it makes the .zip with the cs and xml? i purchased agile and thats all fine i can build the dll files without problem but i either need users to manually install every indicator themselves which is silly or i need to find a way to automate the .zip file, can you advise?
I don’t think there’s a way to do what you’re asking. NT doesn’t have any command line options that I’m aware of (at all). It’s possible to build your indicators in separate projects from the standard custom project and thus create dll’s. But that would require restructuring your code. A one time cost, but probably not insignificant.
Also when you export, the included cs file is only a portion of the actual code file. It only has the using statements and the partial constructor components for the indicator factory class. None of your code is in the exported cs file. Generating this would require some tooling that could extract the correct parts of the file.
The xml files are just some basic version and security info that could all likely be easily generated en-masse via some basic code.
Why can’t you use NT to export all indicators into one .zip file?
CC → Tools → Export → NinjaScript Add-On…
You’d only need to do this once per each release of your indicators.
(The question is: how often do you really create a new release for your customer base?)
Seems like a waste of your time to automate something you’d probably be doing relatively infrequently. Even once a month is not worthy of automation, IMHO.
![]()
i have 300 odd indicators. i assumed a simple command line tool wouldve been normal practice for a production application.
Ah, 300 … that’s a lot.
Are they all sold/provided separately?
If so, yeah, I see your point.
Have you tried anything to automate the mouse and keyboard?
Some of these tools let you record your mouse movements and keyboard presses into a macro and let you replay them. Others are more programming languages, such as AutoHotkey.
Try this search.
Good luck!
Yeah i guess im going to have to do it manually, in this day and age most things can be automated just a bit frustrating that there must be something proprietry about the .zip files.
I compiled and used agile.net to create a ob dll file then even used the .cs and .xml created by exporting but it didnt import so there must be something about the actual dll it generates that differs to the .dll i manually compile and ob with agile.
Perhaps @QuantKey_Bruce can chime in here. I believe he’s an expert in vendor workflows and may know why your dll couldn’t be imported.
maybe im doing something stupid its very possible.
@echo off
setlocal enabledelayedexpansion
:: ============================================
:: BUILD-INDICATOR.cmd
:: Compiles, obfuscates, verifies, and packages NinjaTrader indicators
:: Usage: BUILD-INDICATOR.cmd “C:\path\to\MyIndicator.cs” “url-slug” “1.0.1”
::
:: Prerequisites (must exist in same folder as .cs):
:: - [IndicatorName]_Generated.cs (stub file from Prompt 5)
:: - Info.xml (metadata file from Prompt 5)
:: ============================================
:: Configuration
set “NT8_BIN=C:\Program Files\NinjaTrader 8\bin”
set “NT8_CUSTOM=%USERPROFILE%\Documents\NinjaTrader 8\bin\Custom”
set “DOTNET=C:\Windows\Microsoft.NET\Framework64\v4.0.30319”
set “WPF=%DOTNET%\WPF”
set “AGILE=C:\Program Files (x86)\SecureTeam\AgileDotNet.Console.exe”
set “SEVENZIP=C:\Program Files\7-Zip\7z.exe”
set “CSC=C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\Roslyn\csc.exe”
:: ============================================
:: Parse input
:: ============================================
if “%~1”==“” (
echo ERROR: No input file specified
echo Usage: BUILD-INDICATOR.cmd “C:\path\to\MyIndicator.cs” “url-slug” “1.0.1”
exit /b 1
)
if “%~2”==“” (
echo ERROR: No slug specified
echo Usage: BUILD-INDICATOR.cmd “C:\path\to\MyIndicator.cs” “url-slug” “1.0.1”
exit /b 1
)
set “CSFILE=%~1”
set “SLUG=%~2”
set “VERSION=%~3”
if “%VERSION%”==“” set “VERSION=1.0.1”
set “FOLDER=%~dp1”
set “INDICATOR_NAME=%~n1”
:: File paths
set “DLLFILE=%FOLDER%%INDICATOR_NAME%.dll”
set “STUB_CS=%FOLDER%%INDICATOR_NAME%_Generated.cs”
set “INFO_XML=%FOLDER%Info.xml”
set “PROTECTED_DIR=%FOLDER%protected”
set “PROTECTED_DLL=%PROTECTED_DIR%%INDICATOR_NAME%.dll”
set “ZIPFILE=%FOLDER%%SLUG%-%VERSION%.zip”
echo.
echo ============================================
echo Building: %INDICATOR_NAME%
echo Slug: %SLUG%
echo Version: %VERSION%
echo Output: %ZIPFILE%
echo ============================================
echo.
:: ============================================
:: Step 1: Verify prerequisites
:: ============================================
echo [1/6] Verifying prerequisites …
if not exist “%CSFILE%” (
echo ERROR: Source file not found: %CSFILE%
exit /b 1
)
if not exist “%STUB_CS%” (
echo ERROR: Stub file not found: %STUB_CS%
echo Run Prompt 5 to generate this file first.
exit /b 1
)
if not exist “%INFO_XML%” (
echo ERROR: Info.xml not found: %INFO_XML%
echo Run Prompt 5 to generate this file first.
exit /b 1
)
echo OK
:: ============================================
:: Step 2: Compile .cs to .dll
:: ============================================
echo [2/6] Compiling %INDICATOR_NAME%.cs …
“%CSC%” /target:library /out:“%DLLFILE%” /langversion:latest /nowarn:CS0436,CS0618 ^
/reference:“%NT8_BIN%\NinjaTrader.Core.dll” ^
/reference:“%NT8_BIN%\NinjaTrader.Gui.dll” ^
/reference:“%NT8_BIN%\SharpDX.dll” ^
/reference:“%NT8_BIN%\SharpDX.Direct2D1.dll” ^
/reference:“%NT8_BIN%\Newtonsoft.Json.dll” ^
/reference:“%NT8_CUSTOM%\NinjaTrader.Custom.dll” ^
/reference:“%DOTNET%\System.Net.Http.dll” ^
/reference:“%DOTNET%\System.Windows.Forms.dll” ^
/reference:“%DOTNET%\System.ComponentModel.DataAnnotations.dll” ^
/reference:“%WPF%\PresentationCore.dll” ^
/reference:“%WPF%\PresentationFramework.dll” ^
/reference:“%WPF%\WindowsBase.dll” ^
/reference:“%DOTNET%\System.dll” ^
/reference:“%DOTNET%\System.Core.dll” ^
/reference:“%DOTNET%\System.Xml.dll” ^
/reference:“%DOTNET%\System.Xml.Linq.dll” ^
“%CSFILE%”
if errorlevel 1 (
echo ERROR: Compilation failed
exit /b 1
)
echo OK
:: ============================================
:: Step 3: Obfuscate with Agile.NET
:: ============================================
echo [3/6] Obfuscating with Agile.NET …
if not exist “%PROTECTED_DIR%” mkdir “%PROTECTED_DIR%”
“%AGILE%” /target:“%DLLFILE%” /Obfuscate /SecureStrings /Secure /Out:“%PROTECTED_DIR%”
if errorlevel 1 (
echo ERROR: Obfuscation failed
exit /b 1
)
echo OK
:: ============================================
:: Step 4: Verify obfuscation
:: ============================================
echo [4/6] Verifying obfuscation …
powershell -Command “if (Select-String -Path ‘%PROTECTED_DLL%’ -Pattern ‘chartupgrades’ -Encoding Unicode -Quiet) { exit 1 } else { exit 0 }”
if errorlevel 1 (
echo ERROR: Obfuscation verification FAILED - strings still visible!
exit /b 1
)
echo OK - Strings encrypted
:: ============================================
:: Step 5: Prepare archive files
:: ============================================
echo [5/6] Preparing archive files …
:: Copy stub and info to protected dir for zipping
copy “%STUB_CS%” “%PROTECTED_DIR%%INDICATOR_NAME%.cs” >nul
copy “%INFO_XML%” “%PROTECTED_DIR%\Info.xml” >nul
echo OK
:: ============================================
:: Step 6: Create zip
:: ============================================
echo [6/6] Creating %SLUG%-%VERSION%.zip …
if exist “%ZIPFILE%” del “%ZIPFILE%”
:: Add files to zip (from protected dir so paths are clean)
pushd “%PROTECTED_DIR%”
“%SEVENZIP%” a -tzip -mx=9 “%ZIPFILE%” “%INDICATOR_NAME%.dll” “%INDICATOR_NAME%.cs” “Info.xml” >nul
popd
if errorlevel 1 (
echo ERROR: Zip creation failed
exit /b 1
)
echo OK
:: ============================================
:: Cleanup
:: ============================================
del “%DLLFILE%” 2>nul
del “%PROTECTED_DIR%%INDICATOR_NAME%.dll” 2>nul
del “%PROTECTED_DIR%%INDICATOR_NAME%.cs” 2>nul
del “%PROTECTED_DIR%\Info.xml” 2>nul
rmdir “%PROTECTED_DIR%” 2>nul
:: ============================================
:: Done
:: ============================================
echo.
echo ============================================
echo BUILD COMPLETE
echo.
echo Output: %ZIPFILE%
echo.
echo Contents:
echo - %INDICATOR_NAME%.dll (obfuscated)
echo - %INDICATOR_NAME%.cs (generated stub)
echo - Info.xml
echo.
echo Ready for upload phase
echo ============================================
echo.
exit /b 0
When you are running the obfuscator, it seems you are probably setting Obfuscation=true on the assembly itself? But I don’t believe that’s what the “protected” checkbox does. It doesn’t use secure strings either, which is worth noting.
You may want to look at C:\Program Files\NinjaTrader 8\bin\Custom\Backup\AgileDotNet.cls to better understand what the settings are that NinjaTrader uses by default when you check the protected checkbox. It might be that what you’re doing is more secure yet not compatible with NT8’s import process which does require that some things be visible.
I haven’t run your script but my gut instinct is that you should take a look at AgileDotNet.cls from the factory install of NT8 and match your settings to theirs, then pause and see if that works, and if it does, then go one small step at a time to see how much you can tighten it without breaking the import process. We did a very similar exercise here to methodically determine how many of the Agile.net features we could turn on without breaking anything for several different products, and depending on what all your products do (how much reflection you use, whether they interact and so need to be able to see each other, etc.) you may be able to turn on more or fewer features and still have it function.
Additionally, if it saves you time, you can export one of your indicators as a sample in compiled but not protected form and use the AgileDotNet GUI to protect it, then see if that works, and with the GUI, you can quickly iterate through the different checkboxes and features to see if they work for your application. Don’t just turn everything on - start with NT’s settings (or start with everything off if you want to be truly methodical) and go one small step at a time checking each time to see what works. That way you’ll truly understand which ones are required for a successful import into NT8 in your specific case.
good spotting, i attempted this without /SecureStrings and /Obfuscate same issue, i then ran with /Project:“C:\Program Files\NinjaTrader 8\bin\Custom\Backup\AgileDotNet.cls” still no bueno.
I then went one step further and tried using a unprotected dll to eliminate agile.net from the equasion and it failed aswell so i can only assume theres a dll in the compile process im not adding or privy to?
After doing some digging i found Documents\NinjaTrader 8\bin\Custom\NinjaTrader.Custom.csproj which shows how normally dlls are compiled with everything else so i changed to a dotnet build approach using this csproj as a reference and it worked!
Afterwards i just toyed with agile to get it working and we are done. so for anyone who comes in the future looking for answers:
-
Build using dotnet (not standalone CSC):
dotnet build “%USERPROFILE%\Documents\NinjaTrader 8\bin\Custom\NinjaTrader.Custom.csproj” -c Release -p:Platform=x64 --verbosity minimal -
Apply Agile.NET protection:
“C:\Program Files (x86)\SecureTeam\AgileDotNet.Console.exe” /Target:“YourIndicator.dll” /Secure /Out:“.” -
Key points:
- Copy your .cs source to %USERPROFILE%\Documents\NinjaTrader 8\bin\Custom\Indicators\YourNamespace\ before building
- Output DLL is at %USERPROFILE%\Documents\NinjaTrader 8\bin\Custom\bin\Release\NinjaTrader.Custom.dll
- Rename the protected DLL to your indicator name for packaging
- Clean up obj and bin folders after build to avoid NT compile conflicts
- Package contents (zip):
- YourIndicator.dll (protected)
- YourIndicator.cs (stub file)
- Info.xml with
<Agile>7.0.0.30</Agile>
The critical insight: NinjaTrader compiles ALL indicators into a single NinjaTrader.Custom.dll. Standalone CSC compilation creates a separate assembly that NT’s import process rejects.
You must build via NT’s csproj.
Stub file (YourIndicator.cs):
This is the NinjaTrader-generated accessor code that allows other scripts to call your indicator. It contains partial class definitions in three namespaces:
- NinjaTrader.NinjaScript.Indicators - so other indicators can call it
- NinjaTrader.NinjaScript.MarketAnalyzerColumns - for Market Analyzer
- NinjaTrader.NinjaScript.Strategies - so strategies can call it
Example structure:
namespace NinjaTrader.NinjaScript.Indicators
{
public partial class Indicator
{
public YourNamespace.YourIndicator YourIndicator(param1, param2…)
{
return CacheIndicator<YourNamespace.YourIndicator>(…);
}
}
}
Why such an old version number?
![]()
its the latest version of Agile ?
The version inside the Info.xml file is the NT8 version number that was used to produce the export.
it has ninjatrader and agile versions in it dude..
<NinjaTrader>
<Export>
<Version>8.1.6.3</Version>
<Agile>7.0.0.30</Agile>
</Export>
</NinjaTrader>
Great. I’m glad you got it sorted out!
My bad, I’m still on an older version of NT8 and hadn’t seen that.
Good to know!
![]()