//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// 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
0 B
|👍
/👎