Any body know C#?

 

i want my mt4 program communicate with C# codes in different kinds of computers,X86 and 64bits

so i decide to try Named Pipe,a solution without any DLL

here's my mql4 code:

#include <Files\FilePipe.mqh>

CFilePipe ExtPipe;

int OnInit()
{
//--- create timer
   EventSetTimer(60);
   
   bool bfirst=true;
   while(!IsStopped())
   {
      if(ExtPipe.Open("\\\\.\\pipe\\My.Pipe.Server",FILE_READ|FILE_WRITE|FILE_BIN)!=INVALID_HANDLE)
         break;
      if(bfirst)
      {
         bfirst=false;
         Print("Client: waiting for pipe server");
      }
      Sleep(250);
   }
   
   if(IsStopped())
      return(INIT_FAILED);
   
   Print("Client: pipe opened");
   
   //--- send welcome message
   if(!ExtPipe.WriteString(__FILE__+" on MQL4 build "+IntegerToString(__MQL4BUILD__)))
   {
      Print("Client: sending welcome message failed");
      return(INIT_FAILED);
   }
   Print("Welcome message sended");
   //--- read data from server
   Sleep(1000);
   string str;
   int    value=0;

   Print("Trying to recv");
   if(!ExtPipe.ReadString(str))
   {
      Print("Client: reading string failed");
      return(INIT_FAILED);
   }
   
   Print("Server: \"",str,"\" received");
//---
   return(INIT_SUCCEEDED);
}

 copy from example code

send welcome info to server and wait one sec,waiting server messages.

and my C# code:

 

public static NamedPipeServerStream pipeServer = new NamedPipeServerStream("My.Pipe.Server", PipeDirection.InOut);

        static void Main(string[] args)
        {
            Console.WriteLine("Named pipe server stream object created");
            Console.WriteLine("Waiting for client connection...:");

            Thread thRead = new Thread(new ThreadStart(OnConnected));
            thRead.Start();
        }

        private static void OnConnected()
        {
            
            pipeServer.WaitForConnection();
            while (true)
            {
                try
                {
                    pipeServer.WaitForPipeDrain();

                    Console.WriteLine("Client connected");


                    byte[] byteRec;
                    byteRec = new byte[256];

                    pipeServer.Read(byteRec, 0, 256);

                    List<byte> listWeNeed = new List<byte>();
                    foreach (byte b in byteRec)
                    {
                        if (b != '\0')
                        {
                            listWeNeed.Add(b);
                        }
                    }

                    byte[] byteFinally = listWeNeed.ToArray();

                    string strReaded = Encoding.UTF8.GetString(byteFinally);


                    if (strReaded.Length > 2)
                    {
                        Console.WriteLine(strReaded);
                        //Send some message to mt4

                        if (pipeServer.CanWrite)
                        {
                            byte[] write = Encoding.UTF8.GetBytes("42");

                            pipeServer.Write(write, 0, write.Length);
                            pipeServer.Flush();

                            Console.WriteLine("Sended");
                        }
                    }
                }
                catch (IOException e)
                {
                    Console.WriteLine("ERROR {0}", e.Message);
                }
            }
        }
 

the mt4 shows the welcome message sended,and it is true:

the c# side:

 

the c# received "PipeTest.mq4 on MQL4 build 553" which mt4 sended.

but when i order C# to send a message by the code

 

pipeServer.Write(write, 0, write.Length);
pipeServer.Flush();

it does not work.

pipeServer.Write method always doesn't work.

 

Do anybody know WHY?

 

Thanks a lot. 

 

Hi, I do have similar troubles with the Metatrader Named Pipe :(

I wrote a little PowerShell Pipeserver - PowerShell should be related:

# is the comment sign like // in Metatrader
$BaseName = "testpipe"
$Enc = [System.Text.Encoding]::UTF8 # ASCII # 
$Buf = new-object byte[] 4096


function ReadMsg ($r, $e, $b) {
    try {
        #$r
        #$e
        $nTry=2
        $got = ""
        $Loops = 0
        Write-Host "start ReadMsg.."
        do {
            # Read what data is available
            $foundmore = $false
            do {
                #$r
                try {
                    $read = $r.Read($b, 0, $b.Length)
                    Write-Host "READ: $read  Result: $($read.Result)"
                    if($read -gt 0) {
                        $foundmore = $true
                        #$got += $e.GetString($b, 0, $read)
                        #$got += [char]$($b | where{$_ -gt 0})
                        foreach ($x in $b) { 
                            if ($x -gt 0){$got += [char]$x; Write-Host "$x => $got" }
                            #else { Write-Host "$b"}
                        }
                        $nTry = -1
                        Write-Host "rdMsg: rd:$read, $got" 
                    }
                } catch { $foundMore = $false; $read = 0; }
            } while($read -gt 0)
            if ($nTry -gt 0) {Start-Sleep -m 5; $nTry--;}
        } while($foundmore -or $nTry -gt 0)
    }
    finally { 
        return $got 
    }
}


function rdPipe ($r, $e, $b) {
    $ret = ""
    $n = 0
    Do {
      $n++
      $b = $r.Read()
      if ($b -gt 0 ) {
          $c = [char]$b #
          $ret += $c
          Write-Host "rdMsg $n: $ret" 
      }
    } while( $b -gt 0 -and $c -ne $EOS )
    if ($ret -ne "" ) { Write-Host "FINAL b $b,  n: $n, ret: $ret" }
    return $ret
}


$pipeDir  = [System.IO.Pipes.PipeDirection]::InOut
$pipeMsg  = [System.IO.Pipes.PipeTransmissionMode]::Message
$pipeOpti = [System.IO.Pipes.PipeOptions]::Asynchronous
$pipe = New-Object system.IO.Pipes.NamedPipeServerStream( $pipeName, $pipeDir, 1, $pipeMsg, $pipeOpti )
if ( !$pipe.IsConnected ) { $pipe.WaitForConnection() }
echo "Connected Pipe: $pipeName"
$pw = new-object System.IO.StreamWriter $pipe
$pw.AutoFlush = $true
$pr = new-object System.IO.StreamReader $pipe

$mSec = 100
while ( $pipe.IsConnected ) {
    $got = rdPipe $pr $sw $Enc $Buf "P:S" # ($read, $wrt, $enc, $buf, $direction) ReadMsg
    #$got = rdPipe $pipe $sw $Enc $Buf "P:S" # ($read, $wrt, $enc, $buf, $direction) ReadMsg
    #$got = ReadMsg $pr $sw $Enc $Buf "P:S" # ($read, $wrt, $enc, $buf, $direction) ReadMsg
    
    if ( $got -ne "" ) {
        echo "P:S^^ $got"
        if ( $got -match "_EXIT_" ) { break }
        else {
            $found = $got -match "Sleep_mSec:(\d+)"
            if ($found) { 
                $mSec = $MATCHES[1] 
                echo "chg Sleeping to $mSec mSec"
            }
        }
    }
    Start-Sleep -m $mSec    
}
if ( $pipe.IsConnected ) {
    $pr.Dispose()
    $pw.Dispose()
    $pipe.Dispose()
    $pipe.Close()
}
return

My welcome-message is just "Hi, I am your client :)". But either I don't receive it: the buffer $b is always 0 or with rdPipe-Function I read the message but the server is blocked it cant leave the loop Do {..} while() until the MT4-script closes the socket.

I have no idea what to do ?? I tried to change between ANSI and UNICODE on MT4-side and ASCII and UTF8 in the PS-script no change - anybody here with an enlightening idea?

I really would appreciate it.

Thanks in advance,

Gooly

 

C# has the same problem - I guess - as PowerShell. In the c++ PipeServer it is defined to read only a specific number of bytes but neither C# nor PowerShell provides this.

Both can read the stream and will hang unless the socket is closed by the client.

 

i found a way to communicate between MT4 and C#

 

i create a file in \MQL4\Files Folder,and i use FILE_SHARE_READ|FILE_SHARE_WRITE to make this file can be share by other programs.

in C# side,i just write messages to this file,and MQL4 read.

 

NamePipe is also a kind of file sharing method.so i made it by myself. 

 
gooly:

C# has the same problem - I guess - as PowerShell. In the c++ PipeServer it is defined to read only a specific number of bytes but neither C# nor PowerShell provides this.

Both can read the stream and will hang unless the socket is closed by the client.


i wrote such C# codes to find the file path

 

string strAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

StringBuilder sbTerminalPath = new StringBuilder(strAppDataPath);
sbTerminalPath.Append(@"\MetaQuotes\Terminal");

string strTerminalPath = sbTerminalPath.ToString();

var SubDirectories = Directory.GetDirectories(strTerminalPath).ToList<string>();

foreach (string strDir in SubDirectories)
{
    StringBuilder sbFileDir = new StringBuilder(strDir);
    sbFileDir.Append(@"\MQL4\Files");

    string strFileDir = sbFileDir.ToString();
    if (Directory.Exists(strFileDir))
    {
       MessageBox.Show(strFileDir);

       StringBuilder sbNewsFile = new StringBuilder(strFileDir);
       sbNewsFile.Append(@"\News.txt");

       string strNewsFile = sbNewsFile.ToString();
       if (!File.Exists(strNewsFile))
          File.Create(strNewsFile);
       //strNewsFile is the path we need
    }
}
 

You can use socket programming to connect.....C# Socket Programming

Lee 

Reason: