Use WinForm as AppService for UWP - c#

I'm trying to figure out how I can send data to my WinForm Component without always having to reply on a message sent by the WinForm. I know one can set an AppService name, etc. in the package.appxmanifest of the UWP App. But, what is the equivaliant of this in a Win32 environment like WinForms.
Is any code needed to assist with getting an answer?
Thank you
Edit
Currently, my UWP App is responding to messages sent from my WinForm Component every couple of milliseconds.
App.xaml.cs
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
if (args.TaskInstance.TriggerDetails is AppServiceTriggerDetails)
{
appServiceDeferral = args.TaskInstance.GetDeferral();
args.TaskInstance.Canceled += OnTaskCanceled; // Associate a cancellation handler with the background task.
AppServiceTriggerDetails details = args.TaskInstance.TriggerDetails as AppServiceTriggerDetails;
Connection = details.AppServiceConnection;
Connection.RequestReceived += (new MainPage()).Connection_OnRequestReceived;
}
}
MainPage.xaml.cs
public async void Connection_OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
// write setting to stop timer
localSettings.Values["Win32Working"] = "True";
// read content
if (args.Request.Message.ContainsKey("content"))
{
object message = null;
args.Request.Message.TryGetValue("content", out message);
// if message is an int[]
if (message is int[])
{
// init field vars
int indexInArray = 0;
bool newTest1On = false;
bool newTest2On = false;
bool newTest3On = false;
foreach (int trueorfalse in (int[])message)
{
// set bool state based on index
switch (indexInArray)
{
case 0:
newCapsOn = Convert.ToBoolean(trueorfalse);
localSettings.Values["Test1"] = (Convert.ToBoolean(trueorfalse)).ToString();
break;
case 1:
newNumOn = Convert.ToBoolean(trueorfalse);
localSettings.Values["Test2"] = (Convert.ToBoolean(trueorfalse)).ToString();
break;
case 2:
newScrollOn = Convert.ToBoolean(trueorfalse);
localSettings.Values["Test3"] = (Convert.ToBoolean(trueorfalse)).ToString();
break;
default:
break;
}
indexInArray++;
}
if (newTest1On != Test1On || newTest2On != Test2On || newTest3On != Test3On)
localSettings.Values["updateUI"] = true.ToString();
// update bools
Test1On = newTest1On;
Test2On = newTest2On;
Test3On = neTest3On;
// if exit requested
if (Convert.ToBoolean(localSettings.Values["sendExit"]))
{
// tell WinForm to exit
ValueSet messageExit = new ValueSet();
messageExit.Add("exit", null);
AppServiceResponseStatus responseStatus = await args.Request.SendResponseAsync(messageExit);
localSettings.Values["sendExit"] = false.ToString();
localSettings.Values["Win32Working"] = false.ToString();
}
}
}
else if (args.Request.Message.ContainsKey("request"))
{
if (!Convert.ToBoolean(localSettings.Values["sendExit"]))
{
// send current settings as response
AppServiceResponseStatus responseStatus = await args.Request.SendResponseAsync(UpdateWin32());
}
else
{
// tell WinForm to exit
ValueSet message = new ValueSet();
message.Add("exit", null);
AppServiceResponseStatus responseStatus = await args.Request.SendResponseAsync(message);
localSettings.Values["sendExit"] = false.ToString();
localSettings.Values["Win32Working"] = false.ToString();
}
}
else if (args.Request.Message.ContainsKey("exit"))
{
// exit
Application.Current.Exit();
}
}
My WinForm Code:
private async void threadCommunicationWinFrmAndUWP_Run()
{
bool askForInfo = false;
DoWork:
ValueSet message = new ValueSet();
if (!askForInfo) { message.Add("content", notifyIconsLogic.GetStatuses()); askForInfo = true; }
else { message.Add("request", ""); askForInfo = false; }
#region SendToUWP
// if connection isn't inited
if (connection == null)
{
// init
connection = new AppServiceConnection();
connection.PackageFamilyName = Package.Current.Id.FamilyName;
connection.AppServiceName = "NotifyIconsUWP";
// attempt connection
AppServiceConnectionStatus connectionStatus = await connection.OpenAsync();
// if UWP isn't running
if (connectionStatus == AppServiceConnectionStatus.AppUnavailable) return;
}
AppServiceResponse serviceResponse = await connection.SendMessageAsync(message);
// if UWP isn't running
if (serviceResponse.Status == AppServiceResponseStatus.Failure) return;
// get response
if (serviceResponse.Message.ContainsKey("content"))
{
object newMessage = null;
serviceResponse.Message.TryGetValue("content", out newMessage);
// if message is an int[]
if (newMessage is int[])
{
// init field vars
int indexInArray = 0;
bool showTest1 = false;
bool showTest2 = false;
bool showTest3 = false;
foreach (int trueorfalse in (int[])newMessage)
{
// set bool state based on index
switch (indexInArray)
{
case 0:
showTest1 = Convert.ToBoolean(trueorfalse);
break;
case 1:
showTest2 = Convert.ToBoolean(trueorfalse);
break;
case 2:
showTest3 = Convert.ToBoolean(trueorfalse);
break;
default:
break;
}
indexInArray++;
}
notifyIconsLogic.SetChecker(showTest1, showTest2, showTest3);
}
}
if (serviceResponse.Message.ContainsKey("exit")) Exit();
#endregion
goto DoWork;
}
This ramps up the CPU Usage excessively. The point is, my only way of getting information to the WinForm from the UWP App, currently, is by responding to messages sent in a loop.
Question
How can I send messages from the UWP App to the WinForm without only responding to the messages sent in a loop? Because, I want to eliminate the reliance on the loop (CPU Purposes).
In other words: how do I get the results of the package.appxmanifest to 'work' in WinForms?
package.appxmanifest
<Extensions>
<uap:Extension Category="windows.appService">
<uap:AppService Name="NotifyIconsUWP" />
</uap:Extension>
<desktop:Extension Category="windows.fullTrustProcess" Executable="Win32\NotifyIconsComponent.exe" />
</Extensions>

You should be able to send a request on the established app service connection from UWP app like this:
AppServiceResponse response = await App.Connection.SendMessageAsync(valueSet);
And then receive this message in the Windows Forms app by attaching an event handler:
connection.RequestReceived += Connection_RequestReceived;
Check out this sample which demonstrates two way communication between Console app and UWP app.

Related

NetMQ Polling a rep socket with a timeout in a loop

I'm trying to port my code from an obsolete library called CastleMQ to NetMQ but I'm running into some problems.
I prefer to using polling with a timeout, for reliability - I just found that it worked best for me from trial and error compared to just sitting blocking the port indefinitely.
here is my CastleMQ code
public int ZeroPort;
private void ThreadProc()
{
var ctx = new Context();
try {
using (var repSocket = ctx.CreateSocket(SocketType.Rep))
{
string bindAddress = "tcp://*:"+ZeroPort;
repSocket.Bind(bindAddress);
print2("*** BINDING on {0} ***", bindAddress);
bool quit = false;
while (!quit) {
try {
var polling = new Polling(PollingEvents.RecvReady, repSocket);
polling.RecvReady += (socket) =>
{ // using socket.Recv() here is guaranted to return stuff
var msg = socket.Recv();
var msgStr = Encoding.UTF8.GetString(msg);
print2("[REP:{0}] {1}", bindAddress, msgStr);
switch (msgStr) {
case "positions": {
StringBuilder csv = new StringBuilder();
print2("csv: {0}", csv.ToString());
socket.Send(csv.ToString());
break;
}
default: {
socket.Send("Unrecognized Command: " + msgStr);
break;
}
}
};
polling.Poll(POLL_TIMEOUT_MS); // this returns once some socket event happens
} catch (Exception e) {
if (e is ThreadAbortException) {
quit = true;
print2("\n*** EXITED ***");
} else print2(e.ToString());
}
}
}
} catch (Exception e) {
print2(e.ToString());
} finally {
ctx.Dispose();
}
}
here is what I tried to do and then got lost with NetMQ
private void ThreadProc()
{
try {
string bindAddress = "#tcp://*:" + ZeroPort;
print2("*** BINDING on {0} ***", bindAddress);
using (var repSocket = new ResponseSocket(bindAddress))
using (var poller = new NetMQPoller { repSocket })
{
// bool quit = false;
// while (!quit)
// these event will be raised by the Poller
repSocket.ReceiveReady += (s, a) =>
{
// receive won't block as a message is ready
string msg = a.Socket.ReceiveString(); // defeinition for ReceiveString() can't be found
// send a response
a.Socket.Send("Response"); // it doesn't like "Response", do I need to wrap it in some object?
I'm especially confused as how to add a timeout so I can poll with a timeout in a loop the way my CastleMQ code does.
Any pointers would be much appreciated, thanks

Update WPF application using console application that will call to the windows service

Hi stackoverflow masters. What i want trying to solve is to update my WPF application, I have 3 programs WPF applcation, console application and windows service. What it does was my WPF application calls my console application and my console application send a command to the windows service, my windows service will kill the process of my WPF application and do the update and my console application will run my WPF application again. Now, the updating part in windows service is working, but i have a problem with my console application since the WPF application calls my console application every time the user open it and it loops forever. I know there are problems with my console app.
Thanks in advance masters. :)
so here's my code.
try
{
_log.Info("Checking for new update.");
int wpfAppExecuteCommand;
string defaultpath = #"C:\Program Files (x86)\WPF Application";
string wpfAppInfoPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WPF\\WPFAppInfo.txt");
string[] txtFile = File.ReadAllLines(wpfAppInfoPath);
if (txtFile.Count() > 0)
{
_wpfAppInfo = txtFile[0];
switch (_wpfAppInfo)
{
case "WPF Application":
wpfAppExecuteCommand = 150;
_wpfSoftwareLocation = Path.Combine(defaultpath, "WPF Application.exe");
break;
default:
wpfAppExecuteCommand = 0;
break;
}
using (var service = new ServiceController("Update Checker API Service"))
{
if (service.Status == ServiceControllerStatus.Running)
{
_log.Debug("Service is running.");
service.ExecuteCommand(wpfAppExecuteCommand);
}
else
{
_log.Error("Service is not running.");
}
}
}
_log.Debug("Please wait..");
_stopwatch = new Stopwatch();
_stopwatch.Start();
bool checking = true;
while (checking)
{
if (_stopwatch.Elapsed > TimeSpan.FromMinutes(1))
{
if (!_oneMin)
{
_oneMin = true;
_log.Warn("Installing udpate is taking too long, please wait..");
}
}
else if (_stopwatch.Elapsed > TimeSpan.FromMinutes(5))
{
if (!_fiveMin)
{
_fiveMin = true;
_log.Warn("Installing udpate is taking too long, please wait..");
}
}
else if (_stopwatch.Elapsed > TimeSpan.FromMinutes(10))
{
if (!_tenMin)
{
_tenMin = true;
_isTimerOn = true;
_log.Warn(".");
}
}
if (File.Exists(_resultTxt))
{
_log.Trace("File exist. Read if is Success");
string[] lines = File.ReadAllLines(_resultTxt);
if (lines[0].Equals("Success"))
{
_log.Trace("Checks if the Software.exe exist");
if (File.Exists(_wpfSoftwareLocation))
{
string runMsiExecBatchFile = Path.Combine(_batchFileDefaultFolder, "RunMsiExec.bat");
//Deleting the batch file used by windows service.
if (File.Exists(runMsiExecBatchFile))
{
File.Delete(Path.Combine(_batchFileDefaultFolder, "RunMsiExec.bat"));
_log.Info("RunMsiExec.bat file deleted.");
}
else
{
_log.Warn("RunMsiExec.bat not found");
}
_openWpfApp = true;
checking = false;
_stopwatch.Stop();
}
else
{
_log.Error("Software.exe not exist");
_stopwatch.Stop();
checking = false;
}
}
else if (lines[0].Equals("The current version is up to date"))
{
_log.Info("The current version is up to date");
_openWpfApp = true;
checking = false;
_stopwatch.Stop();
}
else
{
_log.Error(lines[0]);
checking = false;
_stopwatch.Stop();
}
}
else
{
_log.Debug("Result text not found.");
}
}
if (_openWpfApp)
{
_log.Info("Open WPF application software.");
Process.Start(_wpfSoftwareLocation);
}
else
{
_log.Info("Unable to open the Wpf application software.");
}
catch (Exception ex)
{
_log.Error(ex);
}

Reconnecting to socket.io server takes long time after receiving messages using SocketIoClientDotNet

I'm developing a plugin for Grasshopper for Rhino which uses a .NET framework with C# and I have a problem when reconnecting to a socket.io 1.4.5 server. I'm using SocketIoClientDotNet 0.9.13 to connect to a server and it works fine if I just want to connect/disconnect to a server but I have a problem reconnecting to a server after I received a message using an event taking a lot of time to reconnect.
Depends on the number of messages I received by the event during the connection, after I close and make a new connection it takes more than a minute (sometimes more than 10 mins if there are a lot of messages received) for the new connection.
Could anybody tell what is going wrong?
The code is written as follows:
Quobject.SocketIoClientDotNet.Client.Socket socket;
private System.Threading.ManualResetEvent manualResetEvent = null;
private bool currentState = false;
public object output = null;
public bool connected = false;
private Quobject.SocketIoClientDotNet.Client.IO.Options CreateOptions()
{
Quobject.SocketIoClientDotNet.Client.IO.Options op = new Quobject.SocketIoClientDotNet.Client.IO.Options();
op.AutoConnect = true;
op.Reconnection = true;
op.ReconnectionAttempts = 5;
op.ReconnectionDelay = 5;
op.Timeout = 20;
op.Secure = true;
op.ForceNew = true;
op.Multiplex = true;
return op;
}
private void ConnectToSocket(bool b, string address){
if(currentState != b){
if(b && !connected){
manualResetEvent = new System.Threading.ManualResetEvent(false);
var options = CreateOptions();
socket = IO.Socket(address, options);
socket.On(Quobject.SocketIoClientDotNet.Client.Socket.EVENT_CONNECT, () =>
{
connected = true;
Print("connected");
manualResetEvent.Set();
});
socket.On("slider_message", (data) =>
{
if(data != null){
var jobject = data as JToken;
try{
var sliderValue = jobject.Value<string>("slider");
output = sliderValue;
}catch{
}
}
manualResetEvent.Set();
});
socket.On(Quobject.SocketIoClientDotNet.Client.Socket.EVENT_DISCONNECT, () =>
{
connected = false;
Print("disconnected");
manualResetEvent.Set();
});
Print("connecting...");
manualResetEvent.WaitOne();
}else{
if(socket != null & connected){
manualResetEvent = new System.Threading.ManualResetEvent(false);
Print("disconnecting...");
socket.Close();
manualResetEvent.WaitOne();
socket = null;
}
}
}
currentState = b;
}

c# prevent screen capture of UserControl

The execs at my company would like a particular custom control of our ui to make a best-effort at preventing screen capture. I implemented a slick solution using SetWindowDisplayAffinity and DWMEnableComposition at the top Window level of our application to prevent screen capture of the entire app but the previously mentioned execs weren't happy with that. They want only the particular UserControl to prevent screen capture, not the entire app.
The custom control is a .NET 2.0 Windows.Forms.UserControl wrapped in a 4.5 WPF WindowsFormsHost contained by a 4.5 WPF Window control.
Before I tell the execs where to go, I want to be certain there isn't a reasonable way to implement this.
So, my question is: How do I implement screen capture prevention of a .NET 2.0 UserControl?
Thanks
i had an idea:
the user click "PrintScreen", a capture from my program is copy to ClipBoard.
So, all what i need it: to catch cliboard an check if he contains an image.
if yes: i delete the image from clipboard.
the code:
//definition a timer
public static Timer getImageTimer = new Timer();
[STAThread]
static void Main()
{
getImageTimer.Interval = 500;
getImageTimer.Tick += GetImageTimer_Tick;
getImageTimer.Start();
......
}
private static void GetImageTimer_Tick(object sender, EventArgs e)
{
if (Clipboard.ContainsImage())//if clipboard contains an image
Clipboard.Clear();//delete
}
*but it avoid any time program is running. (you need to know if your program is foreground, and then check clipboard);
You might be able to capture the key stroke.
Below is a method I used for that, but it had limited success:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if ((m_parent != null) && m_parent.ScreenCapture(ref msg)) {
return true;
} else {
return base.ProcessCmdKey(ref msg, keyData);
}
}
protected override bool ProcessKeyEventArgs(ref Message msg) {
if ((m_parent != null) && m_parent.ScreenCapture(ref msg)) {
return true;
} else {
return base.ProcessKeyEventArgs(ref msg);
}
}
Returning "True" was supposed to tell the system that the PrintScreen routine was handled, but it often still found the data on the clipboard.
What I did instead, as you can see from the call to m_parent.ScreenCapture, was to save the capture to a file, then display it in my own custom image viewer.
If it helps, here is the wrapper I created for the custom image viewer in m_parent.ScreenCapture:
public bool ScreenCapture(ref Message msg) {
var WParam = (Keys)msg.WParam;
if ((WParam == Keys.PrintScreen) || (WParam == (Keys.PrintScreen & Keys.Alt))) {
ScreenCapture(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
msg = new Message(); // erases the data
return true;
}
return false;
}
public void ScreenCapture(string initialDirectory) {
this.Refresh();
var rect = new Rectangle(Location.X, Location.Y, Size.Width, Size.Height);
var imgFile = Global.ScreenCapture(rect);
//string fullName = null;
string filename = null;
string extension = null;
if ((imgFile != null) && imgFile.Exists) {
filename = Global.GetFilenameWithoutExt(imgFile.FullName);
extension = Path.GetExtension(imgFile.FullName);
} else {
using (var worker = new BackgroundWorker()) {
worker.DoWork += delegate(object sender, DoWorkEventArgs e) {
Thread.Sleep(300);
var bmp = new Bitmap(rect.Width, rect.Height);
using (var g = Graphics.FromImage(bmp)) {
g.CopyFromScreen(Location, Point.Empty, rect.Size); // WinForm Only
}
e.Result = bmp;
};
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
if (e.Error != null) {
var err = e.Error;
while (err.InnerException != null) {
err = err.InnerException;
}
MessageBox.Show(err.Message, "Screen Capture", MessageBoxButtons.OK, MessageBoxIcon.Stop);
} else if (e.Cancelled) {
} else if (e.Result != null) {
if (e.Result is Bitmap) {
var bitmap = (Bitmap)e.Result;
imgFile = new FileInfo(Global.GetUniqueFilenameWithPath(m_screenShotPath, "Screenshot", ".jpg"));
filename = Global.GetFilenameWithoutExt(imgFile.FullName);
extension = Path.GetExtension(imgFile.FullName);
bitmap.Save(imgFile.FullName, ImageFormat.Jpeg);
}
}
};
worker.RunWorkerAsync();
}
}
if ((imgFile != null) && imgFile.Exists && !String.IsNullOrEmpty(filename) && !String.IsNullOrEmpty(extension)) {
bool ok = false;
using (SaveFileDialog dlg = new SaveFileDialog()) {
dlg.Title = "ACP Image Capture: Image Name, File Format, and Destination";
dlg.FileName = filename;
dlg.InitialDirectory = m_screenShotPath;
dlg.DefaultExt = extension;
dlg.AddExtension = true;
dlg.Filter = "PNG Image|*.png|Jpeg Image (JPG)|*.jpg|GIF Image (GIF)|*.gif|Bitmap (BMP)|*.bmp" +
"|EWM Image|*.emf|TIFF Image|*.tif|Windows Metafile (WMF)|*.wmf|Exchangable image file|*.exif";
dlg.FilterIndex = 0;
if (dlg.ShowDialog(this) == DialogResult.OK) {
imgFile = imgFile.CopyTo(dlg.FileName, true);
m_screenShotPath = imgFile.DirectoryName;
ImageFormat fmtStyle;
switch (dlg.FilterIndex) {
case 2: fmtStyle = ImageFormat.Jpeg; break;
case 3: fmtStyle = ImageFormat.Gif; break;
case 4: fmtStyle = ImageFormat.Bmp; break;
case 5: fmtStyle = ImageFormat.Emf; break;
case 6: fmtStyle = ImageFormat.Tiff; break;
case 7: fmtStyle = ImageFormat.Wmf; break;
case 8: fmtStyle = ImageFormat.Exif; break;
default: fmtStyle = ImageFormat.Png; break;
}
ok = true;
}
}
if (ok) {
string command = string.Format(#"{0}", imgFile.FullName);
try { // try default image viewer
var psi = new ProcessStartInfo(command);
Process.Start(psi);
} catch (Exception) {
try { // try IE
ProcessStartInfo psi = new ProcessStartInfo("iexplore.exe", command);
Process.Start(psi);
} catch (Exception) { }
}
}
}
}
I wrote that years ago, and I don't work there now. The source code is still in my Cloud drive so that I can leverage skills I learned once (and forgot).
That code isn't meant to get you completely done, but just to show you a way of doing it. If you need any help with something, let me know.
Not a silver bullet, but could form part of a strategy...
If you were worried about the windows snipping tool or other known snipping tools, you could subscribe to Windows events to capture a notification of when SnippingTool.exe was launched and then hide your application until it was closed:
var applicationStartWatcher = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
applicationStartWatcher.EventArrived += (sender, args) =>
{
if (args.NewEvent.Properties["ProcessName"].Value.ToString().StartsWith("SnippingTool"))
{
Dispatcher.Invoke(() => this.Visibility = Visibility.Hidden);
}
};
applicationStartWatcher.Start();
var applicationCloseWatcher = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStopTrace"));
applicationCloseWatcher.EventArrived += (sender, args) =>
{
if (args.NewEvent.Properties["ProcessName"].Value.ToString().StartsWith("SnippingTool"))
{
Dispatcher.Invoke(() =>
{
this.Visibility = Visibility.Visible;
this.Activate();
});
}
};
applicationCloseWatcher.Start();
You will probably need to be running as an administrator for this code to work.
ManagementEventWatcher is in the System.Management assembly.
This coupled with some strategy for handling the print screen key: for example something like this may at least make it difficult to screen capture.

c# BackgroundWorker pause

I have a small C# application that communicate with a server and get some data via API request, using POST method. It is an Apache server by the way.
My problem is that my C# app sends a tons of requests continuously, and the server creates a tons of log files.
I use a BackgroundWorker and I want to pause it for a few seconds, but Thread.Sleep(5000) doesn't working.
This app is running in the system tray it doesn't have a GUI, just get some content, and print them out.
Code:
private void _bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
JSONParser parser = new JSONParser(_config.Prop.server + "content/api.php", "print", "getAll");
try
{
while (!_bgWorker.CancellationPending)
{
try
{
JSONPrintNeeds needs = parser.DownloadAll();
List<JSONPrintNeed> temp = new List<JSONPrintNeed>();
foreach (JSONPrintNeed need in needs.data)
{
temp.Add(need);
}
foreach (JSONPrintNeed need in temp)
{
Printer printer = new Printer(need.megrendeles);
printer.PrintController = new StandardPrintController();
List<String> installed = new List<String>();
for (int i = 0; i < PrinterSettings.InstalledPrinters.Count; i++)
{
installed.Add(PrinterSettings.InstalledPrinters[i]);
}
if (installed.Contains(need.nyomtato))
{
printer.PrinterSettings.PrinterName = need.nyomtato;
}
int format = int.Parse(need.format);
switch (format)
{
case 0:
default: // txt
printer.Print();
break;
case 1: // html
SetDefaultPrinter(need.nyomtato);
browser.DocumentText = need.megrendeles;
browser.Print();
break;
}
JSONResult result = parser.DeleteOne(int.Parse(need.ny_id));
}
parser.DeleteAll();
Thread.Sleep(5000);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
you can use EventWaitHandle for sync threads.
EventWaitHandle flag = new EventWaitHandle(false, EventResetMode.AutoReset);
if (stop)
{
flag.WaitOne(5000);
}

Categories

Resources