Upfront: I am still fairly new to C#. I have done all the research I can up to the point I am at now. This is my first time asking for help online.
I am trying to create a program in C# that sits in the background and receives input from a scanner. From what I have researched so far the scanner acts like a keyboard wedge. This is created as a console application. The program is supposed to compare the part number scanned with the previous part number that was scanned. If the new part number is different than the last then it sends an e-mail saying that the previous part number is completed and out for delivery and that the new part number is starting production. It works except for 2 issues:
I tried using Hooks to intercept input. My resources where:
https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/
http://null-byte.wonderhowto.com/how-to/create-simple-hidden-console-keylogger-c-sharp-0132757/
While the code I have works for sending input to the console in the background it prints one character per line as well as the issue the other issue I am having...
Either its capturing input to a blank console with one character per line or it's running the rest of my code without the functionality of the hooks.
I have been working on this program for several days and I am at a loss. Any help would be greatly appreciated...
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Windows.Input;
namespace Test1
{
class Program
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
public static LowLevelKeyboardProc _proc = HookCallBack;
public static IntPtr _hookID = IntPtr.Zero;
#region Import DLLs
[DllImport("user32.dll", CharSet = CharSet.Auto,SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc Ipfn, IntPtr hMod, uint dwThreadId);
[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 CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr IParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string IpModuleName);
#endregion
#region Key Tracker Delegates/Functions
public 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);
}
}
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr IParam);
public static class PreviousDriver
{
public static string previousDriver{get;set;}
}
#endregion
#region Email functionality
public static void CreateMail()
{
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MailItem mailItem = (Outlook.MailItem)app.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
mailItem.Subject="Driver Update";
//mailItem.To = ; email here
mailItem.Body = "Your " + PreviousDriver.previousDriver + "is finished and is out for delivery.\n\n";
mailItem.Display(false);
mailItem.Send();
}
#endregion
public static class CurrentDriverCount
{
public static int currentDriverCount{get;set;}
}
#region Main
public static void Main()
{
//var handle = GetConsoleWindow();
//ShowWindow(handle, SW_HIDE);
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
DriverStart();
}
#endregion
#region DriverStart()
public static void DriverStart()
{
//string PreviousDriver = null;
Console.WriteLine("What is your driver?\n");
string CurrentDriver = Console.ReadLine(); //Scan driver
Console.WriteLine("Your current driver is " + CurrentDriver + "\n");
if(CurrentDriver == PreviousDriver.previousDriver)
{
//When it's the same driver
Console.WriteLine("Your previous driver was " + PreviousDriver.previousDriver + "\n");
CurrentDriverCount.currentDriverCount +=1;
Console.WriteLine("Your driver count is " + CurrentDriverCount.currentDriverCount + ".\n");
DriverStart();
} else {
//When the driver is different
Console.WriteLine("Your " + PreviousDriver.previousDriver + "is finished and is out for delivery.\n\n" +
"Your "+ CurrentDriver + "are starting now!\n");
CreateMail();
PreviousDriver.previousDriver = CurrentDriver;
CurrentDriverCount.currentDriverCount = 0;
CurrentDriverCount.currentDriverCount +=1;
Console.WriteLine("Your driver count is " + CurrentDriverCount.currentDriverCount + ".\n");
DriverStart();
}
}
#endregion
private static IntPtr HookCallBack(int nCode, IntPtr wParam, IntPtr IParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(IParam);
Console.WriteLine((Keys)vkCode);
StreamWriter sw = new StreamWriter(Application.StartupPath,true);
sw.Write((Keys)vkCode);
sw.Close();
}
return CallNextHookEx(_hookID, nCode, wParam, IParam);
}
}
}
Related
private async void WrongPassword_Load(object sender, EventArgs e)
{
IntPtr NEWDESKTOP = CreateDesktop("dew", IntPtr.Zero, IntPtr.Zero, 0, (uint) DESKTOP_ACCESS.GENERIC_ALL,IntPtr.Zero);
IntPtr OLDDESKTOP = GetThreadDesktop(GetCurrentThreadId());
SwitchDesktop(NEWDESKTOP);
SetThreadDesktop(NEWDESKTOP);
Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
ShowIcon = false;
Text = "";
TopMost = true;
ControlBox = false;
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
button1.Enabled = false;
MessageCycle();
var i = 60;
Task.Factory.StartNew(() =>
{
SoundPlayer dewd = new SoundPlayer(Resources.WrongPassword);
dewd.PlaySync();
});
PlayMusic();
while (i > 0)
{
CountDownLabel.Text = "Please wait " + i +
" seconds before you can dismiss to prevent \n DDOS, BRUTE FORCE ATTACKS";
i = i - 1;
Task.Delay(1000);
}
SetThreadDesktop(OLDDESKTOP);
CloseDesktop(NEWDESKTOP);
SwitchDesktop(OLDDESKTOP);
CountDownLabel.Text = "We are not responsible if you lose your password and files";
button1.Enabled = true;
}
When I put SetThreadDesktop(NEWDESKTOP), my form does not transfer from my current desktop to NEWDESKTOP, I have also put TrySetApartmentState(ApartmentState.STA) and it still does not work, can someone give me a solution to how to transfer a form from your current desktop to NEWDESKTOP?
Comments the [STAThread] and try to activate STA manually:
Also make sure that Don't use anything which will prevent you switching desktop before calling SetThreadDesktop
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace WindowsFormsApp1
{
static class Program
{
[Flags]
internal enum ACCESS_MASK : uint
{
DESKTOP_NONE = 0,
DESKTOP_READOBJECTS = 0x0001,
DESKTOP_CREATEWINDOW = 0x0002,
DESKTOP_CREATEMENU = 0x0004,
DESKTOP_HOOKCONTROL = 0x0008,
DESKTOP_JOURNALRECORD = 0x0010,
DESKTOP_JOURNALPLAYBACK = 0x0020,
DESKTOP_ENUMERATE = 0x0040,
DESKTOP_WRITEOBJECTS = 0x0080,
DESKTOP_SWITCHDESKTOP = 0x0100,
GENERIC_ALL = 0x10000000,
}
[DllImport("user32.dll", EntryPoint = "CreateDesktop", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateDesktop(
[MarshalAs(UnmanagedType.LPWStr)] string desktopName,
[MarshalAs(UnmanagedType.LPWStr)] string device, // must be null.
[MarshalAs(UnmanagedType.LPWStr)] string deviceMode, // must be null,
[MarshalAs(UnmanagedType.U4)] int flags, // use 0
[MarshalAs(UnmanagedType.U4)] ACCESS_MASK accessMask,
IntPtr attributes);
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetThreadDesktop(uint dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
public static extern int SetThreadDesktop(IntPtr hDesktop);
[DllImport("user32.dll", SetLastError = true)]
public static extern int SwitchDesktop(IntPtr hDesktop);
[DllImport("user32.dll", SetLastError = true)]
public static extern int CloseDesktop(IntPtr hDesktop);
/// <summary>
/// The main entry point for the application.
/// </summary>
//[STAThread]
static void Main()
{
int ret = 0;
IntPtr NEWDESKTOP = CreateDesktop("dew", null, null, 0, ACCESS_MASK.GENERIC_ALL, IntPtr.Zero);
IntPtr OLDDESKTOP = GetThreadDesktop(GetCurrentThreadId());
ret = SetThreadDesktop(NEWDESKTOP);
ret = SwitchDesktop(NEWDESKTOP);
Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
ret = SwitchDesktop(OLDDESKTOP);
CloseDesktop(NEWDESKTOP);
}
}
}
I generally do run the method listed below to maximize iconized windows;
however when it comes to outlook, there are times where it will maximize a Mail (message) that i have open instead of the parent application (outlook) ; its just pulling up anything outlook that it finds and i need the parent, how can i achieve this?
I have tried using WINAPI GetAncestor, I have also tried GetParent .
public static bool EventChecking(string progr)
{
int bb = 0;
if (Process.GetProcessesByName(progr).Length > 0)
{
bb++;
}
if (bb == 0)
{
return false;
}
foreach (Process ddcd in Process.GetProcesses())
{
if (ddcd.ProcessName.Contains(progr))
{
if (ddcd.MainWindowHandle != IntPtr.Zero)
{
pointer = ddcd.MainWindowHandle;
if (IsIconic(pointer))
{
SendMessage(pointer, 0x112, 0xF120, 0);
}
SetForegroundWindow(pointer);
}
};
}
return true;
}
EDIT:
I also recently tried:
if (ddcd.MainWindowTitle.EndsWith("- Outlook"))
and it still pulls up the single email
I have also had trouble working with Outlook via C# but I have had some success with Win32 calls. Below is one way to locate the Outlook Main Window by checking the Caption.
You could also try EnumWindows but it takes more effort to implement due to Callbacks.
using System.Text;
using System.Runtime.InteropServices;
public IntPtr GetOutlookHandle()
{
string windowClass = "rctrl_renwnd32";
uint GW_HWNDNEXT = 2;
IntPtr firstHandle = new IntPtr(0);
IntPtr handle = new IntPtr(0);
// Look for a Window with the right Class
firstHandle = FindWindow(windowClass, null);
// Nothing Found
if (firstHandle.Equals(IntPtr.Zero)) return IntPtr.Zero;
// Remember where we started to avoid an infinite loop
handle = firstHandle;
do
{
// Check the Caption to find the Main Window
if (GetWindowCaption(handle).EndsWith(" - Microsoft Outlook"))
{
return handle;
}
// Get the next Window with the same Class
handle = GetWindow(handle, GW_HWNDNEXT);
} while (handle != firstHandle);
// Didn't find any matches
return IntPtr.Zero;
}
private static string GetWindowCaption(IntPtr windowHandle)
{
// Determine Length of Caption
int length = GetWindowTextLength(windowHandle);
StringBuilder sb = new StringBuilder(length + 1);
// Get Window Caption
GetWindowText(windowHandle, sb, sb.Capacity);
return sb.ToString();
}
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetWindowTextLength(IntPtr hWnd);
I have a path of some program (for example explorer), how can I get program icon, convert it to png/jpeg and then display in PictureBox?
I have something like this:
string filePath = "C:\\myfile.exe";
Icon TheIcon = IconFromFilePath(filePath);
if (TheIcon != null) {
// But then I don't know what to do...
}
public Icon IconFromFilePath(string filePath){
Icon programicon = null;
try {
programicon = Icon.ExtractAssociatedIcon(filePath);
}
catch { }
return programicon;
}
I found something similar here. Here is the icon. How I can create 32-bit icon?
The code is surprisingly simple if you know where to look. Start with the Icon class, since that's fundamentally what you're after here.
If you browse its methods, you'll come across a very interesting looking ExtractAssociatedIcon. That accepts a single string parameter that specifies the path to a file containing an icon, such as an executable file.
So that gives you an Icon object, now you just need to display it in a PictureBox. You don't have to convert it to a PNG or JPEG, a bitmap works fine. And there's a built-in member function for that: ToBitmap.
Assigning the new bitmap to the PictureBox.Image property is all you need to do to display it.
This question might be old but here's my answer.
Here's a full code snippet I used in extracting full 256 x 256 icons from any exe file.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
namespace IconUtils
{
internal static class ExtractIcon
{
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
internal delegate bool ENUMRESNAMEPROC(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LockResource(IntPtr hResData);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
public static extern bool EnumResourceNames(IntPtr hModule, IntPtr lpszType, ENUMRESNAMEPROC lpEnumFunc, IntPtr lParam);
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
private readonly static IntPtr RT_ICON = (IntPtr)3;
private readonly static IntPtr RT_GROUP_ICON = (IntPtr)14;
public static Icon ExtractIconFromExecutable(string path)
{
IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
var tmpData = new List<byte[]>();
ENUMRESNAMEPROC callback = (h, t, name, l) =>
{
var dir = GetDataFromResource(hModule, RT_GROUP_ICON, name);
// Calculate the size of an entire .icon file.
int count = BitConverter.ToUInt16(dir, 4); // GRPICONDIR.idCount
int len = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (int i = 0; i < count; ++i)
len += BitConverter.ToInt32(dir, 6 + 14 * i + 8); // GRPICONDIRENTRY.dwBytesInRes
using (var dst = new BinaryWriter(new MemoryStream(len)))
{
// Copy GRPICONDIR to ICONDIR.
dst.Write(dir, 0, 6);
int picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (int i = 0; i < count; ++i)
{
// Load the picture.
ushort id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12); // GRPICONDIRENTRY.nID
var pic = GetDataFromResource(hModule, RT_ICON, (IntPtr)id);
// Copy GRPICONDIRENTRY to ICONDIRENTRY.
dst.Seek(6 + 16 * i, 0);
dst.Write(dir, 6 + 14 * i, 8); // First 8bytes are identical.
dst.Write(pic.Length); // ICONDIRENTRY.dwBytesInRes
dst.Write(picOffset); // ICONDIRENTRY.dwImageOffset
// Copy a picture.
dst.Seek(picOffset, 0);
dst.Write(pic, 0, pic.Length);
picOffset += pic.Length;
}
tmpData.Add(((MemoryStream)dst.BaseStream).ToArray());
}
return true;
};
EnumResourceNames(hModule, RT_GROUP_ICON, callback, IntPtr.Zero);
byte[][] iconData = tmpData.ToArray();
using (var ms = new MemoryStream(iconData[0]))
{
return new Icon(ms);
}
}
private static byte[] GetDataFromResource(IntPtr hModule, IntPtr type, IntPtr name)
{
// Load the binary data from the specified resource.
IntPtr hResInfo = FindResource(hModule, name, type);
IntPtr hResData = LoadResource(hModule, hResInfo);
IntPtr pResData = LockResource(hResData);
uint size = SizeofResource(hModule, hResInfo);
byte[] buf = new byte[size];
Marshal.Copy(pResData, buf, 0, buf.Length);
return buf;
}
}
}
Usage:
Icon ExeIcon = IconUtils.ExtractIcon.ExtractIconFromExecutable(#"C:\Windows\explorer.exe");
Source: https://www.codeproject.com/Articles/26824/Extract-icons-from-EXE-or-DLL-files
I'm calling the following function on wininet.dll in order to get online (C# pinvoke):
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int InternetDial(IntPtr hWndParent, string pszEntryName,
int dwFlags, ref int lpdwConnection,
int ReservedValue);
public static bool GetOnline()
{
int connectionID = 0;
InternetDial(IntPtr.Zero, "DefaultDialUp", INTERNET_AUTODIAL_FORCE_UNATTENDED, ref connectionID, 0);
return (connectionID != 0);
}
The problem is when error occurs in the dial up process, such as hardware failure,
Windows shows a blocking dialog that ask the user how to procceed,
And my function is stuck until the user causes the dialog to be closed:
This code should be deployed on automatic systems so this is a major issue for me...
I'm looking for a way to suppress the error dialogs on the windows API level..
Thanks in advance,
Eitan.
Iv'e managed to find a workaruond for the issue, but it's pretty nasty,
better solutions still welcome...
const int WM_CLOSE = 0x10;
const int INTERNET_AUTODIAL_FORCE_UNATTENDED = 0x2;
[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int InternetDial(IntPtr hWndParent, string pszEntryName, int dwFlags, ref int lpdwConnection, int ReservedValue);
public static bool GetOnline()
{
connectionID = 0;
Form f = null;
var t = new Thread((ParameterizedThreadStart)delegate
{
f = new Form();
InternetDial(f.Handle, "DefaultDialUp", INTERNET_AUTODIAL_FORCE_UNATTENDED, ref connectionID, 0);
});
t.Start();
t.Join(23000); //wait 23 seconds before closing the window
f.Invoke((EventHandler)delegate {
PostMessage(f.Handle.ToInt32(), WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
});
t.Join();
return (connectionID != 0);
}
I'm using this webbrowswer feature of C#. Trying to log in a website through my application. Everything goes fine, except when a wrong ID or password is entered there's little message box (that is set on the webpage itself) which pops up and blocks everything until "Ok" is clicked.
So the question is: Is there any possible way to manage this little window (like reading the text inside of it)? If it is then great!
But if there's no way to do that then is there anyway to simply make this message box go away programatically?
You can "manage" the message box dialog by importing some window functions from user32.dll and getting the messagebox dialog's handle by it's class name and window name. For example to click its OK button:
public class Foo
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private void ClickOKButton()
{
IntPtr hwnd = FindWindow("#32770", "Message from webpage");
hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Button", "OK");
uint message = 0xf5;
SendMessage(hwnd, message, IntPtr.Zero, IntPtr.Zero);
}
}
Some reading material from MSDN.
Copy paste from Sires anwser: https://stackoverflow.com/a/251524/954225
private void InjectAlertBlocker() {
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
string alertBlocker = "window.alert = function () { }";
element.text = alertBlocker;
head.AppendChild(scriptEl);
}
here is refined version of Saeb's answer. Saeb's code was not working for me, I added one more step to activate the button and then clicking on it.
using System;
using System.Runtime.InteropServices;
namespace IE_Automation
{
public class IEPoppupWindowClicker
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
private const int BM_CLICK = 0xF5;
private const uint WM_ACTIVATE = 0x6;
private const int WA_ACTIVE = 1;
public void ActivateAndClickOkButton()
{
// find dialog window with titlebar text of "Message from webpage"
var hwnd = FindWindow("#32770", "Message from webpage");
if (hwnd != IntPtr.Zero)
{
// find button on dialog window: classname = "Button", text = "OK"
var btn = FindWindowEx(hwnd, IntPtr.Zero, "Button", "OK");
if (btn != IntPtr.Zero)
{
// activate the button on dialog first or it may not acknowledge a click msg on first try
SendMessage(btn, WM_ACTIVATE, WA_ACTIVE, 0);
// send button a click message
SendMessage(btn, BM_CLICK, 0, 0);
}
else
{
//Interaction.MsgBox("button not found!");
}
}
else
{
//Interaction.MsgBox("window not found!");
}
}
}
}