Using EPANet Toolkit in C#

Update 24/02/2014: there is new EPANET C# class here.

Thanks to abcprogramlama (site in Turkish) I finally got the EPANet Toolkit working in C# (C-sharp). First the EpanetCSharpLibrary should be added to the solution (click to expend or download here):

using System;
using System.Runtime.InteropServices;

namespace EpanetCSharpLibrary
{
 public static class Epanet
 {
 public const string EPANETDLL = "epanet2.dll";
 public const int EN_ELEVATION = 0;
 public const int EN_BASEDEMAND = 1;
 public const int EN_PATTERN = 2;
 public const int EN_EMITTER = 3;
 public const int EN_INITQUAL = 4;
 public const int EN_SOURCEQUAL = 5;
 public const int EN_SOURCEPAT = 6;
 public const int EN_SOURCETYPE = 7;
 public const int EN_TANKLEVEL = 8;
 public const int EN_DEMAND = 9;
 public const int EN_HEAD = 10;
 public const int EN_PRESSURE = 11;
 public const int EN_QUALITY = 12;
 public const int EN_SOURCEMASS = 13;
 public const int EN_INITVOLUME = 14;
 public const int EN_MIXMODEL = 15;
 public const int EN_MIXZONEVOL = 16;
 public const int EN_TANKDIAM = 17;
 public const int EN_MINVOLUME = 18;
 public const int EN_VOLCURVE = 19;
 public const int EN_MINLEVEL = 20;
 public const int EN_MAXLEVEL = 21;
 public const int EN_MIXFRACTION = 22;
 public const int EN_TANK_KBULK = 23;
 public const int EN_DIAMETER = 0;
 public const int EN_LENGTH = 1;
 public const int EN_ROUGHNESS = 2;
 public const int EN_MINORLOSS = 3;
 public const int EN_INITSTATUS = 4;
 public const int EN_INITSETTING = 5;
 public const int EN_KBULK = 6;
 public const int EN_KWALL = 7;
 public const int EN_FLOW = 8;
 public const int EN_VELOCITY = 9;
 public const int EN_HEADLOSS = 10;
 public const int EN_STATUS = 11;
 public const int EN_SETTING = 12;
 public const int EN_ENERGY = 13;
 public const int EN_DURATION = 0;
 public const int EN_HYDSTEP = 1;
 public const int EN_QUALSTEP = 2;
 public const int EN_PATTERNSTEP = 3;
 public const int EN_PATTERNSTART = 4;
 public const int EN_REPORTSTEP = 5;
 public const int EN_REPORTSTART = 6;
 public const int EN_RULESTEP = 7;
 public const int EN_STATISTIC = 8;
 public const int EN_PERIODS = 9;
 public const int EN_NODECOUNT = 0;
 public const int EN_TANKCOUNT = 1;
 public const int EN_LINKCOUNT = 2;
 public const int EN_PATCOUNT = 3;
 public const int EN_CURVECOUNT = 4;
 public const int EN_CONTROLCOUNT = 5;
 public const int EN_JUNCTION = 0;
 public const int EN_RESERVOIR = 1;
 public const int EN_TANK = 2;
 public const int EN_CVPIPE = 0;
 public const int EN_PIPE = 1;
 public const int EN_PUMP = 2;
 public const int EN_PRV = 3;
 public const int EN_PSV = 4;
 public const int EN_PBV = 5;
 public const int EN_FCV = 6;
 public const int EN_TCV = 7;
 public const int EN_GPV = 8;
 public const int EN_NONE = 0;
 public const int EN_CHEM = 1;
 public const int EN_AGE = 2;
 public const int EN_TRACE = 3;
 public const int EN_CONCEN = 0;
 public const int EN_MASS = 1;
 public const int EN_SETPOINT = 2;
 public const int EN_FLOWPACED = 3;
 public const int EN_CFS = 0;
 public const int EN_GPM = 1;
 public const int EN_MGD = 2;
 public const int EN_IMGD = 3;
 public const int EN_AFD = 4;
 public const int EN_LPS = 5;
 public const int EN_LPM = 6;
 public const int EN_MLD = 7;
 public const int EN_CMH = 8;
 public const int EN_CMD = 9;
 public const int EN_TRIALS = 0;
 public const int EN_ACCURACY = 1;
 public const int EN_TOLERANCE = 2;
 public const int EN_EMITEXPON = 3;
 public const int EN_DEMANDMULT = 4;
 public const int EN_LOWLEVEL = 0;
 public const int EN_HILEVEL = 1;
 public const int EN_TIMER = 2;
 public const int EN_TIMEOFDAY = 3;
 public const int EN_AVERAGE = 1;
 public const int EN_MINIMUM = 2;
 public const int EN_MAXIMUM = 3;
 public const int EN_RANGE = 4;
 public const int EN_MIX1 = 0;
 public const int EN_MIX2 = 1;
 public const int EN_FIFO = 2;
 public const int EN_LIFO = 3;
 public const int EN_NOSAVE = 0;
 public const int EN_SAVE = 1;
 public const int EN_INITFLOW = 10;

#region Epanet Imports
 public delegate void UserSuppliedFunction(string param0);
 /// <summary>
 /// Runs a complete EPANET simulation.
 /// </summary>
 /// <param name="f1">name of the input file</param>
 /// <param name="f2">name of an output report file</param>
 /// <param name="f3">name of an output output file </param>
 /// <param name="vfunc">pointer to a user-supplied function which accepts a character string as its argument</param>
 /// <returns>Returns an error code.</returns>
 [DllImport(EPANETDLL, EntryPoint = "ENepanet")]
 public static extern int ENepanet(string f1, string f2, string f3, UserSuppliedFunction vfunc);

/// <summary>
 /// Opens the Toolkit to analyze a particular distribution system.
 /// </summary>
 /// <param name="param0">name of the input file</param>
 /// <param name="param1">name of an output report file</param>
 /// <param name="param2">name of an output output file</param>
 /// <returns>Returns an error code.</returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENopen")]
 public static extern int ENopen(string param0, string param1, string param2);

/// <summary>
 /// Writes all current network input data to a file using the format of an EPANET input file.
 /// </summary>
 /// <param name="filename">name of the file where data is saved.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsaveinpfile")]
 public static extern int ENsaveinpfile(string filename);

/// <summary>
 /// Closes down the Toolkit system (including all files being processed).
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENclose")]
 public static extern int ENclose();

/// <summary>
 /// Runs a complete hydraulic simulation with results
 /// for all time periods written to the binary Hydraulics file.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsolveH")]
 public static extern int ENsolveH();

/// <summary>
 /// Transfers results of a hydraulic simulation from the binary Hydraulics file to the binary Output file,
 /// where results are only reported at uniform reporting intervals.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsaveH")]
 public static extern int ENsaveH();

/// <summary>
 /// Opens the hydraulics analysis system.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENopenH")]
 public static extern int ENopenH();

/// <summary>
 /// Initializes storage tank levels, link status and settings,
 /// and the simulation clock time prior to running a hydraulic analysis.
 /// </summary>
 /// <param name="saveflag">0-1 flag indicating if hydraulic results will be saved to the hydraulics file.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENinitH")]
 public static extern int ENinitH(int saveflag);

/// <summary>
 /// Runs a single period hydraulic analysis, retrieving the current simulation clock time t.
 /// </summary>
 /// <param name="t">current simulation clock time in seconds.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENrunH")]
 public static extern int ENrunH(ref long t);

/// <summary>
 /// Determines the length of time until the next hydraulic event occurs in an extended period simulation.
 /// </summary>
 /// <param name="tstep">time (in seconds) until next hydraulic event occurs or
 /// 0 if at the end of the simulation period.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENnextH")]
 public static extern int ENnextH(ref long tstep);

/// <summary>
 /// Closes the hydraulic analysis system, freeing all allocated memory.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENcloseH")]
 public static extern int ENcloseH();

/// <summary>
 /// Saves the current contents of the binary hydraulics file to a file.
 /// </summary>
 /// <param name="fname">name of the file where the hydraulics results should be saved.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsavehydfile")]
 public static extern int ENsavehydfile(string fname);

/// <summary>
 /// Uses the contents of the specified file as the current binary hydraulics file.
 /// </summary>
 /// <param name="fname">name of the file containing hydraulic analysis results for the current network.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENusehydfile")]
 public static extern int ENusehydfile(string fname);

/// <summary>
 /// Runs a complete water quality simulation with results at uniform reporting
 /// intervals written to EPANET's binary Output file.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsolveQ")]
 public static extern int ENsolveQ();

/// <summary>
 /// Opens the water quality analysis system.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENopenQ")]
 public static extern int ENopenQ();

/// <summary>
 /// Initializes water quality and the simulation clock time prior to running a water quality analysis.
 /// </summary>
 /// <param name="saveflag">0-1 flag indicating if analysis results
 /// should be saved to EPANET's binary output file at uniform reporting periods.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = " ENinitQ")]
 public static extern int ENinitQ(int saveflag);

/// <summary>
 /// Makes available the hydraulic and water quality results that occur
 /// at the start of the next time period of a water quality analysis,
 /// where the start of the period is returned in t.
 /// </summary>
 /// <param name="t">current simulation clock time in seconds.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENrunQ")]
 public static extern int ENrunQ(ref long t);

/// <summary>
 /// Advances the water quality simulation to the start of the next hydraulic time period.
 /// </summary>
 /// <param name="tstep">time (in seconds) until next hydraulic event occurs or
 /// 0 if at the end of the simulation period.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENnextQ")]
 public static extern int ENnextQ(ref long tstep);

/// <summary>
 /// Advances the water quality simulation one water quality time step.
 /// The time remaining in the overall simulation is returned in tleft.
 /// </summary>
 /// <param name="tleft">seconds remaining in the overall simulation duration.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENstepQ")]
 public static extern int ENstepQ(ref long tleft);

/// <summary>
 /// Closes the water quality analysis system, freeing all allocated memory.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENcloseQ")]
 public static extern int ENcloseQ();

/// <summary>
 /// Writes a line of text to the EPANET report file.
 /// </summary>
 /// <param name="line">text to be written to file.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENwriteline")]
 public static extern int ENwriteline(string line);

/// <summary>
 /// Writes a formatted text report on simulation results to the Report file.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENreport")]
 public static extern int ENreport();

/// <summary>
 /// Clears any report formatting commands that either appeared in the
 /// [REPORT] section of the EPANET Input file or were issued with the ENsetreport function.
 /// </summary>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENresetreport")]
 public static extern int ENresetreport();

/// <summary>
 /// Issues a report formatting command.
 /// Formatting commands are the same as used in the
 /// [REPORT] section of the EPANET Input file.
 /// </summary>
 /// <param name="command">text of a report formatting command.</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetreport")]
 public static extern int ENsetreport(string command);

/// <summary>
 /// Retrieves the parameters of a simple control statement.
 /// The index of the control is specified in cindex and
 /// the remaining arguments return the control's parameters.
 /// </summary>
 /// <param name="cindex">control statement index</param>
 /// <param name="ctype">control type code</param>
 /// <param name="lindex">index of link being controlled</param>
 /// <param name="setting">value of the control setting</param>
 /// <param name="nindex">index of controlling node</param>
 /// <param name="level">value of controlling water level or
 /// pressure for level controls or of time of control action (in seconds)
 /// for time-based controls</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetcontrol")]
 public static extern int ENgetcontrol(int cindex, ref int ctype, ref int lindex,
 ref float setting, ref int nindex, ref float level);

/// <summary>
 /// Retrieves the number of network components of a specified type.
 /// </summary>
 /// <param name="countcode">component code</param>
 /// <param name="count">number of countcode components in the network</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetcount")]
 public static extern int ENgetcount(int countcode, ref int count);

/// <summary>
 /// Retrieves the value of a particular analysis option.
 /// </summary>
 /// <param name="optioncode">an option code</param>
 /// <param name="value">an option value</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetoption")]
 public static extern int ENgetoption(int optioncode, ref float value);

/// <summary>
 /// Retrieves the value of a specific analysis time parameter.
 /// </summary>
 /// <param name="paramcode">time parameter code</param>
 /// <param name="timevalue">value of time parameter in seconds</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgettimeparam")]
 public static extern int ENgettimeparam(int paramcode, ref int timevalue);

/// <summary>
 /// Retrieves a code number indicating the units used to express all flow rates.
 /// </summary>
 /// <param name="unitscode">value of a flow units code number</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetflowunits")]
 public static extern int ENgetflowunits(ref int unitscode);

/// <summary>
 /// Retrieves the index of a particular time pattern.
 /// </summary>
 /// <param name="id">pattern ID label</param>
 /// <param name="index">pattern index</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetpatternindex")]
 public static extern int ENgetpatternindex(string id, ref int index);

/// <summary>
 /// Retrieves the ID label of a particular time pattern.
 /// </summary>
 /// <param name="index">pattern index</param>
 /// <param name="id">ID label of pattern</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetpatternid")]
 public static extern int ENgetpatternid(int index, string id);

/// <summary>
 /// Retrieves the number of time periods in a specific time pattern.
 /// </summary>
 /// <param name="index">pattern index</param>
 /// <param name="len">number of time periods in the pattern</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetpatternlen")]
 public static extern int ENgetpatternlen(int index, ref int len);

/// <summary>
 /// Retrieves the multiplier factor for a specific time period in a time pattern.
 /// </summary>
 /// <param name="index">time pattern index</param>
 /// <param name="period">period within time pattern</param>
 /// <param name="value">multiplier factor for the period</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetpatternvalue")]
 public static extern int ENgetpatternvalue(int index, int period, ref float value);

/// <summary>
 /// Retrieves the type of water quality analysis called for.
 /// </summary>
 /// <param name="qualcode">water quality analysis code</param>
 /// <param name="tracenode">index of node traced in a source tracing analysis</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetqualtype")]
 public static extern int ENgetqualtype(ref int qualcode, ref int tracenode);

/// <summary>
 /// Retrieves the text of the message associated with a particular error or warning code.
 /// </summary>
 /// <param name="errcode">error or warning code</param>
 /// <param name="errmsg">text of the error or warning message for errcode</param>
 /// <param name="nchar">maximum number of characters that errmsg can hold</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgeterror")]
 public static extern int ENgeterror(int errcode, string errmsg, int nchar);

/// <summary>
 /// Retrieves the index of a node with a specified ID.
 /// </summary>
 /// <param name="id">node ID label</param>
 /// <param name="index">node index</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetnodeindex")]
 public static extern int ENgetnodeindex(string id, ref int index);

/// <summary>
 /// Retrieves the ID label of a node with a specified index
 /// </summary>
 /// <param name="index">node index</param>
 /// <param name="id">ID label of node</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetnodeid")]
 public static extern int ENgetnodeid(int index, string id);

/// <summary>
 /// Retrieves the node-type code for a specific node.
 /// </summary>
 /// <param name="index">node index</param>
 /// <param name="typecode">node-type code</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetnodetype")]
 public static extern int ENgetnodetype(int index, ref int typecode);

/// <summary>
 /// Retrieves the value of a specific link parameter.
 /// </summary>
 /// <param name="index">node index</param>
 /// <param name="paramcode">parameter code</param>
 /// <param name="value">parameter value</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetnodevalue")]
 public static extern int ENgetnodevalue(int index, int paramcode, ref float value);

/// <summary>
 /// Retrieves the index of a link with a specified ID.
 /// </summary>
 /// <param name="id">link ID label</param>
 /// <param name="index">link index</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetlinkindex")]
 public static extern int ENgetlinkindex(string id, ref int index);

/// <summary>
 /// Retrieves the ID label of a link with a specified index.
 /// </summary>
 /// <param name="index">link index</param>
 /// <param name="id">ID label of link</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetlinkid")]
 public static extern int ENgetlinkid(int index, string id);

/// <summary>
 /// Retrieves the link-type code for a specific link.
 /// </summary>
 /// <param name="index">link index</param>
 /// <param name="typecode">link-type code</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetlinktype")]
 public static extern int ENgetlinktype(int index, ref int typecode);

/// <summary>
 /// Retrieves the indexes of the end nodes of a specified link.
 /// </summary>
 /// <param name="index">link index</param>
 /// <param name="fromnode">index of node at start of link</param>
 /// <param name="tonode">index of node at end of link</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetlinknodes")]
 public static extern int ENgetlinknodes(int index, ref int fromnode, ref int tonode);

/// <summary>
 /// Retrieves the value of a specific link parameter.
 /// </summary>
 /// <param name="index">link index</param>
 /// <param name="paramcode">parameter code</param>
 /// <param name="value">parameter value</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetlinkvalue")]
 public static extern int ENgetlinkvalue(int index, int paramcode, ref float value);

/// <summary>
 /// Retrieves version.
 /// </summary>
 /// <param name="version">Version</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENgetversion")]
 public static extern int ENgetversion(ref int version);

/// <summary>
 /// Sets the parameters of a simple control statement.
 /// </summary>
 /// <param name="cindex">control statement index</param>
 /// <param name="ctype">control type code</param>
 /// <param name="lindex">index of link being controlled</param>
 /// <param name="setting">value of the control setting</param>
 /// <param name="nindex">index of controlling node</param>
 /// <param name="level">value of controlling water level or pressure
 /// for level controls or of time of control action (in seconds)
 /// for time-based controls</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetcontrol")]
 public static extern int ENsetcontrol(int cindex, int ctype, int lindex,
 float setting, int nindex, float level);

/// <summary>
 /// Sets the value of a parameter for a specific node.
 /// </summary>
 /// <param name="index">node index</param>
 /// <param name="paramcode">parameter code</param>
 /// <param name="value">parameter value</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetnodevalue")]
 public static extern int ENsetnodevalue(int index, int paramcode, float value);

/// <summary>
 /// Sets the value of a parameter for a specific link.
 /// </summary>
 /// <param name="index">link index</param>
 /// <param name="paramcode">parameter code</param>
 /// <param name="value">parameter value</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetlinkvalue")]
 public static extern int ENsetlinkvalue(int index, int paramcode, float value);

/// <summary>
 /// Adds a new time pattern to the network.
 /// </summary>
 /// <param name="id">ID label of pattern</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENaddpattern")]
 public static extern int ENaddpattern(string id);

/// <summary>
 /// Sets all of the multiplier factors for a specific time pattern.
 /// </summary>
 /// <param name="index">time pattern index</param>
 /// <param name="factors">multiplier factors for the entire pattern</param>
 /// <param name="nfactors">number of factors in the pattern</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetpattern")]
 public static extern int ENsetpattern(int index, float[] factors, int nfactors);

/// <summary>
 /// Sets the multiplier factor for a specific period within a time pattern.
 /// </summary>
 /// <param name="index">time pattern index</param>
 /// <param name="period">period within time pattern</param>
 /// <param name="value">multiplier factor for the period</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetpatternvalue")]
 public static extern int ENsetpatternvalue(int index, int period, float value);

/// <summary>
 /// Sets the value of a time parameter.
 /// </summary>
 /// <param name="paramcode">time parameter code</param>
 /// <param name="timevalue">value of time parameter in seconds</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsettimeparam")]
 public static extern int ENsettimeparam(int paramcode, long timevalue);

/// <summary>
 /// Sets the value of a particular analysis option.
 /// </summary>
 /// <param name="optioncode">an option code</param>
 /// <param name="value">an option value</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetoption")]
 public static extern int ENsetoption(int optioncode, float value);

/// <summary>
 /// Sets the level of hydraulic status reporting.
 /// </summary>
 /// <param name="statuslevel">level of status reporting</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetstatusreport")]
 public static extern int ENsetstatusreport(int statuslevel);

/// <summary>
 /// Sets the type of water quality analysis called for.
 /// </summary>
 /// <param name="qualcode">water quality analysis code</param>
 /// <param name="chemname">name of the chemical being analyzed</param>
 /// <param name="chemunits">units that the chemical is measured in</param>
 /// <param name="tracenode">ID of node traced in a source tracing analysis</param>
 /// <returns></returns>
 [DllImportAttribute(EPANETDLL, EntryPoint = "ENsetqualtype")]
 public static extern int ENsetqualtype(int qualcode, string chemname, string chemunits, string tracenode);

#endregion
 }
}

Now the EPANet class can be used:

public static void Main()
    {
        int i = 0;
        int v = 0;
        string f1="", f2="", f3="";
        //get the DLL's version
        i = Epanet.ENgetversion(ref v);

        f1 = "Net1.inp";
        f2 = "out.txt";
        f3 = "rep.txt";
        //run an EPANet simulation
        i = Epanet.ENepanet(f1, f2, f3, null);
     }

Turns out to be simple…

Tagged with: ,
14 comments on “Using EPANet Toolkit in C#
  1. Lucas Vasconcelos says:

    Thank you!

  2. Kyle Lancaster says:

    Thanks for this, saved me a lot of effort! Just one thing that drove me mad, the funtion ENinitH’s entrypoint has a space before its name ” ENinitH” and this causes it to fail. I spent ages trying to figure it out until I noticed that little space. It just needs to be removed.

  3. Nhu DO says:

    Thank you very much. It’s really useful and works well. Just one thing, I cannot retrieve nodeID and linkID using ENgetnodeID and ENgetlinkID. Could you please let me know how to get the these IDs? thank you very much
    The code I wrote like this:
    int getNodeType = 0;
    string getnodeID=””;
    for (int i = 1; i <= nodeCount; i++)
    {
    nodeNumber[i] = new EPANode();
    Epanet.ENgetnodetype(i, ref getNodeType);
    nodeNumber[i].Type = getNodeType;

    Epanet.ENgetnodeid(i, getnodeID);
    nodeNumber[i].ID = getnodeID;
    dt.Rows.Add(nodeNumber[i].ID, nodeNumber[i].Type); // add to table

  4. Vyacheslav Shevelyov says:

    Marshaling of strings in ENgetnodeid is incorrect. Strings in C# are immutable, so no chance to get modifiet strings from unmanaged code. There are number of ways to workaround this – using StringBuilder, IntPtr or byte[] types. The most simpliest way – using StringBuilder class:

    In Epanet class replace:

    public const int MAXID = 31;

    [DllImport(EPANETDLL, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
    public static extern ErrorCode ENgetnodeid(
    int index,
    [MarshalAs(UnmanagedType.LPStr), Out]StringBuilder id);

    Use this function in the following way:


    public static string GetId(int index) {
    StringBuilder s = new StringBuilder(Epanet.MAXID);
    int err = Epanet.ENgetnodeid(index, s);
    if (err != 0) throw new Exception("Epanet exception #" + err);
    return s.ToString();
    }

    The same way works for links.
    By the way there are also many errors in Epanet class. Using C# long data type in functions ENrunH, ENnextH, etc is incorrect for classic epanet2.dll, compiled with Microsoft VC++ compiler.

    long data type in VC C/C++ (64bit, and 32 bit) = int data type in C# (both a 32bit signet integers). Passing them by ref is questionable, seems it shold be out.

    Epanet constants is better to group in Enums to limit acceptable values and give for developers hint, which parameters are valid.

    Hope, it helps. Good luck!

  5. Q.zhang says:

    Thank you very much. It’s really useful and works well.

  6. Annadatha says:

    Hi Elad,

    I am beginner and I have small question. Can I add/remove lines under control section like following section in INP file. Can you kindly point me function related to.

    [CONTROLS]
    LINK 1006 Closed At Time 0.000000
    LINK 1007 Closed At Time 0.000000

    Thank you in advance ,

    Annadatha.

    • Hi Annadatha – you can edit a simple control by the ENsetcontrol function. You can’t add a control but you can remove one:
      “To remove a control on a particular link, set the lindex parameter to 0. Values for the other parameters in the function will be ignored.”

  7. Annadatha says:

    Thank you for your quick reply, i really appreciate your help.

    Regards,

    Annadatha

  8. Shamsuzzaman says:

    Hello ELad,
    Thanks for such nice post which make our first step easy to run EPANet dll to get output file for simulation. But I am in trouble to get it running from my ARCMap Addin (C#.NetAPI). The same source for dll function calling is working in a console application but when I do the same calling from ArcMap Addin button click, it returns error 305. Do you have any clue regarding this?

    Regards,
    Shamsuzzaman

    • Error 305 means “Cannot open hydraulics file” but I don’t know what might be wrong in your setup.

      • Shekh Shamsuzzaman says:

        Thanks for your reply. I also found the same in the error code description. I also tried with independent executable invoking from ArcMap Addin button,but no luck. Is there any single resource dependency between EPANet and ARCMap, which might causes to stop creating/ accessing Hydraulic file.

        Regards,
        Shamsuzzaman

      • ali says:

        Hi,i want to use toolkit with epanet version 2 pls help me to carryout the programming procedure

  9. Eyal Price says:

    Hi,

    The toolkit worked great in C# using WIN8.1 and visual studio 2012.

    After updating the system to ‘Windows 10’ the ENopen commend stopped working, returning error “302”.

    Solution – define the character set to ANSI as follows..
    [DllImportAttribute(EPANETDLL, EntryPoint = “ENopen”, CharSet = CharSet.Ansi)]
    public static extern int ENopen(string param0, string param1, string param2);

    Hope this helps, I wasted a few good days on this…

    Regards,
    Eyal

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.