GlobalAccessSoftware icon

SmesaMmfIpc.cs (Memory Mapped Data Sharing and secondary instances invoked.

GlobalAccessSoftware | PRO | 07/04/22 02:39:28 PM UTC | 0 ⭐ | 1461 👁️ | Never ⏰ | []
C# |

11.74 KB

|

None

|

0 👍

/

0 👎

 
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// SmesaMmfIpc.cs from SmesaNewTab.cs
// v2.6.1.34 Features Memory Mapped file
// form of Inter-Process-Communications.
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// v2.6.0.32 15-Feb-2018 -JpE-
// v2.6.1.32 20-Feb-2018 0151 Threading.
// v3.0.0.36 28-Feb-2018 0420 MyApp WPF.
// v3.0.1.37 01-Mar-2018 Reverted Hybrid
// v3.1.1.39 08-Mar-2018 Awesome and
// Inspiring! Args passed while running!
// v3.1.3.41 19-Mar-2018 2331 Final Adj!
// v3.1.3.43 20-Mar-2018 PrefClick Code.
// v3.3.5.48 21-Apr-18 Integrated w/PB+
// v4.3.5.49 22-Apr-2018 Integrated.
// v4.4.5.53 14-May Bring to Front mods.
// v4.7.0.71 19-Sep About Colors.
// v4.7.0.72 21-Sep-2018 RC
// v4.8.1.79 11-Oct Peruse & Polish.
// v4.8.2.80 15-Oct B2F Mechanism
// v4.8.2.81 23-Oct Mapper2 interfaced
// v4.8.3.85 09-Nov-2018 Favorites Mods.
// v4.9.4.90 27-Nov-2018 ReadRemovals() and
// GetSelectedIndex() integration completed.
// NOTE: See calls to GetSelectedIndex();
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Security.Permissions;
using System.IO.MemoryMappedFiles;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
 
// Custom NameSpace & Class Library (.dll)
using MyCustomLibrary;
 
// Aliases
using MCD = MyCustomLibrary.Dialogs;
using SMS = MyEditor.Properties.Settings;
using SMR = MyEditor.Properties.Resources;
using SNM = MyCustomLibrary.SafeNativeMethods;
 
namespace MyEditor
{
  public partial class Smesa
  {
#region Server side IPC MsgN Mods v4.8.2.81.G03
 
    /// <summary> if (byte 8190 was flipped
    /// to 1) then bring Editor to front.
    /// I correctly assumed that
    /// 0 is same as null in byte files.
    /// SO, I will call B2F if 1 and rewrite
    /// a zero. If 0 is found return back!
    /// If something else found, from 2-255,
    /// then that's future growth.
    /// v4.8.2.81.G02 : 2018-Oct-23
    /// Purposely Designed to leave many uses
    /// for other msgs to Smesa from abroad
    /// as reuses of the same Watcher
    /// Event/Delegate & !Handler.
    /// </summary>
    /// <param name="length"></param>
    private int CheckForMsgN(long length)
    {
      Mx2.WaitOne();
      var file = Mapped;
      var args = new object[]
      { file, SMS.Default.EditorSize,
        SMS.Default.EditorOffset1 -2,
        // See Note Above about  ^ this.
        length, true, Path
          .GetFileNameWithoutExtension(
            file), false };
      var bites = MemoryMapper
        .ReverseReadBytes(args);
      if (bites.Count == 0)
      { Mx2.ReleaseMutex();
        return 4; }
      if (bites.Count == 1)
      { if ( bites[0] == 0)
        { Mx2.ReleaseMutex();
          return 3; }
        if ( bites[0] == 1)
        { if (TabControl.InvokeRequired)
            Invoke(new Invoker3(B2F));
          else B2F();
          //  ^ Bring M.E. to Front. Then
          // Reset v bites to 0. (aka NULL)
          args[3] = new Collection<byte> {0};
          if (!MemoryMapper
            .ReverseWriteBytes(args))
          { MessageBox.Show(SMR.MsgN);
            Mx2.ReleaseMutex();
            return 2; } }
        if (bites[0] > 1) PbSignal(bites[0]);
      } else BatchRead(bites);
      Mx2.ReleaseMutex(); // NOTE: 
      return 1;
    }
 
    // todo future <byte> msgs to Smesa from abroad.
    #region Future Mods
 
    /* Don't forget that you're going to want
     * to Zero out any other bites used, or NOT.
     * Some may become resident as things evolve.
     * v4.8.2.81 23-Oct-2018
     */
 
    private static void PbSignal(byte p)
    {
      if (p == 2) DoThis();
      if (p == 3) DoThat();
      // etc, etc.
    }
 
    private static void DoThat()
    {
      const string x = "Doing that!";
      MessageBox.Show(x);
 
      // expansion ready
    }
 
    private static void DoThis()
    {
      const string x = "Doing this!";
      MessageBox.Show(x);
 
      // expansion ready
    }
 
    private static void
      BatchRead(IList<byte> result)
    {
      const string x = "Batch Read!";
      MessageBox.Show(
        string.Format(
          x + "\n\ndefault = {0}\n\n" +
          "Count is {1}", result[0],
          result.Count));
      // extreme expansion ready
    }
    #endregion Future Mods using MsgN & IPC
 
#endregion IPC MsgN Mods v4.8.2.81.G03
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region Server-Side MMF-IPC Handling
 
    // Inter-Process-Communications (IPC) with
    // Memory Mapped File (MMF) & File Watcher.
    // Smesa is Owner & 1st Instance Server-Side
    // Code MmfClientSideWrite is Client for 2nd
    // Instances of MyEditor. (Now in MCT2)
 
 
    /// <summary>
    /// Only ran, once at launch, and
    /// whenever a msg comes in from abroad.
    /// This creates _mmf, Delegate, Eventhandler
    /// & a Reader for it. 2nd instances just
    /// never see this Server-Side code period.
    /// </summary>
    /// <param name="read"></param>
    [ComVisible(false)]
    private void MmfServerSide(bool read = false)
    {
      if (Watcher != null)
        Watcher.EnableRaisingEvents = false;
      var temp = MmfManage(read);
      // NOTE: Clean Exit if not a Mail Run.
      if (temp.Count < 1) // v MsgN Hook v48281
      {
        if (read && CheckForMsgN(1) > 2)
          CheckForRemovals(); // <===<< v49386
      }
      else ServerSideMsgReceived(temp);
      // Mail Received ^ acting on it!
      if (Watcher != null) Watcher
        .EnableRaisingEvents = true;
    }
 
    // FOR RELEASE TESTING & DEBUGGING PRINTBLASTER
    private static void SetPaths(string mapped)
    {
      var pb  = BlasterPath =
        WriteShared.AppRoot + SMR.PrintApp;
      var dir = string.IsNullOrEmpty(pb)
        || !File.Exists(pb)
          ? Path.GetDirectoryName(mapped)
          : Path.GetDirectoryName(BlasterPath);
      EditorPath = dir + SMR.EdApp;
      var docs = MyToolbox.GetDocFolder;
      var file = docs + SMR.PathMe;
      File.WriteAllText(file, EditorPath);
      File.SetLastAccessTime(
        file, DateTime.Now);
      var path = docs + SMR.PathEd;
      var maps = dir + "\\" +
        Path.GetFileName(mapped);
      File.WriteAllText(path, maps);
      File.SetLastAccessTime(
        path, DateTime.Now);
      // v4.8.2.80
      dir = Path.GetDirectoryName(mapped);
      var me = dir + SMR.ME;
      File.WriteAllText(me, dir);
    }
 
    private static void LogOut()
    {
      var dir = Path.GetDirectoryName(Mapped);
      var log = dir + SMR.ME;
      if (File.Exists(log)) File.Delete(log);
    }
 
    /// <summary> Args passed in from 2nd Instance!
    /// Acts on Msg Passed from 2nd Instance client.
    /// Awesome and inspiring mods! (Rev3.4)
    /// </summary>
    /// <param name="temp"></param>
    private void ServerSideMsgReceived(
      ICollection<string> temp)
    {
      if (TabControl.InvokeRequired)
      { // If Called From Worker Thread
        Invoke(new Invoker1(TabPrompt));
        temp.Add(Convert.ToString(_tab));
        _myContext.Post(MultiSelect, temp);
        Invoke(new Invoker3(B2F)); }
      else // also handles UI thread (test) calls.
      { temp.Add(Convert.ToString(
        TabPrompt(TabControl.SelectedIndex)));
        MultiSelect(temp);
        B2F(); } }
 
    /// <summary> This has 2b seperate for
    /// Invokers (as above) re-written for
    /// SafeNativeCode Class: Must be static.
    /// v4.4.5.53 15-May-2018
    /// </summary>
    private static void B2F()
    {
      SNM.B2F(Process
        .GetCurrentProcess()
          .MainWindowHandle);
    }
 
    private static Collection<string>
      MmfManage(bool read)
    {
      var size = SMS.Default.EditorSize;
      var temp = new Collection<string>();
      using (var t =
        MemoryMappedFile.CreateFromFile(
          Mapped, FileMode.OpenOrCreate,
          Path.GetFileNameWithoutExtension(
          Mapped), size))
      { if (read)
        { // 1st instance Gets Msg from
          // 2nd instance OR other Apps.
          #region Read Mail
 
          var view   = SMS.Default.EditorView1;
          var offset = SMS.Default.EditorOffset1;
          using (var reader = t.CreateViewAccessor(
            offset, view, MemoryMappedFileAccess.ReadWrite))
          {
            // Assessor itself is now Offset.
            var position = 0;
            while (position <= view)
            {
              var strl = reader.ReadUInt16(position);
              //  ^^^^ = This next byte-array's length.
              if (strl < 1) break; // No More Are Used.
              var buff = new byte[strl];
              reader.ReadArray(
                position += 2, buff, 0, strl);
              position += strl;
              var str = Encoding.UTF32.GetString(buff);
              if (string.IsNullOrEmpty(str)) break;
              temp.Add(str);
            } // Remember how many bytes were used...
            var used = position; // <-= Speed Enhancement!
            // Mail Read, Now Shred only the bytes used.
            position = 0;
            // REM: ^ Accessor itself is now offset.
            while (position <= used // was <
              // stops at end ^^^^ of current msg...
              && position <= view) //<-= or file.
            {
              // then zeros v out used bytes for next write.
              reader.Write(position, (ushort) 0);
              position += 2;
            }
          }
          #endregion Reader
        }
      }
      return temp;
    }
 
    /* Only seen by the 1st Instance of our App. */
    private void WaitForProcess2()
    {
      if (InvokeRequired)
        Invoke(new Invoker1(WaitCursor));
      else // Display v Spinning Blue Donut!
        Cursor = Cursors.WaitCursor;
      List<Process> pros;
      var p = Process.GetCurrentProcess();
      do { p.WaitForExit(250);
        pros = Process.GetProcessesByName(
          Process.GetCurrentProcess()
            .ProcessName).ToList();
      } while (pros.Count > 1);
      if (InvokeRequired)
        Invoke(new Invoker1(ArrowCursor));
      else Cursor = Cursors.Arrow;
    }
 
    private void ArrowCursor()
    {
      Cursor = Cursors.Arrow;
    }
 
    private void WaitCursor()
    {
      Cursor = Cursors.WaitCursor;
    }
#endregion Server-Side MMF-IPC
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region Server-Side MMF Watcher, Event & Handler
 
    /* Only seen by the 1st Instance of our App. */
 
    private void MmfChangedEventHandler(
      object sender, EventArgs e)
    {
      if (!SMS.Default.MultiTab) return;
      // It's a Mail Run, brb!
      WaitForProcess2();
      // Okay, Mail Read and Shred, Bye!
      MmfServerSide(true);
    }
 
    // Only seen by the 1st Instance of our App.
    [PermissionSet(SecurityAction.Demand,
      Name  = "FullTrust")]
    private void MmfEventDelegate()
    {
      var m = Mapped;
      Watcher.NotifyFilter =
        NotifyFilters.LastWrite;
      Watcher.InternalBufferSize  = 2048;
        //SMS.Default.EditorSize
      Watcher.EnableRaisingEvents = false;
      // Setup File System Watcher:
      Watcher.Path   = // for Mapped File.
        Path.GetDirectoryName(m);
      Watcher.Filter = Path.GetFileName(m);
      if (File.Exists(m)) File.Delete(m);
      // Setup Server-Side of memory-mapped-file:
      MmfServerSide();
      // Create Eventhandler...
      Watcher.Changed += MmfChangedEventHandler;
      Watcher.EnableRaisingEvents = true;
    }
#endregion SS MMF Watcher, Event & Handler
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
  }
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎