emulate input for dos application - c#

i have to input some data into an really old dos application and wanted to automate this. first i tried SendKeys, which failed, after that i tried the InputSimulator (inputsimulator.codeplex.com) which failed too. It works in any other Application (even cmd...) but not in the application i want to...
sample code i used:
InputSimulator.SimulateTextEntry("test");
InputSimulator.SimulateKeyDown(VirtualKeyCode.F1);
InputSimulator.SimulateKeyUp(VirtualKeyCode.F1);
i also tried it with SimulateKeyPress, same results :(
can someone please give me some hints?
Target System: Win XP
Screen of the app:
http://images.devs-on.net/Image/wxhZouyZdwemgTRp-Bereich.png
EDIT1: is it possible to start the .bat from my application and stdin the input?
EDIT2: as Boluc Papuccuoglu pointed out the stdin approach won't work. so is there anyway to code a working keystrokes emulating function?
EDIT3: with keybd_event i got it to write to the application. BUT... i tried it with
public const int A = 0x41;
public const int C = 0x43;
keybd_event(A, 0, KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(A, 0, KEYEVENTF_KEYUP, 0);
System.Threading.Thread.Sleep(1000);
keybd_event(C, 0, KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(C, 0, KEYEVENTF_KEYUP, 0);
but i only get 2 times "a".
EDIT4: doesn't matter which Virtual Key i give to keybd_event, he is always writing "a" and nothing else. seems like i have to do it the old fashioned aka manual way.
EDIT5: so yeah, manual entry sucked, so i decided to give autoit a try and it works. WTF? maybe someone can explain me how autoits way of sending keys to a program is different then sendkeys, inputsimulator and keybd_event.

Unfortunately the stdin approach probably will not work. From what I can see in the screenshot, the application most probably acts on keypresses, not the contents of the input stream.

Related

Take screenshot of external OpenGL game C# with BitBlt (CopyFromScreen)

I am trying to create some kind of antycheat for counter strike (hl) game. Of course funcionality of making a screenshot in-game is built-in, but exploited (detected) by antyss applications, so every time screenshot is taken from the game, antyss is disabling the cheats (so that no cheats are visible on the screenshots)
For the last few days, I've read dozens of threads regarding this topic. Most of them are outdated and are using libraries, that are obsolete right now.
I've read about the approach with mirage driver (which is not working on windows 10), about injecting to the application (of course application/game is not part of my code) and using/incjeting some code with OPEN GL/D3D library (to read backbuffer). Probably this could be in the end the only solution.
But right now I have almost a working solution. I write "almost" because it is working but giving me only some kind of "cached" data. It is giving me a correct screenshot, but if I take another screenshot - still the same screenshot is taken as last time. If while being in-game I minimize the application (full-screen mode) and then get back to the game, the new screenshot taken will have up to date screenshot, but then again, the next screenshot would be exactly the same.
I don't know if it is "by design" or is it "some sort of bug" Nevertheless my question is: Can I force somehow this "reloading" without having to programmatically call some kind of "alt+tab" and then focusing on the application once again?
In this topic:
How to take screenshots of a game with OpenGL
#Andon M. Coleman wrote:
Are you on Windows? In fullscreen mode starting with Windows Vista, there is trouble with anything that tries to capture the front-buffer (including the built-in Alt + PrintScreen). The easiest solution is to change your buffer swap behavior to Copy Swap (PFD_SWAP_COPY, slower but guaranteed to work). Often if you Alt+TAB out and back in after making the fullscreen mode switch that will fix it too; though I have never been able to explain that ;) If you did not write the game in the question, then the second solution may be your only choice if you want to use that code.
This is exactly the problem I am facing. As he wrote: "Alt+Tab" is fixing the problem (although he did not know whether it is a feature or a bug) He proposed to change the buffer swap behavior to Copy Swap(PFD_SWAP_COPY) Any tips on how to change my code with that will also be most welcome (I can try this one) But if I understood correctly, this approach is the viable solution only if you can change this in the game (and this is not my case)
Here is my working code (which in topics about such scenarios was claiming that in this approach the screenshot is BLACK. But it is working for me)
private const int SW_RESTORE = 9;
public void TakeScreenShot()
{
var guid = Guid.NewGuid();
string procName = "hl";
Process proc;
try
{
proc = Process.GetProcessesByName(procName)[0];
}
catch (IndexOutOfRangeException e)
{
return;
}
// Focus on the application
SetForegroundWindow(proc.MainWindowHandle);
ShowWindow(proc.MainWindowHandle, SW_RESTORE);
Thread.Sleep(1000);
Rect rect = new Rect();
IntPtr error = GetWindowRect(proc.MainWindowHandle, ref rect);
while (error == (IntPtr)0)
{
error = GetWindowRect(proc.MainWindowHandle, ref rect);
}
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
using (Bitmap printscreen = new Bitmap(width, height, PixelFormat.Format32bppArgb))
{
using (var graphics = Graphics.FromImage(printscreen))
{
graphics.CopyFromScreen(rect.left,
rect.top,
0,
0,
new Size(width, height),
CopyPixelOperation.SourceCopy);
printscreen.Save($#"{Path.GetTempPath()}\{guid.ToString()}.jpg", ImageFormat.Jpeg);
}
}
}
I want this application to work on Windows7, Windows8, Windows 10. The best would be to cover full screen and windowed mode (but fullscreen is probably more important)
Any advice how to proceed (or why I am getting the "cached" data) would be nice :)
Of course if someone will say (with full authority), that what i want to achieve is impossible with CopyFromScreen (and there is no hack to fix that, apart from minimizing and maximazing the screen) i will consider option with injecting the code. But normally i would want to stay away from this one, as this could be treated as cheat and can lead to VAC ban.
====== UPDATE ======
You can try reproduce the process of taking screenshot by downloading the game (is small one, 260 MB):
https://cssetti.pl/Api/GameDownload.php?GameDownloadId=v43
Then you can copy-paste my code to Linqpad (or any other editor) and run the code. The application after launching will launch the HL process which is then use to try to grab the screenshot.
====== UPDATE 2 ======
In windows mode everything works correctly (the printscreens are ok)

Randomly strange behaviour when using select() with timeout on Windows

I'm using a tool to communicate with a gameserver. To establish the connection with the gameserver I'm sending a login packet and then go on from there. I also used a tool, that does the same, but which is written by someone else in C# with a pre-made library. This app has some issues with stackoverflow exceptions after using it for hours and porting it linux isn't much fun aswell, therefore I decided to write my own application from scratch in C++.
My script pretty much looks like this:
while (!connected) {
if (connectCounter == 0)
std::cout << "Trying to connect..." << std::flush;
else
std::cout << "." << std::flush; // add point
connectCounter++;
int selectSize = 0;
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
fd_set fds;
FD_ZERO(&fds);
FD_SET(mysocket, &fds);
selectSize = select(mysocket + 1, &fds, 0, 0, &timeout);
if (selectSize == 1) {
// we might now be logged in, check routines
connected = true;
}
}
Now there's a "bug" randomly happening to me in both applications, the one written by someone else in C# and in my own one. I should probably mention that I've never had this behaviour before, but sinced I formatted my computer I saw this issue happpening for the first time.
Issue: Gameserver was offline for some hours, computer was probably freshly booted. Gameserver is still down and I start the application. Now it tries to login but won't have success as the gameserver is still offline. Now it writes "Trying to connect". Because of the timeout settings it should wait 5 seconds and then add 1 point after every unsuccessful try. Instead it fires point after point without waiting for the timeout. This happens in both application, the C# app written by someone else and in my own application. In both applications it only happens randomly and not every time I'm starting the application. As I mentioned I've never experienced this issues before formatting my computer. I also ported this application to my linux server and didn't not experience that behaviour on linux. A friend of mine also uses both applications and never reported that kind of issue to me.
This is so strange to me and I can't figure out the reason for it. From what I get this can't really be code related because it happens in two totally different applications and from what I can tell only since I reinstalled Windows.
EDIT 1: Now I found something interesting, I added the following code on windows and linux:
selectSize = select(mysocket + 1, &fds, 0, 0, &timeout);
std::cout << selectSize << std::cout;
Interesting thing is that on Windows my console will now output: Trying to connect...0.1.0.1.0.1.0.1
Restarted the application and it outputs Trying to connect...0.0.0.0.0.1
On linux it always returns Trying to connect...0.0.0.0.0, never ever with a false positive.
Still only happening on windows. Don't even know what approach the guy from the C# application used but there it's the same problem happening randomly after reinstalling windows.
EDIT 2: I guess I found the problem.
Before the timeout settings and select() I'm doing a sendto() with my login packet. I guess for whatever reason there is something incoming in return, so that selectSize might change to 1 in some cases. Is it possible that this is causing the issue on Windows, while its working on linux?
Quoting from "the" POSIX specification (a copy of it online):
A descriptor shall be considered ready for reading when a call to an input function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully. (The function might return data, an end-of-file indication, or an error other than one indicating that it is blocked, and in each of these cases the descriptor shall be considered ready for reading.)
So I'd say in order to fix your code you must additionally check whether file descriptors that are "ready for reading" don't have any error or eof indication.
To check if the socket is connected, you should check it for writability, not readability. Change
selectSize = select(mysocket + 1, &fds, 0, 0, &timeout);
to
selectSize = select(mysocket + 1, 0, &fds, 0, &timeout);
Okay, so it seems that I finally found at least a partial answer to my initial question, why linux gives me a working result while windows breaks my application. From what I have read on windows platforms select() returns WSAECONNECTRESET instead of blocking or timeout, see: WinSock Recvfrom() now returns WSAECONNRESET instead of blocking or timing out
So this seems to be the reason why the application is working perfectly fine (for my purposes) on linux, where select() still seems to return a timeout while Windows returns that error and breaks my application to a certain extent.
Solution:
So I finally found a fix. Special thanks to the guy who reminded me to use Wireshark. At first I tought the select() giving back 1 when it should be 0 after sending the login packet to gameserver while it's offline is totally random but in fact I found out that from time to time I get a "ICMP port unreachable", this caused select() to return 1 instead of 0 (see the link above) Obviously I only want select() to return 1 when an actual login reponse is coming from the sever. On linux this works out of the box and doesn't cause any problems.
For Windows I found a simple fix by adding this code before the select() function:
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12)
DWORD lpcbBytesReturned = 0;
BOOL lpvInBuffer = FALSE;
WSAIoctl(mysocket, SIO_UDP_CONNRESET, &lpvInBuffer, sizeof(lpvInBuffer), NULL, 0, &lpcbBytesReturned, NULL, NULL);

Sendkeys.send send alt+space+n combination

The title pretty much explains question. I want to sen alt+space+n combination via Senkeys.send method, how this could be done? So far I've tried SendKeys.Send("% N"); but it's not working.
Spacebar isn't a traditional modifier key, so I believe you will need to send the keyUp and keyDown events seperately.
I'm not completely familiar with C# sendkeys, since I use the AutoIt library for this kind of thing, with AutoIt the commands would be something like:
private void pressAltSpaceN()
{
AutoItX3Declarations.AU3_Send("{alt down}", 0);
AutoItX3Declarations.AU3_Send("{space down}", 0);
AutoItX3Declarations.AU3_Send("{n down}", 0);
AutoItX3Declarations.AU3_Send("{n up}", 0);
AutoItX3Declarations.AU3_Send("{space up}", 0);
AutoItX3Declarations.AU3_Send("{alt up}", 0);
}
Hopefully someone else can tell how to send keyUp and keyDown events using SendKeys, otherwise you can learn how to integrate AutoIt into C# using the answer to this question: link.
The string you're using should work. Perhaps the default journaling hook doesn't work with the application you're trying to minimize. You could try using the alternate method using app.config and SendInput (see here).
A better way to solve the problem would be to obtain a handle to the focused window using GetActiveWindow, then call ShowWindowAsync and pass in a ShowWindowCommand value of 2.

How to make keybd_event handle more than two key presses at once?

Im using keybd_event win api call in C# and i want to simulate special key presses, like alt+f4, alt+tab and similar. My program can handle "simple" key presses, like shift+p, altgr+w and simple use of tab, or enter are also working, but when two special buttons present (for special buttons i mean alt, shift, ctrl or functional buttons) it seems it does nothing. My program should handle multiple forms through remote desktop, thats why im using this keybd_event call, but for example alt+f4 doesnt work even locally (im testing on a notepad, but i cannot close it with this command). Anyone has idea what am i doing wrong? Is it even possible to make them work?
Thanks in advance!
Edit:
I have created a DLLImport class in which i stored all the win api calls. I also have some helper methods, for example:
private void PressAlt()
{
DLLImport.keybd_event(0xA0, 0x38, 0, 0);
}
private void ReleaseAlt()
{
DLLImport.keybd_event(0xA0, 0x38, 0x0002, 0);
}
For tab, im using this in a separate method:
DLLImport.keybd_event(0x09, 0x0f, 0, 0); //press tab
...
DLLImport.keybd_event(0x09, 0x0f, 0x0002, 0); //release tab
And im now testing it with:
PressAlt();
PressSpecial("tab");
ReleaseSpecial("tab");
ReleaseAlt();
From the code you posted, it looks like you have the wrong values for at least one of the virtual key codes (MSDN reference here).
For example, the code 0xA0 is the Left Shift key (VK_LSHIFT), you should try 0x12 (VK_MENU) or 0xA4 (VK_LMENU) instead.
Note - there is a useful summary of common virtual key codes and scan codes on CodeProject.

How to make form system modal using C#?

I need to show form as top level system-wide, e.g. over /all/ other windows on screen. I do realize this is usually /bad UI practice/, but I have very specific scenario in mind.
We intend to use normal Windows PCs for POS cash registrators. There is an option on the screen to open cash drawer. It would be rather bad for someone just to press something on a screen and get access to money when clerk isn't looking. So we equiped PCs with RFID readers and each clerk has his/her own RFID card which will be used for authentication.
I need however an mechanism to lock the computer (or make it unusable) when clerk goes away. Logging off seems too much of a nuisance.
Any ideas welcome.
LP,
Dejan
Well, after a day of trial and error I came to sort of solution.
It involves the following steps:
1.
When "Lock" button is pressed new (empty) /desktop/ is created.
Program is run in this desktop with full screen form and login procedure.
There is nothing else to switch to or run on this desktop.
2.
Task manager is disabled via registry.
Of course, somebody uninvited can still access the Ctrl-Alt-Delete menu, but there is nothing of particular harm he can do there.
3.
Alt-F4 and such are disabled.
4.
When authentication is made, program switches back to original desktop and everything proceeds as normal.
There is some P/Invoking required, of course.
If someone wants to do something similar, perhaps s/he will find my bare bones example helpful - link text
LP,
Dejan
I think you'll need to look into calling down to the Win32 API to achieve this.
You'll need to look into:
ShowWindow
and
SetWindowPos
and invoke them with code similar to the following (note this is pseudo-code):
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void ShowTopmost(Form frm)
{
ShowWindow(frm.Handle, SW_SHOWMAXIMIZED);
SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
0, 0, [width of desktop], [height of desktop],
SWP_SHOWWINDOW);
}
Form has a TopMost property.
set Form.TopMost = true

Categories

Resources