Ok I have an app named Sharknadoo that I created,what this app does it reads the value from a combobox from 1 to whatever number and creates that number of textboxes in the right of it.
Now let us presume I do not have the code for this sharknadoo app just the app installed on my desktop.My question is how can I send my listbox.items from "My amazing app" to the sharknadoo textboxes? Presuming I have the same number of items in my listbox as I have textboxes in my other app.I am sorry but I really want to learn how to do this ,someone told me it is possible to achieve but I have no idea on how to achieve it was thinking about using coordinates or something like that,but from what I understood you can even hang on to the fact that the sharknadoo app is using textboxes without even having access to its source code.Thank you in advance friends :D.
Process[] processes = Process.GetProcessesByName("Sharknadoo.exe");
int i = 0;
foreach (Process p in processes)
{
IntPtr windowHandle = p.MainWindowHandle;
string item = listBox1.Items[i].ToString();
listBox1.Items.Add(item);
i++;
}
I realize the logic of my code is not good but it's all I could come up with.
This answer follows similar logic to your code, but instead simulates keyboard strokes and relies on using TAB to navigate boxes, but it should work in your case.
First add some code that we will use later to grab a link to your Sharknadoo application:
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
Now assuming you have not touched anything in the app (Very dangerous assumption, it would be better to launch Sharknadoo from your code before doing any of this), the tab index should be at 0 so we can do something like the following when you click the "Send to Sharknadoo" button:
// Send a your array of names to the Sharknadoo application.
public void sendToSharknadoo(String[] detailsToSend)
{
// Get a handle to the Sharknadoo application. The window class
// and window name can be obtained from Sharknadoo using the
// Spy++ tool.
IntPtr windowHandle = FindWindow("SharknadooFrame","Sharknadoo");
// Verify that Sharknadoo is a running process.
if (windowHandle == IntPtr.Zero)
{
MessageBox.Show("Sharknadoo is not running.");
return;
}
// Make Sharknadoo the foreground application and set the number
// of text boxes for your info
SetForegroundWindow(windowHandle);
// Get to first box
SendKeys.SendWait("{TAB}");
// enter number of boxes
SendKeys.SendWait("{DOWN}");
SendKeys.SendWait((string)detailsToSend.Length);
// Now enter your details into each of those boxes
foreach (String s in detailsToSend)
{
// Get next textbox box
SendKeys.SendWait("{TAB}");
// enter text into box
SendKeys.SendWait(s);
}
}
With any luck that will do the trick. However you will probably need to mess with the order a bit put some checks in place.
Note: if you want a faster more aggressive approach that should execute before the user can interfere then try SendKeys.Send() instead of SendKeys.SendWait()
Source:
https://msdn.microsoft.com/en-us/library/ms171548(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys(v=vs.110).aspx
Additional Stack Overflow questions like this one:
Insert text into the textbox of another application
Related
I am creating my own C# clipboard manager and I have a global hotkey, ALT+H, that will trigger removal of text formatting from the clipboard. My application runs in the backend with a tray icon only. As such this is working fine but my problem is that when I am inside an application, e.g. Word and I am pressing my hotkey, then it will show me all kind of menus inside those applications and I do not want that.
Just for info then this is very related to another question I have on SO currently, How to stop further processing global hotkeys in C#. In the other question, this is based on finding a solution for the hotkey but another approach, which I think could even be better, could be to temporary switch focus to my application and once my hotkey is no longer applicable then the focus can be switched back to the originating application.
However then I have no idea how to switch back to the originating application again!?
My code so far, only focussing on the application changing mechanishmn:
Programs.cs:
// Import the required "SetForegroundWindow" method
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
Form1.cs:
// Change focus to my application (when hotkey is active)
Program.SetForegroundWindow(this.Handle);
I am not fully sure if this actually does work but I can see that the originating application (e.g. Word) looses focus and my application works fine still so I do expect it works fine.
My problem is - how to get the hWnd(?) handle from the originating application so I can switch back to it once done? And what if I am not within any application but e.g. just on the WIndows desktop? What will then happen - can it change back to that?
I would appreciate any hints that can help as I am by far no real C# developer ;-)
I have found the solution myself and will explain what worked out for me. I have this code here:
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
// I get in to here when the clipboard has changed and I need to find the application that has changed the clipboard
// Get the active/originating application handle
IntPtr originatingHandle = GetForegroundWindow();
// ------------------
// Do "some stuff" - this is not required for the application switching but it will get the application process name for the active/originating application
// Get the process ID from the active application
uint processId = 0;
GetWindowThreadProcessId(originatingHandle, out processId);
// Get the process name from the process ID
string appProcessName = Process.GetProcessById((int)processId).ProcessName;
// End "some stuff"
// ------------------
// Change focus to my application - this code is inside my main form (Form1)
SetForegroundWindow(this.Handle);
// Do some more stuff - whatever is required for my application to do
// ...
// Change focus back to the originating application again
SetForegroundWindow(originatingHandle);
At least the above code works for me.
I am trying to figure out how I can make my C# application to send keys to another application window, without focusing on it.
I have a list of words and 3 notepads files.
Imagine I have all 3 notepad windows opened in order, and my program would take the first word in the listbox and write it in the first Notepad window. The second word in the second Notepad window and third one in the third Notepad window. Then start over and continue.
So I want it to post 1 word in each and continue like that over and over.
But I only figured out how to do it with 1 notepad window (while having it active).
int i = 0;
i = listBox1.SelectedIndex;
i = i + 1;
if (i > listBox1.Items.Count - 1)
i = 0;
listBox1.SelectedIndex = i;
string message = listBox1.SelectedItem.ToString();
SendKeys.Send(message);
SendKeys.Send("{ENTER}");
This would require me to first focus on the notepad window, start the timer and then keep focus on the notepad window. It would then just loop through the list and type the word (1 on each line). And it works fine. But I want to be able to do it on 3 windows.
And then I need to get the window title somehow, not the process name.
I would have 3 processes called Notepad then.
But if they are named Note1, Note2, Note3 how would I do that?
I need help to make some kind of list of what programs to write to:
listofprograms = ["Note1", "Note2", "Note3"];
And it would find the application windows opened with those names,
then somehow write the text into those windows.
Could anyone help me out? Haven't found anything about this so far and trust me I've looked around!
Unfortunately there is no great way to do this. SendKeys is a really simple and desirable API but it only applies to the active window. There is no way to make it work on an inactive window nor is there an API with the same ease of access that works on inactive windows.
Generally when people run up against this problem they have to go one of two routes
Physically active the apps you want to send the keys to one at a time
Drop down to a much lower level of SendMessage or PostMessage to send keyboard events
The second option is generally more reliable but harder to implement.
SendKeys is not made for this type of functionality. To do what you're looking for, you're going to need to use some Win32 API calls in your code. See How to send text to Notepad in C#/Win32? for reference.
If you're looking for a way to send keys to an application, using SendKeys.Send(keys) is an option, but you need to bring the window to the top via the SetForegroundWindow API.
So, if you continue using your approach, you could use FindWindow, SetForegroundWindow to force the Notepad windows to be activated and focused, so that you could send the keys.
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String WindowName);
[DllImport("user32.dll")]
private static extern IntPtr SetForegroundWindow(int hWnd);
public int Activate(int hWnd)
{
if (hWnd > 0) {
SetForegroundWindow(hWnd);
return hWnd;
}
else {
return -1;
}
}
public int GetWindowHwnd(string className, string windowName) {
int hwnd = 0;
string cls = className == string.Empty ? null : className;
string win = windowName == string.Empty ? null : windowName;
hwnd = FindWindow(cls , win );
return hwnd;
}
Although there is also another solution, which could help you out. Here all Notepad processes are handled:
How to send text to Notepad in C#/Win32?
With some adaptions it should work for your case, too (basically you would iterate and loop through the notepad instances found and place a word in each instance).
You might also want to take a look at the following information about FindWindow:
http://www.pinvoke.net/default.aspx/user32.findwindow
SetKeyboardState:
http://www.pinvoke.net/default.aspx/user32/SetKeyboardState.html
As well as SendMessage:
http://www.pinvoke.net/default.aspx/coredll/SendMessage.html
You should find some useful hints in the examples and descriptions.
So long story short, I am trying to automate some things when my computer boots up. I thought I'd write an C# console application to do this and then add it to a schedule task in windows to be executed on bootup. My problem is with one program, it requires a password and has no options to open via the command line. Thus it must be entered manually. My thought was to retrieve my password from a KeePass database and use SendKeys to enter the password and login to the program. The problem I'm having is the time it takes to load; I have no way of detecting when the GUI interface has loaded and is ready for my SendKeys. Is there any way to detect this? I'm assuming all I have to work with is the "Process" class since thats what I used to run the program. Also note that when I run the executable using Process.Start(), the program creates another process for logging in, but it has no associated window that I can see using Windows API calls.
Okay that was long, I can re-cap...
Problem:
From C# detecting when a third party program has loaded (i.e. the splash screen is gone and GUI is ready for user interaction - meaning I can't just rely on if the Process is running or not).
Also, no command line options for the third party program, or I would just run it with the password as an argument.
Goal:
To use SendKeys in order to automate entering a password, but my program must wait for the third party application to finish loading.
Notes:
Using C# .NET 3.5 Console Application
NOT detecting load for my own form but a third party otherwise this would be easy (i.e. form_loaded event...)
Thank you for looking at my question, if you want any more details or anything let me know.
UPDATE:
Problem solved!
The two answers I received combined to give me the solution I wanted. So if anyone comes across this later, here is what I did to make it work.
So this program automates a login for some client software that you must login to. My problem was that the software offered not option or documentation for command line prameters which many other programs offer so you can login with a keyfile or something. This program also disabled copy and paste so the password HAS to be typed in manually, which is a big pain if you use passwords like I do, long complicated ones with no patterns. So I wrote this program for my benefit as well others at work; I just schedule it to run at logon to my windows machine and it opens the client software and performs login automatically.
//
// IMPORTANT Windows API imports....
//
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint procId);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
// When I get to this point in my code, I already had the password and window title...
string password = "password";
string title = "window title";
// This gets a handle to the window I want where "title" is the text in the title
// bar of the window as a string.
// This is a Windows API function that must be imported by DLLImport
// I had to get the handle this way because all I knew about the third party
// window was the title, not the process name or anything...
IntPtr hWnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, null, title);
// Now that I have a handle to the login window I used another windows API
// call to get the process ID.
// This windows API call gives me the Process ID as an out parameter and returns
// the thread ID of the window. I don't use the thread it, but maybe you can...
uint loginWindowProcId;
uint loginWindowThreadId = GetWindowThreadProcessId(hWnd, out loginWindowProcId);
// now I can just use .NET to find the Process for me...
Process loginWindowProcess = null;
if (0 != loginWindowProcId)
{
// get the process object
loginWindowProcess = Process.GetProcessById((int)loginWindowProcId);
// This right here is why I wanted the Process structure. It takes a
// little while for the client software to load and be ready. So here
// you wait for the window to be idle so you know it has loaded and can
// receive user input, or in this case keys from "SendKeys".
loginWindowProcess.WaitForInputIdle();
// I use yet another windows API call to make sure that the login window
// is currently in the foreground. This ensures that the keys are sent
// to the right window. Use the handle that we started with.
SetForegroundWindow(hWnd);
// Now send the password to the window. In my case, the user name is
// always there from my windows credentials. So normally I would type in the
// password and press ENTER to login. But here I'll use SendKeys to mimic my
// behavior.
SendKeys.SendWait(password); // send password string
SendKeys.SendWait("{ENTER}"); // send ENTER key
// Now the client should be logging in for you! : )
// IMPORTANT NOTE
// If you are using a console application like I am, you must add a reference to
// System.Windows.Forms to your project and put "using System.Windows.Forms;" in
// your code. This is required to use the "SendKeys" function.
//
// Also this code is just for my testing (quick and dirty), you will want to write
// more checks and catch errors and such. You should probably give the
// WaitForInputIdle a timeout etc...
}
You can check with Process.WaitForInputIdle after you start a process, and wait until is fully started, here is the simple example :
http://msdn.microsoft.com/en-us/library/xb73d10t%28v=vs.71%29.aspx
Try looking at that: http://www.acoolsip.com/a-cool-blog/science-and-technology/151-c-sending-commands-to-independent-windows.html
you can check if the window is shown (using the link) and then sending messages (also on the link)
I would make a tools like Google toolbar translate function, but it is for desktop.
What i want to do is
highlight the text in any application (word,pdf,live messenger etc) , and translate by google translate api ,return as a tool tips.
I have search msdn about monitoring text, i only found using copy&paste and monitoring clipboard to tick the event.
so, any idea about that?
thanks you.
A starting point would be to get a reference to the current foreground window. The code below will get the currently selected window and the title of that window:
[ DllImport("user32.dll") ]
static extern int GetForegroundWindow();
[ DllImport("user32.dll") ]
static extern int GetWindowText(int hWnd, StringBuilder text, int count);
private void GetActiveWindow()
{
const int nChars = 256;
int handle = 0;
StringBuilder Buff = new StringBuilder(nChars);
handle = GetForegroundWindow();
if ( GetWindowText(handle, Buff, nChars) > 0 )
{
this.captionWindowLabel.Text = Buff.ToString();
this.IDWindowLabel.Text = handle.ToString();
}
}
You could run this code within a timer: i.e give the user 10 seconds to select a window.
I am not sure how you would retrieve selected text within a window, but I will look into it for you.
I think you'll need to start by getting the handle of any window that is activated when your program is active. My guess is you need to look into InteropServices here to do this.
Using Windows API.
It sounds like you need to have your code intercept any window handle of any process, this is where it gets a bit complex as you have to ensure you do have access permissions to access another process.
Speaking of which, I do not think it is a good idea as you could end up crashing another process by poking around under the hood in regards to the winapi calls to trap the text selection event, not too mention the fact that you would have to determine if the process has any text selected. The best direction I can give is this...an article was written on how to spy on a process on CodeProject here, this can be a step in the right direction, bear in mind that the code used was for the .NET 1.0 framework.
Hope this helps and good luck in your coding,
Best regards,
Tom.
I am developing a .NET windows app that needs to insert text in the place where the cursor is. The cursor will be in a different application that I have no control over. I think the operating system needs to be used here to achieve this. Can you help please?
Put the text you want to insert into the clipboard
Find the window's handle:
Process[] processes = Process.GetProcessesByName("notepad");
foreach (Process p in processes)
{
IntPtr pFoundWindow = p.MainWindowHandle;
// Do something with the handle...
}
Send a "Ctrl+V" message to the window using pinvoke, see http://www.pinvoke.net/default.aspx/user32.SendMessage
The most easy is to use the SendKeys class on Windows.Forms.
Otherwise use the SendMessage from the windows api to send key by key (some information on this).
Do not use the clipboard, the user typically does not want that, and does not expect that.