I want to set focus on notepad (Untitled - Notepad) and write some text into it. I have to create a Windows Service for this.
I can create windows service but don't know how to set focus on notepad.
Please provide me code samples in Windows Service
I have tried following code. But no luck with it.
namespace SampleService
{
public partial class Service1 : ServiceBase
{
string application = string.Empty;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
GetTaskWindows();
int iHandle = NativeWin32.FindWindow(null, application);
NativeWin32.SetForegroundWindow(iHandle);
}
protected override void OnStop()
{
GetTaskWindows();
int iHandle = NativeWin32.FindWindow(null, application);
NativeWin32.SetForegroundWindow(iHandle);
}
private void GetTaskWindows()
{
// Get the desktopwindow handle
int nDeshWndHandle = NativeWin32.GetDesktopWindow();
// Get the first child window
int nChildHandle = NativeWin32.GetWindow(nDeshWndHandle, NativeWin32.GW_CHILD);
while (nChildHandle != 0)
{
// Get only visible windows
if (NativeWin32.IsWindowVisible(nChildHandle) != 0)
{
StringBuilder sbTitle = new StringBuilder(1024);
// Read the Title bar text on the windows to put in combobox
NativeWin32.GetWindowText(nChildHandle, sbTitle, sbTitle.Capacity);
String sWinTitle = sbTitle.ToString();
{
if (sWinTitle.Length > 0)
{
if (sWinTitle.Contains("Notepad"))
{
application = sWinTitle;
}
}
}
}
// Look for the next child.
nChildHandle = NativeWin32.GetWindow(nChildHandle, NativeWin32.GW_HWNDNEXT);
}
}
}
}
Fixed myself. Created one small application which will focus on notepad and used sendKeys function to write text into notepad.
Related
I am leaning Xamarin,
I have build a quick app that read audio effect file (mp3/wav).
My problem :
When I start the App while I was listened music ( spotify/deezer ) the musique stops because the app has started.
So, I would like to be able to listen to music ( spotify/deezer ) and use my app.
My audio C# class in Android looks like this :
public class MyAudioOutput : IAudioServiceOutput
{
public void GetAudioSetting()
{
var audioManager = (Android.Media.AudioManager)Android.App.Application.Context.GetSystemService(Android.Content.Context.AudioService);
audioManager.Mode = Mode.Normal;
audioManager.SpeakerphoneOn = true;
}
}
My Audio C# classe in IOS looks like this :
public class MyAudioOutput : IAudioServiceOutput
{
public void GetAudioSetting()
{
var session = AVAudioSession.SharedInstance();
session.OverrideOutputAudioPort(AVAudioSessionPortOverride.Speaker, out NSError error);
session.SetCategory(AVAudioSessionCategory.Playback);
session.SetActive(true);
}
}
My interface in Xamarin Forms shared :
public interface IAudioServiceOutput
{
void GetAudioSetting();
}
In my Xamarin forms cs file , I use the function this way :
ISimpleAudioPlayer AudioPlayerGood;
void InitMyAudio()
{
string filenamegood = "Question.Good_Answer.mp3";
using (Stream streamGood = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(filenamegood))
{
AudioPlayerGood = CrossSimpleAudioPlayer.CreateSimpleAudioPlayer();
AudioPlayerGood.Load(streamGood);
}
}
void OnPlayAnswerSong(bool goodanswer)
{
if (goodanswer == true)
{
AudioPlayerGood.Play();
}
else if (goodanswer == false)
{
AudioPlayerWrong.Play();
}
}
Thanks for you help
For this, you can refer to the following thread:Pause background service in Xamarin.Forms
The implementation on android platform is as follows:
[assembly: Dependency(typeof(StopMusicService))]
namespace TTSDemo.Droid
{
public class StopMusicService : IControl
{
AudioManager audioMan;
AudioManager.IOnAudioFocusChangeListener listener;
public void StopBackgroundMusic()
{
audioMan = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
listener = new MyAudioListener(this);
var ret = audioMan.RequestAudioFocus(listener, Stream.Music, AudioFocus.Gain);
}
}
internal class MyAudioListener :Java.Lang.Object, AudioManager.IOnAudioFocusChangeListener
{
private StopMusicService stopMusicService;
public MyAudioListener(StopMusicService stopMusicService)
{
this.stopMusicService = stopMusicService;
}
public void OnAudioFocusChange([GeneratedEnum] AudioFocus focusChange)
{
// throw new NotImplementedException();
}
}
}
And you can also check the updated part code by Nieminen included in above link.
So I am creating an editor tool, this tool is open by clicking in a custom MenuItem. This tool is open as a utility window using the GetWindow<T>(true, "title") and ShowModalUtility() methods. This new utility window has button that will open another utility window (different editor window type) using the same methods mentioned above.
I don't know if is a bug or by design, but it seems like having multiple utility windows open is not working properly. When the second utility window is open (by pressing the button in the first one) the rest of the unity editor is still block like it should, but the second utility window does not block the first one.
It looks as if being a utility window is a "static" thing and all utility windows have the same priority so you can click on any of them at any time.
Does anyone know how to block one utility editor window using another utility editor window?
P.S: I saw this post, and like I mentioned, I am using ShowModalUtility() but it does not work properly for me, when I have both utility windows open.
UPDATE:
Here is a working example:
using UnityEditor;
using UnityEngine;
public class Test
{
public class TestWindow1 : EditorWindow
{
[MenuItem("TEST/Test Window 1")]
public static void Open()
{
var window = GetWindow<TestWindow1>(true, "Test Window 1");
window.ShowModalUtility();
}
private string text = "";
void OnGUI()
{
text = EditorGUILayout.TextField("Try To Write Here:", text);
if (GUILayout.Button("Open Test Window 2"))
{
TestWindow2.Open();
}
}
}
public class TestWindow2 : EditorWindow
{
public static void Open()
{
var window = GetWindow<TestWindow2>(true, "Test Window 2");
window.ShowModalUtility();
}
private string text = "";
void OnGUI()
{
text = EditorGUILayout.TextField("Try To Write Here:", text);
if (GUILayout.Button("Open Test Window 3"))
{
TestWindow3.Open();
}
}
}
public class TestWindow3 : EditorWindow
{
public static void Open()
{
var window = GetWindow<TestWindow3>(true, "Test Window 3");
window.ShowModalUtility();
}
void OnGUI()
{
EditorGUILayout.LabelField("NOTHING TO DO HERE!!!!");
}
}
}
So if you try to run this code then: You will open TestWindow1, if you try to write something in there it will work and if you try to click on the editor it will be block (this is correct behaviour).
If then you open TestWindow2 you should be able to write in window 2 but you should not be able to write in window 1 (window 1 should be block by window 2) here is the problem: At the moment of writing this update, I am able to write in window 1 even when window 2 is open, and also I can write in both window 1 and 2 when window 3 is open, in other words, the utility windows don't block each other, they only block the editor.
Test environment:
Unity 2021.3.15f1 (SILICON for mac)
In my environment, TestWindow2 is not displayed until TestWindow1 is closed. In my environment, it seems that there is only one Window that can be opened with ShowModalUtility().
I think the easiest way to display multiple windows is to check the flags and pass them to EditorGUI.BeginDisabledGroup. However, in that case, ShowModalUtility() cannot be used.
public class Test
{
public class TestWindow1 : EditorWindow
{
public static bool IsOpen { get; private set; }
[MenuItem("TEST/Test Window 1")]
public static void Open()
{
var window = GetWindow<TestWindow1>(true, "Test Window 1");
window.Show();
}
private string text = "";
void Awake() => IsOpen = true;
void OnGUI()
{
EditorGUI.BeginDisabledGroup(TestWindow2.IsOpen || TestWindow3.IsOpen);
text = EditorGUILayout.TextField("Try To Write Here:", text);
if (GUILayout.Button("Open Test Window 2"))
{
TestWindow2.Open();
}
EditorGUI.EndDisabledGroup();
}
void OnDestroy() => IsOpen = false;
}
public class TestWindow2 : EditorWindow
{
public static bool IsOpen { get; private set; }
public static void Open()
{
var window = GetWindow<TestWindow2>(true, "Test Window 2");
window.Show();
}
private string text = "";
void Awake() => IsOpen = true;
void OnGUI()
{
if (!TestWindow1.IsOpen)
{
Close();
}
EditorGUI.BeginDisabledGroup(TestWindow3.IsOpen);
text = EditorGUILayout.TextField("Try To Write Here:", text);
if (GUILayout.Button("Open Test Window 3"))
{
TestWindow3.Open();
}
EditorGUI.EndDisabledGroup();
}
void OnDestroy() => IsOpen = false;
}
public class TestWindow3 : EditorWindow
{
public static bool IsOpen { get; private set; }
public static void Open()
{
var window = GetWindow<TestWindow3>(true, "Test Window 3");
window.Show();
}
void Awake() => IsOpen = true;
void OnGUI()
{
if (!TestWindow1.IsOpen || !TestWindow2.IsOpen)
{
Close();
}
EditorGUILayout.LabelField("NOTHING TO DO HERE!!!!");
}
void OnDestroy() => IsOpen = false;
}
}
Considering the function of ShowModalUtility(), I do not feel uncomfortable with the specification that only one window can be opened. So I think it is better to use the above method or complete within one Window.
Past Responses: -------------------
Could you please provide a minimum reproduction code? Then I may be able to help.
Below is my test code:
using UnityEditor;
using UnityEngine;
// TestWindow1.cs
public class TestWindow1 : EditorWindow
{
[MenuItem("Test/Window1")]
static void ShowWindow()
{
var window = GetWindow<TestWindow1>();
window.ShowModalUtility();
}
void OnGUI()
{
if (GUILayout.Button("Open Window2"))
{
var window = GetWindow<TestWindow2>();
window.ShowModalUtility();
}
}
}
// TestWindow2.cs
public class TestWindow2 : EditorWindow
{
void OnGUI()
{
if (GUILayout.Button("Open Window3"))
{
var window = GetWindow<TestWindow3>();
window.ShowModalUtility();
}
}
}
// TestWindow3.cs
public class TestWindow3 : EditorWindow {}
I've got a WinForm app that parents Windows of other processes (ex. Google Chrome). I'm using the following code to parent a Windows to my Form, using the Handle returned by [Process].MainWindowHandle.
I'm trying to find the MainWindowTitle of all the Windows that are parented to my Form, so I can display their name on a Label.
When the Window of a WebBrowser is embedded, the Title will change when a different Web Page is selected, switching Tabs.
The code I have for starting the program does work as it should:
ProcessStartInfo ps1 = new ProcessStartInfo(#"C:/Users/Jacob/AppData/Roaming/Spotify/Spotify.exe");
ps1.WindowStyle = ProcessWindowStyle.Minimized;
Process p1 = Process.Start(ps1);
// Allow the process to open it's window
Thread.Sleep(1000);
appWin1 = p1.MainWindowHandle;
spotify = p1;
// Put it into this form
SetParent(appWin1, this.Handle);
// Move the window to overlay it on this window
MoveWindow(appWin1, 0, 70, this.Width / 2, this.Height/2, true);
Since you're willing to use UIAutomation to handle this parenting affair, I propose to handle this using Automation methods entirely. Almost, SetParent still required :).
The class shown here uses the WindowPatter.WindowOpenedEvent to detect and notify when a new Window is opened in the System.
It can be any Window, Console included (still a Window).
This method allows to identify a Window when it's handle is already created, so you don't need an arbitrary time-out or try to use Process.WaitForInputIdle(), which may not have the desired result.
You can pass a list of names of processes to the ProcessNames Property of the class: when any Window that belongs to one of these Processes is opened, UIAutomation detects it and a public event is raised. It notifies the subscribers that one of the Processes in the list has opened a Window, which is the ProcessId of the Owner and the handle of the Windows.
These values are passed in a custom EventArgs class, ProcessStartedArgs when the ProcessStarted event is raised.
Since the Automation Event is raised in a Thread other than the UI Thread, the class captures the SynchronizationContext where the class is created (the UI Thread, since you're probably creating this class in a Form) and marshals the event to that Thread, calling its Post() method passing a SendOrPostCallback delegate.
This way, you can safely pass the Handle of your Form and the Handle of the Window to SetParent().
To retrieve the current Title (Caption) of the parented Window, pass the Handle previously returned in the event argument to the GetCurrentWindowTitle() method. If the Window contains tabbed child Windows, as a Web Browser, this method will return the Title related to the Tab currently selected.
▶ The class is disposable and you need to call its public Dispose() method. This removes the Automation event handler and also all the events in the Invocation List of the public event you have subscribed to. This way, you can use a Lambda to subscribe to the event.
Use a Field to store an instance of this class. Create the instance when needed, passing a List of Process Names you're interested in.
Subscribe to the ProcessStarted event.
When on of these Processes opens a new Window, you'll get a notification and the parenting thing can be performed:
public partial class SomeForm : Form
{
private WindowWatcher watcher = null;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
watcher = new WindowWatcher();
watcher.ProcessNames.AddRange(new[] { "msedge", "firefox", "chrome", "notepad" });
watcher.ProcessStarted += (o, ev) => {
SetParent(ev.WindowHandle, this.Handle);
MoveWindow(ev.WindowHandle, 0, 70, this.Width / 2, this.Height / 2, true);
string windowTitle = WindowWatcher.GetCurrentWindowTitle(ev.WindowHandle);
};
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
watcher.Dispose();
base.OnFormClosed(e);
}
}
WindowWatcher class:
NOTE: UI Automation assemblies are part of Windows Presentation Framework.
When one of these assemblies is referenced in a WinForms application, the WinForms application will become DpiAware (SystemAware), if it's not already DpiAware.
This can have an impact on the Layout of one or more Forms that is not designed to handle Dpi Awareness changes and notifications.
Requires a Project Reference to:
UIAutomationClient
UIAutomationTypes
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Automation;
public class WindowWatcher : IDisposable
{
private SynchronizationContext context = null;
private readonly SendOrPostCallback eventCallback;
public event EventHandler<ProcessStartedArgs> ProcessStarted;
private AutomationElement uiaWindow;
private AutomationEventHandler WindowOpenedHandler;
public WindowWatcher() {
context = SynchronizationContext.Current;
eventCallback = new SendOrPostCallback(EventHandlersInvoker);
InitializeWatcher();
}
public List<string> ProcessNames { get; set; } = new List<string>();
private void InitializeWatcher()
{
Automation.AddAutomationEventHandler(
WindowPattern.WindowOpenedEvent, AutomationElement.RootElement,
TreeScope.Children, WindowOpenedHandler = new AutomationEventHandler(OnWindowOpenedEvent));
}
public static string GetCurrentWindowTitle(IntPtr handle)
{
if (handle == IntPtr.Zero) return string.Empty;
var element = AutomationElement.FromHandle(handle);
if (element != null) {
return element.Current.Name;
}
return string.Empty;
}
private void OnWindowOpenedEvent(object uiaElement, AutomationEventArgs e)
{
uiaWindow = uiaElement as AutomationElement;
if (uiaWindow == null || uiaWindow.Current.ProcessId == Process.GetCurrentProcess().Id) return;
var window = uiaWindow.Current;
var procName = string.Empty;
using (var proc = Process.GetProcessById(window.ProcessId)) {
if (proc == null) throw new InvalidOperationException("Invalid Process");
procName = proc.ProcessName;
}
if (ProcessNames.IndexOf(procName) >= 0) {
var args = new ProcessStartedArgs(procName, window.ProcessId, (IntPtr)window.NativeWindowHandle);
context.Post(eventCallback, args);
}
}
public class ProcessStartedArgs : EventArgs
{
public ProcessStartedArgs(string procName, int procId, IntPtr windowHandle)
{
ProcessName = procName;
ProcessId = procId;
WindowHandle = windowHandle;
}
public string ProcessName { get; }
public int ProcessId { get; }
public IntPtr WindowHandle { get; }
}
private void EventHandlersInvoker(object state)
{
if (!(state is ProcessStartedArgs args)) return;
ProcessStarted?.Invoke(this, args);
}
~WindowWatcher() { Dispose(false); }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (uiaWindow != null && WindowOpenedHandler != null) {
Automation.RemoveAutomationEventHandler(
WindowPattern.WindowOpenedEvent, uiaWindow, WindowOpenedHandler);
}
if (ProcessStarted != null) {
var invList = ProcessStarted.GetInvocationList();
if (invList != null && invList.Length > 0) {
for (int i = invList.Length - 1; i >= 0; i--) {
ProcessStarted -= (EventHandler<ProcessStartedArgs>)invList[i];
}
}
}
}
}
I'm working with an C# .Net application that uses Cplex DLL's for an optimization operation, and during that operation I want to write status progress to a statusbar on the that initiated the operation.
This is the general layout of the specific form;
namespace ActResMain
{
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
//...
cplex.Use(new Cplex_ContinuousCallback());
cplex.Solve()
}
public void Update_OptimizeStatusbarPanel(String strText)
{
statusBarPanel_1.Text = strText;
statusBar1.Refresh();
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize formOpt = new FormOptimize();
public override void Main()
{
//From here I want to edit the statusbar at FormOptimize. I can write progress to console without any problems, but cannot reach function "Update_OptimizeStatusbarPanel".
//If I include "FormOptimize formOpt = new FormOptimize" here, i get Visual studio exception on illegal window reference.
}
}
}
}
I have also tried invoking the Update_OptimizeStatusbarPanel function like this:
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize formOpt = new FormOptimize();
public override void Main()
{
FormCollection fc = Application.OpenForms;
var mpc = fc[1];
Type type = mpc.GetType();
MethodInfo dynMethod = type.GetMethod("Update_OptimizeStatusbarPanel");
dynMethod.Invoke(mpc, new object[] { String.Format("Running Optimization: {0} iterations ", Niterations)});
}
}
But then I get an exception from visual studio stating that an object created by one thread cannot be modified from another thread.
Maybe this is something stupid that I have missed, but help is greatly appriciated
EDIT: I edited the code as per Mohammad Dehghans suggestion,
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
cplex.Use(new Cplex_ContinuousCallback(this));
cplex.Solve()
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize _formOptimize;
public Cplex_ContinuousCallback(FormOptimize formOptimize)
{
this._formOptimize = formOptimize;
}
public override void Main()
{
if (Niterations % 10 == 0)
{
_formOptimize.Update_OptimizeStatusbarPanel(0, String.Format("Running Optimization: {0} iterations ", Niterations), 0);
}
}
}
public void Update_OptimizeStatusbarPanel(short panelIndex, String strText, short severity)
{
if (statusBar1.InvokeRequired)
statusBar1.Invoke(new Action<short, string, short>(Update_OptimizeStatusbarPanel), panelIndex, strText, severity);
else
{
if (panelIndex == 0)
{
//...
statusBarPanel_0.Text = strText;
}
else if (panelIndex == 1)
{
//...
statusBarPanel_1.Text = strText;
}
statusBar1.Refresh();
}
}
}
But by doing that I apparently broke something, as the application just ..stops after statusBar1.Invoke() is called the first time. If I pause the debugger it says that cplex.Solve() is executing, but then nothing more happens.
First of all, you need to pass the instance of your form to the implemented callback class, so when the Main method is called, you have access to the exact instance that is being shown on the screen.
Secondly, you need to use Invoke method to update the UI controls from anther thread (I've not worked with CPLEX so far, but I guess the callback is invoked from another thread. That's usual).
Read this for more information.
The complete code could be:
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
//Misc code
cplex.Use(new Cplex_ContinuousCallback(this)); // <-- passing `this`
cplex.Solve()
//Misc code
}
public void Update_OptimizeStatusbarPanel(String strText)
{
if (statusBarPanel_1.InvokeRequired)
statusBarPanel_1.Invoke(Action<string>(Update_OptimizeStatusbarPanel), strText);
else
{
statusBarPanel_1.Text = strText;
statusBar1.Refresh();
}
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize _formOptimize;
public Cplex_ContinuousCallback(FormOptimize formOptimize)
{
this._formOptimize = formOptimize;
}
public override void Main()
{
//...
_formOptimize.Update_OptimizeStatusbarPanel(String.Format("Running Optimization: {0} iterations ", Niterations));
}
}
}
C# project 1: Library
public class TaskDummy : IPlannedTask {
private static readonly log4net.ILog log =
log4net.LogManager.GetLogger(typeof(TaskDummy));
// implements interface
public void run(System.IO.TextWriter x, object paramIn=null) {
initLog(x);
String msg = "Dummy task is running";
// direct & indirect call of TextWriter::WriteLine
x.WriteLine(msg);
log.Info(msg);
}
private void initLog(System.IO.TextWriter x) {
log4net.Appender = new log4net.Appender.TextWriterAppender();
textAppender.Writer = x;
// ...
}
}
results in TaskDummy.dll. log4net is configured with a TextWriterAppender at runtime.
C# project 2: Console app in same solution with reference on project 1.
class Program {
static void Main(string[] args) {
TaskDummy t = new TaskDummy();
t.run(Console.Out);
}
}
This will print
Dummy task is running
INFO - Dummy task is running
as exspected (direct & indirect call). The TextWriter is the one from console output.
C# project 3: Windows Forms
public class TextBoxWriter : TextWriter {
protected TextBox box;
public TextBoxWriter(TextBox box) {
this.box = box;
}
public override Encoding Encoding {
get { return Encoding.Default; }
}
delegate void WriteLineCallBack(String value);
public override void WriteLine(String value) {
if(box.InvokeRequired) {
WriteLineCallBack d = new WriteLineCallBack(WriteLine);
box.Invoke(d, new object[] { value });
} else {
base.Write(value);
box.AppendText(value.ToString() + Environment.NewLine);
}
}
}
Implementation of TextWriter to write into Windows Forms Textbox (cross-thread). This project loads implementations of IPlannedTask (see project 1) and calls their method run():
// txtLog is a Textbox control
TextBoxWriter twOutput = new TextBowWriter(txtLog);
var DLL = Assembly.LoadFile("TaskDummy.dll");
Type t = DLL.getExportedTypes()[0];
dynamic d = Activator.CreateInstance(t);
((IPlannedTask)d).run(twOutput);
This results in only one line in textbox from the direct call of WriteLine (see project 1). The log.Info call does not work (the method TextBoxWriter::WriteLine is not even called).
=> Why does TextWriterAppender of log4net work with Console.Out but not with TextBoxWriter