Created by: Mark Brown
Website: markbrown.com
Document Version: 1.0
Generated: 2025-05-27
This document provides complete instructions for implementing license protection in your MultiCharts.NET indicators using hardware fingerprinting.
Based on the system scan performed on 2025-05-27:
Machine Details:
RedQuRAZERRAZERMicrosoft Windows NT 10.0.26100.0Intel64 Family 6 Model 183 Stepping 1, GenuineIntel32AMD64GpACbTztZPghp9/lGpACbTzt9pblo1Zina5IX/fGY6emMTSinEu8lVOiHFeydsYE7kM=Add this class to your MultiCharts.NET indicator:
public class LicenseValidator
{
// Your authorized machine fingerprints
private static readonly string[] AuthorizedFingerprints = {
"GpACbTztZPghp9/l", // RedQu's RAZER machine
// Add more authorized machines here as needed
// "ABCD1234EFGH5678", // Another authorized machine
};
public static bool IsAuthorized()
{
string currentFingerprint = GenerateSimpleFingerprint();
return Array.Exists(AuthorizedFingerprints, fp => fp == currentFingerprint);
}
private static string GenerateSimpleFingerprint()
{
try
{
string combined = System.Environment.MachineName + System.Environment.UserName;
using (SHA256 sha256 = SHA256.Create())
{
byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combined));
return Convert.ToBase64String(bytes).Substring(0, 16);
}
}
catch
{
return "ERROR";
}
}
}Add license check in your indicator constructor:
public class YourProtectedIndicator : IndicatorObject
{
public YourProtectedIndicator(object ctx) : base(ctx)
{
// License check at startup
if (!LicenseValidator.IsAuthorized())
{
throw new UnauthorizedAccessException("Invalid license - Contact developer for authorization");
}
// Your normal initialization code here
}
}Add periodic validation in CalcBar method:
protected override void CalcBar()
{
// Periodic license recheck (every 1000 bars)
if (Bars.CurrentBar % 1000 == 0)
{
if (!LicenseValidator.IsAuthorized())
{
Output.WriteLine("License validation failed - Indicator stopped");
return; // Stop processing
}
}
// Your indicator logic here
}using System;
using System.Security.Cryptography;
using System.Text;
using PowerLanguage.Indicator;
namespace PowerLanguage.Indicator
{
[SameAsSymbol(true)]
public class ProtectedIndicator : IndicatorObject
{
// License validation class
private static class LicenseValidator
{
private static readonly string[] AuthorizedFingerprints = {
"GpACbTztZPghp9/l", // RedQu's RAZER machine
// Add more authorized machines here
};
public static bool IsAuthorized()
{
string currentFingerprint = GenerateSimpleFingerprint();
return Array.Exists(AuthorizedFingerprints, fp => fp == currentFingerprint);
}
private static string GenerateSimpleFingerprint()
{
try
{
string combined = System.Environment.MachineName + System.Environment.UserName;
using (SHA256 sha256 = SHA256.Create())
{
byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combined));
return Convert.ToBase64String(bytes).Substring(0, 16);
}
}
catch
{
return "ERROR";
}
}
}
// Constructor with license check
public ProtectedIndicator(object ctx) : base(ctx)
{
if (!LicenseValidator.IsAuthorized())
{
throw new UnauthorizedAccessException("Invalid license - Contact developer");
}
// Your initialization code here
}
protected override void Create()
{
// Your plot creation code here
}
protected override void CalcBar()
{
// Optional periodic check
if (Bars.CurrentBar % 1000 == 0 && !LicenseValidator.IsAuthorized())
{
Output.WriteLine("License validation failed");
return;
}
// Your indicator logic here
}
}
}To authorize additional machines:
AuthorizedFingerprints arrayExample:
private static readonly string[] AuthorizedFingerprints = {
"GpACbTztZPghp9/l", // RedQu's RAZER machine
"XyZ9AbC123456789", // Customer A's machine
"DeF456GhI987654", // Customer B's machine
};Replace GenerateSimpleFingerprint() with:
private static string GenerateComplexFingerprint()
{
try
{
string combined = System.Environment.MachineName +
System.Environment.UserName +
System.Environment.OSVersion.ToString() +
System.Environment.ProcessorCount.ToString() +
(System.Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER") ?? "");
using (SHA256 sha256 = SHA256.Create())
{
byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combined));
return Convert.ToBase64String(bytes);
}
}
catch
{
return "ERROR";
}
}% 5000 instead of % 1000)When distributing your protected indicator:
When a customer needs authorization:
Document Created by: Mark Brown
Website: markbrown.com
Generated on: 2025-05-27
Your Machine Fingerprint: GpACbTztZPghp9/l
Document Version: 1.0
This license protection system was developed by Mark Brown (markbrown.com) for securing MultiCharts.NET indicators using hardware fingerprinting technology.