I am running some automation in a C# program (.Net 4.0). There is an issue with a modal dialog where I want to click the message away and continue testing. I have tried a few options (SendKey and using Win32 to send a click event with code modified from here: http://msdn.microsoft.com/en-us/magazine/gg309183.aspx. Neither of these have proved to be reliable enough to be considered effective.
My next approach will be to try calling the EndDialog() function from my C# program and simply sending the enumeration/return code to the message box.
EndDialog(HWND hDlg, INT_PTR nResult) is the call where hDlg is the handle to the message box being closed and nResult is the result of the dialog.
Where I am running into an issue is how to send the desired result. An example would be that the return code IDCANCEL has a value of 2. How exactly do I send this value? What variables or constants would I need to declare? I'm just looking for how to get the proper pointer declared to send the desired result to the function.
Further information on these result values can be found here http://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=VS.85).aspx
just invoke PostMessage. Here is a sample in c/c++:
::PostMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,BN_CLICKED), 0);
Related
Im trying to check the content of a toast message using playwright but cant find a suitable way to acheive this.
The playwright documentation lists a suitable way to handle alert messages with which I have been able to do things like retrieve the text content from an alert before dismissing it. For example:
Page.Dialog += (_, dialog) =>
{
alertMessage = dialog.Message;
Console.WriteLine(alertMessage);
dialog.AcceptAsync();
};
prints the alert text content prior to accepting the dialog. This can be extended to perform checks such as asserts etc
I've tried using the same approach when trying to handle the toast message but this doesn't work for me, presumably due to different nature of the toast message.
Has anyone successfully managed to interrogate toast messages using playwright?
There is no official documentation from playwright on how to handle toast messages.
Handling Toast Messages in Automation:
Toast messages are normal html elements within the page(not in alert) however they are special in sense as they appear for a very short time and then disappear so we need to write automation code and handle accordingly. Example Below:
async clickSave() {
await Promise.all([
this.page.waitForSelector(loadPanel),
this.page.click(btn_Save),
this.page.waitForSelector('div[class*="ajs-success"]',{state: 'attached'}) //Toast Success message on save successfully
]);
}
We have a 3rd party login dialog which will skip the login prompt if the login data is passed in via command line arguments. This is used when an application is launched from within the main 3rd party software.
The custom app I am writing should provide users with a button to change their login info, however since the app is launched with the login info provided in the command line args, the login dialog never appears when the button is clicked.
Is it possible to clear or reset Environment.GetCommandLineArgs() from the code?
Edit
I ended up simply restarting the application prior to startup if login info existed in the command line. This makes the 3rd party login dialog actually show up instead of automatically using the login info provided in the command line arguments.
I'm accepting Jim's answer because I feel it is the most complete answer to my question, although Oded's answer is also a viable alternative.
What you're asking can't be done in .NET because the Environment class caches the command line and there's no property accessor for setting it. (More correctly, the startup code caches the command line and Environment.CommandLine calls into the runtime to get that cached value.)
In a native Windows application, the GetCommandLine() API function returns a pointer to the command line that the operating system presented to the program. A program can call CommandLineToArgvW to parse the command line into the standard argv and argc parameters familiar to C and C++ programmers.
The Environment class uses something similar. When you call Environment.GetCommandLineArgs, it accesses the Environment.CommandLine property and then calls the windows function CommandLineToArgvW to parse the command line. But Environment.CommandLine doesn't get its value from GetCommandLine(). Instead, the program gets the Windows command line at startup (by calling GetCommandLine()), and then saves it.
This is unfortunate, because you can modify the value that GetCommandLine returns, as demonstrated by this little snippet:
[DllImport("kernel32")]
static extern IntPtr GetCommandLine();
static void DoIt()
{
IntPtr pcmdline = GetCommandLine();
Console.WriteLine("Environment.CommandLine = {0}", Environment.CommandLine);
string realCmdLine = Marshal.PtrToStringAnsi(pcmdline);
Console.WriteLine("realCmdLine = {0}", realCmdLine);
Console.WriteLine("** Modify command line");
// Modify the command line
byte[] bytes = Encoding.ASCII.GetBytes("ham and swiss on rye\0");
Marshal.Copy(bytes, 0, pcmdline, bytes.Length);
Console.WriteLine("Environment.CommandLine = {0}", Environment.CommandLine);
pcmdline = GetCommandLine();
realCmdLine = Marshal.PtrToStringAnsi(pcmdline);
Console.WriteLine("realCmdLine = {0}", realCmdLine);
}
If you run that, you'll find that Environment.CommandLine returns the same string both times, whereas the second time you call GetCommandLine, you'll get back the string ham and swiss on rye.
Even if the above did work, there's no guarantee that it would solve your problem. The 3rd party control might parse the command line, cache the login information, and never parse the command line again.
You can use Process.Start to start a new instance of the application, providing the new credentials as arguments, and exit the current instance.
Add additional command line argument(s) to indicate this secondary condition. For example, an argument could be ShowLogin. If true, then the command line arguments pre-fill the login dialog and the users could update there information as needed. If false, then the arguments are used to auto log in without showing the dialog.
I am making a little tool like Displayfusion and I need some Hooks to receive messages when Windows move/activate/etc , however I'm stuck..
I am using this project for the CallWndProc hook:
http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx
For pretty much all windows it works great(x86 and x64), however on some windows it seems to can't inject the hook DLL. Currently I am having problems with adobe reader X. No messages are being received from that window. I think it has something to do with the sandbox? Can somebody give me a push in the right direction?
The initialization code for the hook:
bool InitializeCallWndProcHook(int threadID, HWND destination)
{
if (g_appInstance == NULL)
return false;
if (GetProp(GetDesktopWindow(), "WILSON_HOOK_HWND_CALLWNDPROC") != NULL)
SendNotifyMessage((HWND)GetProp(GetDesktopWindow(), "WILSON_HOOK_HWND_CALLWNDPROC"), RegisterWindowMessage("WILSON_HOOK_CALLWNDPROC_REPLACED"), 0, 0);
SetProp(GetDesktopWindow(), "WILSON_HOOK_HWND_CALLWNDPROC", destination);
hookCallWndProc = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProcHookCallback, g_appInstance, threadID);
return hookCallWndProc != NULL;
}
Hmm, try if Spy++ can catch the messages. If it can, then obviously it's not a problem with security measures. It Spy++ can't however, then it's pretty much impossible.
See if this works: Use both WH_CALLWNDPROC and WH_GETMESSAGE hooks, since apparently, the former only catches sent message, and the latter only catches posted messages.
I have a similar Problem in my application. Visit the following link:
Strange behaviour of windows hooks
My guess ist that an application interrupts the filter function chain by not calling the CallNextHookEx method. Note that is this only possible when you are using WH_CBT hooks.
I am writing a C# WPF program which sends text messages to another program's window. I have a macro program as part of my keyboard drivers (Logitech g15) which already does this, though it does not send keystrokes directly to the process, but to the currently focused window. It works well but i need to be able to send inputs from my program as well. There are other people using the process so the input text messages from my program needs to be fast enough so that my text does not interfere with their input.
The problem is that when I try to do this with a c# program I get too much delay. The macro program (Logitech G-Series Profiler) sends a command instantly. I have tried the following three commands for sending messages to process. (Listed by order of slowest to fastest)
SetForegroundWindow(_hWnd);
SendKeys.SendWait("{Enter}This is a keystroke input.{Enter}");
It is probably in the name, but this performs the command so slowly that I can actually follow with my eyes the text as it is input letter by letter. I have tried using the “SendKeys.Send” method but I get an error saying: “SendKeys cannot run inside this application because the application is not handling Windows messages.”
PostMessage((IntPtr)_hWnd, (uint)WMessages.WM_KEYUP, (int)key, (int)key);
PostMessage is a bit faster but still not fast enough for the purpose of my program. Besides the method returns before the message has been read by the process, which means two sequential PostMessage calls may not send sequential messages.
SendMessage(_hWnd, 0x100, (int) VKeys.VK_2, (int) VKeys.VK_2);
This is faster than the PostMessage but not nearly as fast as the macro program from Logitech. Also, the receiving program handles the input strangely, apparently not treating it the same way it does "genuine" input from the keyboard.
SetForegroundWindow(_hWnd);
const string text = "This is a keystroke input.";
IInputElement target = Keyboard.FocusedElement;
IInputElement target = InputManager.Current.PrimaryKeyboardDevice.FocusedElement;
var routedEvent = TextCompositionManager.TextInputEvent;
target.RaiseEvent(new TextCompositionEventArgs(InputManager.Current.PrimaryKeyboardDevice, new TextComposition(InputManager.Current, target, text)) { RoutedEvent = routedEvent });
This is the last thing I have tried. It seems instant with the way the text is sent to a process. However, I have only been able to send this to my own program since Keyboard.FocusedElement returns null when I have another program set as foreground window.
If someone can tell me how to get an IInputElement of another window I would sure like to know. Alternatively, if someone has a suggestion for a better method of sending input, I would dearly like to hear it.
Specs: Windows 7, 64bit
Visual Studio 2010, Framework 4
First of all, are you intentionally using WM_KEYDOWN (0x0100) instead of WM_KEYUP (0x0101) in your SendMessage example? This would just press the keys, and never release them, so the application would not process them properly.
Another way worth trying would be to send WM_SETTEXT, assuming the control interprets it correctly (like edit controls or combo boxes).
A last option would be to use SendInput which synthesizes keyboard and mouse input on a very low level, but similarly to you keyboard's macro program, this requires you to activate the correct window and set the focus, which can be quite painful.
Depending on your other's program window type, you could use UI Automation. See this example here:
Add Content to a Text Box Using UI Automation
I'm getting in trouble by hooking window messages. I need to detect window text (caption) changes, so I intercept the WM_SETTEXT message for the interesting windows (I do so because at window creation the window caption is not specified).
Reading the documentation of the WM_SETTEXT documentation, the lParam parameter specify a pointer to the string representing the window text.
The message is forwarded to a .NET application using SendMessage. What I do in the .NET application is:
private static bool ProcessMessage(ref Message msg) {
...
string s = Marshal.PtrToStringAuto(msg.LParam) *
}
where ProcessMessage is the routine handling messages of the .NET form.
What I always get is an empty string, which is not the expected result. I tried other Marshal.PtrToString* methods, but no one has worked.
What am I doing wrong in the conversion of a IntPtr to String?
(*)Note that I cannot debug this code, since it would block the entire system, since all windows messages are intercepted.
LParam is a string pointer, and your code is correct, assuming that it is executed in the same process where WM_SETTEXT message was sent. In another process, this pointer is invalid, and result of using this pointer is undefined.
It is probably a pointer to a pointer of chars.
So read the IntPtr, the read the value in IntPtr which is also IntPtr, then use that as you did.
Maybe it works, maybe it doesn't :p