Apologies if this is a stupid question; I'm not overly familiar with Visual Studio and definitely not the new version.
I am trying to hook calls to TextOutA from a Windows application using EasyHook, roughly following this tutorial, in Visual Studio 2019. (I am 100% certain that they are TextOutA; decompiler output indicates as much, and I was able to successfully hook them using C++. Unfortunately C# is far more supported/documented than C++ for EasyHook.)
Per the tutorial I have a console application and a class library as two projects in the same solution. Getting the Visual Studio solution to compile at all was somewhat bumpy -- I had to manually edit the .csproj files to .NET Framework 4.8 (per this question) and it took some tinkering to get it working. But now I am worried that I have tinkered too much.
What happens: The code compiles without errors and warnings, and seemingly runs successfully. However, nothing in the DLL seems to be called; none of its code appears to be executed, a breakpoint in Run() is never hit, and it still compiles if I just get rid of the Run() code entirely.
This is the console app code, so far (filenames redacted; there may well be other issues with this code but I'd have to run it to find out):
static void Main(string[] args)
{
string injectionLibrary = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "[name of DLL].dll");
Console.WriteLine(injectionLibrary);
try
{
Int32 processID = 0;
Process[] process = Process.GetProcessesByName("[process name]");
Console.Write(process[0]);
processID = process[0].Id;
EasyHook.RemoteHooking.Inject(
processID, // ID of process to inject into
injectionLibrary, // 32-bit library to inject (if target is 32-bit)
injectionLibrary, // 64-bit library to inject (if target is 64-bit)
null // the parameters to pass into injected library
// ...
);
Console.WriteLine("Injected, supposedly.");
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("There was an error while injecting into target: ");
Console.ResetColor();
Console.WriteLine(e.ToString());
}
Console.ReadKey();
}
}
}
And this is the class library:
namespace [DLL name]
{
public class MySimpleEntryPoint : EasyHook.IEntryPoint
{
public MySimpleEntryPoint(EasyHook.RemoteHooking.IContext context)
{
}
public void Run(EasyHook.RemoteHooking.IContext context)
{
Console.Write("Test");
var textOutHook = EasyHook.LocalHook.Create(
EasyHook.LocalHook.GetProcAddress("Gdi32.dll", "TextOutA"),
new TextOutDelegate(TextOut_Hook),
this);
textOutHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
}
[UnmanagedFunctionPointer(CallingConvention.StdCall,
CharSet = CharSet.Unicode,
SetLastError = true)]
delegate bool TextOutDelegate(IntPtr orig_handle, int x_value, int y_value, string output_string, int color);
[DllImport("gdi32.dll", CharSet = CharSet.Unicode, EntryPoint = "TextOutA", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
static extern bool TextOutA(IntPtr orig_handle, int x_value, int y_value, string lpString, int color);
bool TextOut_Hook(IntPtr orig_handle, int x_value, int y_value, string output_string, int color)
{
// We aren't going to call the original at all... YET
Console.Write("...intercepted...");
return false;
}
}
}
The console output for the process is as expected, and so is the output of the path:
C:\Users[my username]\source\repos[name of project]\build\net48\ [name of DLL].dll -- which is indeed where the dll is output to. But, as above, nothing in Run() seems to actually be called, TextOutA certainly isn't being suppressed, etc.
What I have tried:
Adding both the .dll and the class library project (separately) as references to the console app
Setting both the .dll and the executable to output to the same folder
Tweaking the line of code that supposedly gets the path
Comparing this code to basically any comparable EasyHook projects I can find, nothing seems obviously amiss
Calling GetProcAddress from within the console app and not the hook; it works as expected, so the problem doesn't seem to be that
Any help would be much appreciated.
Answer as per my comment.
There are two things happening in your example:
when Run exits your hooks are likely to be cleaned up by the GC and therefore uninstalled
when Run exits EasyHook will unload your assembly
The managed EasyHook helper library EasyLoad runs your IEntryPoint.Run method within a new thread and waits for it to exit. When the method exits the assembly is unloaded etc.
Therefore you should add a while loop at the end of your Run method to prevent it exiting until you are finished with your hooks.
public void Run(EasyHook.RemoteHooking.IContext context)
{
// install hooks
...
while (true) {
Thread.Sleep(500);
// optionally perform a check to see if should break
}
// uninstall hooks / cleanup / etc
}
Related
Is there a way to kill a process with a C# script and have the process's exit code equal 0? I tried using Process.Kill() but that returns exit code -1. I am accessing getting the Excel process with the Process.GetProcessesByName() function. It looks like there is a Win32 API function TerminateProcess that takes an Exit Code as a parameter but I can't find anything equivalent in the Process class.
Edit:
Interesting discovery- when I find the Excel process in the Windows task manager then click "End task" the Excel process exits with code 0. So, it appears that the signal that the Task Manager sends to the process is different then System.Diagnostics.Kill(). Now I just need to figure out what signal the Task Manager is sending and send it.
I solved my problem even though it's a bit dirty. If someone knows a way to do it without DllImport it might be useful to share. Here's what I did:
class MyClass
{
[DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
public static extern bool TerminateProcess(IntPtr proc, uint uExit);
public void MyFunction()
{
foreach (var process in Process.GetProcesssesByName("Excel")
{
TerminateProcess(my_process.Handle, 0);
}
}
}
I couldn't come up with a better more descriptive title as it involves 3 languages which I'll explain now.
I wrote a C++ wrapper around a Python module, which works just fine in C++ by the way. I made a DLL out of this wrapper and exposed some functionalities as a C and used them in a C# application.
The issue is, the C# application just hangs if I do not display the webcam feed.
That is in Python module there is this condition:
if self.debug_show_feed:
cv2.imshow('service core face Capture', frame)
and when set True, will display the webcam feed.
This is mostly a debug thing I put and for actual production it needs to be disabled. On C++ its fine
I can set this to false (through the constructor) and all is fine.
However, On C#, this behavior doesn't happen, if I try to use the module without setting the webcam feed to true, The C# app hangs, and that's because the Start() which calls the main operation becomes a blocking call and none of the callbacks are returned.
my DllImport are as follows by the way:
[DllImport(#"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Initialize(bool showFeed);
[DllImport(#"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Start(bool async);
[DllImport(#"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Stop();
[DllImport(#"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetCpuAffinity(int mask);
public delegate void CallbackDelegate(bool status, string message);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[DllImport(#"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void AddCallback(IntPtr fn);
[DllImport(#"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void RemoveCallback(IntPtr fn);
And this is my C# callback:
private CallbackDelegate del;
public void SetUpCallback()
{
txtLog.Text += "Registering C# callback...\r\n";
del = new CallbackDelegate(callback01);
AddCallback(Marshal.GetFunctionPointerForDelegate(del));
txtLog.Text += "Calling passed C++ callback...\r\n";
}
bool status;
string id;
public void callback01(bool status, string id)
{
this.status = status;
this.id = id;
}
And this is the main python modules that are executed :
def start(self):
try:
self.is_running = True
self._main_loop()
except Exception as ex:
path='exceptions-servicecore.log'
track = traceback.format_exc()
exception_time = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
with open(path, 'a') as f:
f.writelines(f'\n{exception_time} : exception occured {ex.args} \n{track}')
def start_async(self):
st = threading.Thread(target=self.start)
st.start()
def _main_loop(self):
name = None
is_valid = False
while self.is_running and self.cap.isOpened():
is_success, frame = self.cap.read()
if is_success:
name="sth"
is_valid=True
self._execute_callbacks(is_valid, name, frame)
self._execute_c_callbacks(is_valid, name)
if self.debug_show_feed:
cv2.imshow('service core face Capture', frame)
if self.save:
self.video_writer.write(frame)
if (cv2.waitKey(1)&0xFF == ord('q')) or (not self.is_running):
break
self.cap.release()
if self.save:
self.video_writer.release()
cv2.destroyAllWindows()
Knowing this only happens in C# and not C++, I may have some issues in my marshaling or the way I'm trying to use the C# callback in this scenario.
Here is a Visual Studio with a minimal example that demonstrates this: https://workupload.com/file/epsgzmMMVMY
What is the problem here? Why is cv.imshow() causes this behavior?
I found the reason why callbacks on C# side didn't output anything. The callbacks are all executing as they should, but since the main loop on Python side is a blocking method, they only start their execution when the blocking method is over (just like a recursive function where the outputs don't get to be returned until the very end).
I then noticed cv2.imshow() creates a short pause and in that time, the C# client gets the chance to update the output and what it has been sent to. I first tried to pause the current running thread in Python, and it actually kind of worked, the output started to popup on C# side, but still the app was not responsive.
I noticed I can actually make the callback outputs show up in C# by simply using a cv2.waitkey(1) or cv2.imread('') in the else clause when showFeed is False:
while (self.is_running):
...
if self.showFeed:
cv2.imshow("image", frame)
else:
#cv2.imread('')
# or
cv2.waitkey(1)
...
And by writing :
while (self.is_running):
...
if self.showFeed:
cv2.imshow("image", frame)
else:
cv2.namedWindow('image', cv2.WINDOW_OPENGL)
cv2.waitKey(1)
cv2.destroyAllWindows()
...
The outputs are showing just fine and the application is responsive again, However, constantly creating and destroying an empty Opencv window is not a solution as it flickers and is just very bad.
I need to add that, using a timer() control event on c# to print the output and keep the app responsive doesn't work, creating a new thread also doesn't seem to work. it seems the marshaled callbacks this way can't be used like this (I am happy to hear that I am wrong though).
I'll update this answer when I find better solutions than these both C# wise (running the callbacks on a thread) or on Python side, making a visible window or altogether fix this issue.
Update
I removed the changes on Python side and implemented the threading on C# part. The reason the initial threading didn't work was because, all interops had to be called in the same thread, meaning all of the imported methods such as Initialize, Start and AddCallback had to be setup and run from within the same thread.
I'm studying C# by following the guides in MSDN.
Now, I just tried the Example 1 (here is the link to MSDN), and I've encountered an issue: why is the console window closing immediately once displayed my output?
using System;
public class Hello1
{
public static int Main()
{
Console.WriteLine("Hello, World!");
return 0;
}
}
the issue here is that their Hello World Program is showing up then it would immediately close.
why is that?
Because it's finished. When console applications have completed executing and return from their main method, the associated console window automatically closes. This is expected behavior.
If you want to keep it open for debugging purposes, you'll need to instruct the computer to wait for a key press before ending the app and closing the window.
The Console.ReadLine method is one way of doing that. Adding this line to the end of your code (just before the return statement) will cause the application to wait for you to press a key before exiting.
Alternatively, you could start the application without the debugger attached by pressing Ctrl+F5 from within the Visual Studio environment, but this has the obvious disadvantage of preventing you from using the debugging features, which you probably want at your disposal when writing an application.
The best compromise is probably to call the Console.ReadLine method only when debugging the application by wrapping it in a preprocessor directive. Something like:
#if DEBUG
Console.WriteLine("Press enter to close...");
Console.ReadLine();
#endif
You might also want the window to stay open if an uncaught exception was thrown. To do that you can put the Console.ReadLine(); in a finally block:
#if DEBUG
try
{
//...
}
finally
{
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
#endif
Instead of using
Console.Readline()
Console.Read()
Console.ReadKey()
you can run your program using Ctrl+F5 (if you are in Visual Studio). Then Visual Studio will keep the console window open, until you press a key.
Note: You cannot debug your code in this approach.
I assume the reason you don't want it to close in Debug mode, is because you want to look at the values of variables etc. So it's probably best to just insert a break-point on the closing "}" of the main function.
If you don't need to debug, then Ctrl-F5 is the best option.
This behaves the same for CtrlF5 or F5.
Place immediately before end of Main method.
using System.Diagnostics;
private static void Main(string[] args) {
DoWork();
if (Debugger.IsAttached) {
Console.WriteLine("Press any key to continue . . .");
Console.ReadKey();
}
}
In Visual Studio 2019 for .NET Core projects the console doesn't close automatically by default. You can configure the behaviour through menu Tools → Options → Debugging → General → Automatically close the console when debugging stops. If you get your console window automatically closing, check if the mentioned setting is not set.
The same applies to the .NET Framework new style console projects:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
</Project>
The old style .NET Framework project still unconditionally close the console at the end (as of Visual Studio 16.0.1).
Reference: .NET Core tooling update for Visual Studio 2019 Preview 2
If you want to keep your application opened, you have to do something in order to keep its process alive. The below example is the simplest one, to be put at the end of your program:
while (true) ;
However, it'll cause the CPU to overload, as it's therefore forced to iterate infinitely.
At this point, you can opt to use System.Windows.Forms.Application class (but it requires you to add System.Windows.Forms reference):
Application.Run();
This doesn't leak CPU and works successfully.
In order to avoid to add System.Windows.Forms reference, you can use a simple trick, the so-called spin waiting, importing System.Threading:
SpinWait.SpinUntil(() => false);
This also works perfectly, and it basically consists of a while loop with a negated condition that is returned by the above lambda method. Why isn't this overloading CPU? You can look at the source code here; anyway, it basically waits some CPU cycle before iterating over.
You can also create a message looper, which peeks the pending messages from the system and processes each of them before passing to the next iteration, as follows:
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "PeekMessage")]
public static extern int PeekMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg);
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "GetMessage")]
public static extern int GetMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, int wMsgFilterMax);
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "TranslateMessage")]
public static extern int TranslateMessage(ref NativeMessage lpMsg);
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "DispatchMessage")]
public static extern int DispatchMessage(ref NativeMessage lpMsg);
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode]
public static bool ProcessMessageOnce()
{
NativeMessage message = new NativeMessage();
if (!IsMessagePending(out message))
return true;
if (GetMessage(out message, IntPtr.Zero, 0, 0) == -1)
return true;
Message frameworkMessage = new Message()
{
HWnd = message.handle,
LParam = message.lParam,
WParam = message.wParam,
Msg = (int)message.msg
};
if (Application.FilterMessage(ref frameworkMessage))
return true;
TranslateMessage(ref message);
DispatchMessage(ref message);
return false;
}
Then, you can loop safely by doing something like this:
while (true)
ProcessMessageOnce();
The program immediately closes because there's nothing stopping it from closing. Insert a breakpoint at return 0; or add Console.Read(); before return 0; to prevent the program from closing.
Alternatively, you can delay the closing using the following code:
System.Threading.Thread.Sleep(1000);
Note the Sleep is using milliseconds.
Another way is to use Debugger.Break() before returning from Main method
The code is finished, to continue you need to add this:
Console.ReadLine();
or
Console.Read();
Use Console.Read(); to prevent the program from closing, but make sure you add the Console.Read(); code before return statement, or else it will be a unreachable code .
Console.Read();
return 0;
check this Console.Read
Add The Read method to show the output.
Console.WriteLine("Hello, World!");
Console.Read();
return 0;
Here is a way to do it without involving Console:
var endlessTask = new TaskCompletionSource<bool>().Task;
endlessTask.Wait();
Tools -> Options -> Debugging -> General -> Automatically close the console (5th last option)
Check the box and close.
This applied to all projects.
The program is closing as soon as its execution is complete.
In this case when you return 0;. This is expected functionality.
If you want to see the output then either run it in a terminal manually or set a wait at the end of the program so that it will stay open for a few seconds (using the threading library).
I have a C console application which used to be run in the foreground in a CMD terminal in Windows and take user keystroke inputs. However it now needs to be moved to the background and requires no user input.
I have created a system tray, which is implemented correctly with a right click exit and right click about. And have a terminal program which does the functionality.
Rather than rewritting the program again I would like to be able to create a thread which calls the functions from my existing program which are do not require the terminal.
Just to stress the point the console interactive aspects have been removed from the code as have the applications response to keystrokes etc. Hopefully this clarifies things slightly.
Question: Is this possible? And how would I be able to implement this?
(I am generally not a PC programmer using more embedded C so .NET is quite foreign to me. Any help is greatly appreciated)
I'm not sure if this is what you are asking, but if you are asking if you can call functions from your C program from a C# application, then you can. So long as you have the source code to your C program. In order for functions in C to be available to a C# program, they must be exported. I will show you an example:
MyAddDll.h
#include <iostream>
extern "C"
{
__declspec(dllexport) int Add(int a, int b);
}
Whats important here is that your function is wrapped in an extern "C" block. Basically, this tells the compiler not to mangle the name of your function. The other important piece is __declspec(dllexport). This tells the compiler that you want to export this function so it can be called from another program (like your C# program).
MyAddDll.cpp
#include <iostream>
#include "MyAddDll.h"
extern "C"
{
__declspec(dllexport) int Add(int a, int b)
{
return (a + b);
}
}
Again, your code gets wrapped in an extern "C" block and you need to add __declspec(dllexport) to the function. Now you can compile this either into a DLL file or an EXE file. Now to call it from C#, its pretty straight forward:
MyProgram.cs
class Program
{
[DllImport("c:\\PathToMyDllOrExeFile\\MyAddDll.dll")]
public static extern int Add(int val1, int val2);
static void Main(string[] args)
{
int val1 = 12;
int val2 = 4;
Console.WriteLine("{0} + {1} = {2}", val1, val2, Add(val1, val2));
}
}
That's all there is!
One "gotcha" though is make sure your C program and your C# program are both compiled as either 32-bit or 64-bit. You can't compile your C program as 64-bit and your C# program as 32-bit. They must both be using the same bit length.
As already posted, you could use the Process.Start from your C# application tray.
// Uses the ProcessStartInfo class to start new processes,
// both in a minimized mode.
void OpenWithStartInfo()
{
ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Minimized;
Process.Start(startInfo);
startInfo.Arguments = "www.northwindtraders.com";
Process.Start(startInfo);
}
http://msdn.microsoft.com/en-us/library/53ezey2s(v=vs.110).aspx
You could try launching it on a hidden state: http://msdn.microsoft.com/en-us/library/system.diagnostics.processwindowstyle(v=vs.110).aspx
Some programmers are telling to be careful. If any input is expected, then probably your process might halt. make sure nothing really stops your program.
You could try to start a cmd command with Process.Start also, but I would say it is just too much. This would start another process without your C# tray application control:
Process.Start("start /min cmd /c mycommand");
You could start your C program from .NET code via System.Diagnostics.Process. It will be run in a separate process.
You can kill the process from .NET code as well
I writing an application what can either be run on the command line, or with a WPF UI.
[STAThread]
static void Main(string[] args)
{
// Does magic parse args and sets IsCommandLine to true if flag is present
ParseArgs(args);
if(IsCommandLine)
{
// Write a bunch of things to the console
}
else
{
var app = new App();
app.Run(new Window());
}
}
I set the project's Output type to Console Application, I get a console window that popups if I try to execute it by double-clicking the exe. I don't want to show the console window to the user if the flag is not set (passed in via command args).
However, if I set the project's Output type to Windows Application, the double-click behaviour is fine, but when I run it in the console, I get no console output (Console.Writeline)
Your best bet would be to abstract out the code that actually does the work to a separate class library that has no UI and then create two applications one Console, the other WPF that call this.
A console application and an WPF application have entirely different application models so you can't reuse the same code in both applications.
Having a separate class library allows you do other things like use it in other applications such as a web site or client/server architecture.
Create a WPF app and add the following code to your App class:
public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
if (e.Args.Length > 0)
{
List<string> lowercaseArgs = e.Args.ToList().ConvertAll(x => x.ToLower());
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
// your console app code
Console.Write("\rPress any key to continue...");
Console.ReadKey();
FreeConsole();
}
Shutdown();
}
else
{
base.OnStartup(e);
}
}
private const int ATTACH_PARENT_PROCESS = -1;
[DllImport("kernel32", SetLastError = true)]
private static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32.dll")]
private static extern bool FreeConsole();
}
You can conditionally start your WPF application by performing the following steps with the sample below.
Add another entry point with the 'Main' method declarated with STAThreadAttribute. This is required by WPF.
Under your project's 'Build' properties, choose 'Console Application' as your output and your new 'Main' method as the application's 'Startup Object'.
using System;
public static class Program
{
[STAThreadAttribute]
public static void Main()
{
Console.WriteLine("What now?");
Console.ReadKey(true);
App.Main();
}
}
I know I'm a little late to the party, but figured I could toss in my two cents. You could always keep it as a console application, and then hide the console as per this answer (https://stackoverflow.com/a/3571628/1059953). There is a moment of the console being displayed, then it disappears and the window shows up.