There are many posts on how to call an unmanaged DLL's function, by using "DllImport" or using LoadLibrary and GetProcAddress. There are almost no posts on how to list the available functions in a DLL, and none on how to do it using the .NET.
I started by using the code from this post:
http://www.gamedev.net/community/forums/topic.asp?topic_id=409936 by ReZimE
not much was left of the original code, but it gave me the idea I needed in order to approach the problem.
If MSDN jumps to your head, you probably didn't try to use it at all. The thing contains everything you need, ordered by structure. Looks OK, unless you're in a habit of solving a certain point. For those cases the best order is by orientation (aka keywords, categories, etc.) And thus Googling is the best method to use.
For the code I needed to define the structures to be used. PInvoke.NET did a good job on many of the structures. If you need them it's probably one of the best places, though I had to create a few missing structures; based on MSDN.
Now to the code:)
static void Main(string[] args)
{
string DllName = args[0];
unsafe
{
fixed (char* pszModule = DllName)
{
void* hMod = InterOp.GetModuleHandleW(pszModule);
if (hMod != null)
{
Console.WriteLine("Got handle"); uint BaseAddress = (uint)hMod;
// Verify DOS header
IMAGE_DOS_HEADER pDOSHeader = (IMAGE_DOS_HEADER)Marshal.PtrToStructure((IntPtr)hMod, typeof(IMAGE_DOS_HEADER));
if (pDOSHeader.e_magic != IMAGE_DOS_SIGNATURE) // "MZ"
{
Console.WriteLine("Error in DOS signature");
}
// NT Header
void* pNTHeader = InterOp.ImageNtHeader(hMod);
IMAGE_NT_HEADERS NTHeader = (IMAGE_NT_HEADERS)Marshal.PtrToStructure((IntPtr)pNTHeader, typeof(IMAGE_NT_HEADERS));
if (NTHeader.Signature != IMAGE_NT_SIGNATURE) // "PE"
{
Console.WriteLine("Error in NT signature");
}
// RVA of export table
uint lExportOffset = NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
uint lExportSize = NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
// Export table
IMAGE_EXPORT_DIRECTORY pExportDir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure((IntPtr)(BaseAddress + lExportOffset), typeof(IMAGE_EXPORT_DIRECTORY));
// Length of AddressOfNames array
int lNumberOfNames = (int)pExportDir.NumberOfNames;
Console.WriteLine("Found {0} names, size {1} at offset {2}", lNumberOfNames, lExportSize, lExportOffset);
for (int i = 0; i < lNumberOfNames; i++)
{
char* szName = (char*)(BaseAddress + Marshal.ReadInt32((IntPtr)(BaseAddress + pExportDir.AddressOfNames + 4 * i)));
string name = Marshal.PtrToStringAnsi((IntPtr)szName);
Console.WriteLine(name);
}
}
}
}
}
As you'll see; at least I did, because I forgot; it requires the "Allow unsafe code" flag in order to compile.
The constants used in the code are defined as
private static readonly ushort IMAGE_DIRECTORY_ENTRY_EXPORT = 0;
private static readonly ushort IMAGE_DOS_SIGNATURE = 0x5A4D;
private static readonly ushort IMAGE_NT_SIGNATURE = 0x4550;
private const string KERNEL_DLL = "kernel32";
private const string DBGHELP_DLL = "Dbghelp";
private const CallingConvention CALLING_CONVENTION = CallingConvention.Winapi;
I used 6 structures defined in the code, as far as I remember most of them are from the above links so I'll just list them here. In any case it's quite easy to create a new structure based on the definition in the MSDN. Just make sure to define it as "Explicit" instead of "Sequential" if there's a non-standard declaration.
The structures used in the code:
IMAGE_DOS_HEADER
IMAGE_NT_HEADERS
IMAGE_EXPORT_DIRECTORY
IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER32
IMAGE_DATA_DIRECTORY
The last thing is the "access class", I built it especially to access the external functions in the "unsafe" way.
private unsafe class InterOp
{
[DllImport(KERNEL_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "GetModuleHandleW"), SuppressUnmanagedCodeSecurity]
public static extern void* GetModuleHandleW(/*IN*/ char* lpModuleName);
[DllImport(DBGHELP_DLL, CallingConvention = CALLING_CONVENTION, EntryPoint = "ImageNtHeader"), SuppressUnmanagedCodeSecurity]
public static extern void* ImageNtHeader(void* Base);
}
Thursday, October 22, 2009
Wednesday, October 14, 2009
Disabling Screensaver for domain computer
I had encountered this problem while working in a large company with a domain policy that required you to re-enter your password after a few minutes of inactivity. Personally I think it's a good policy, but if you're using 1 computer as the working station and connect to 5 others using RDP (remote desktop) - IT'S LIVING HELL.
In any other situation simply setting the registry key
Neither does:
const int HWND_BROADCAST = 0xFFFF;
const int SC_MONITORPOWER = 0xF170;
const short WM_SYSCOMMAND = 0x112;
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
So I began to dig which message to send in order to fake a mouse movement (or a key press) I've found the answer on this link: http://www.dreamincode.net/forums/showtopic19021.htm
After manipulating it a bit to fit my need I ended up with this code:
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
const int HWND_BROADCAST = 0xFFFF;
[Flags]
private enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
static void Main(string[] args)
{
while (true)
{
System.Threading.Thread.Sleep(1000);
mouse_event((uint)MouseEventFlags.MOVE, 0, 0, 0, 0);
}
}
It doesn't interfere with my work, CPU stays low.
This mini-program is a saver for me.
In any other situation simply setting the registry key
HKEY_CURRENT_USER\Control Panel\Desktop\ScreenSaveActiveto 0 can work. But on a domain it's not working.
Neither does:
const int HWND_BROADCAST = 0xFFFF;
const int SC_MONITORPOWER = 0xF170;
const short WM_SYSCOMMAND = 0x112;
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
So I began to dig which message to send in order to fake a mouse movement (or a key press) I've found the answer on this link: http://www.dreamincode.net/forums/showtopic19021.htm
After manipulating it a bit to fit my need I ended up with this code:
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
const int HWND_BROADCAST = 0xFFFF;
[Flags]
private enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
static void Main(string[] args)
{
while (true)
{
System.Threading.Thread.Sleep(1000);
mouse_event((uint)MouseEventFlags.MOVE, 0, 0, 0, 0);
}
}
It doesn't interfere with my work, CPU stays low.
This mini-program is a saver for me.
Labels:
domain,
mouse event,
mouse move,
Screensaver,
server,
turn off
Some rantings from a programmer
I thought to begin with the methods, the workload or other techie issue. Alas NO. The first thing is M$ Word. To be more precise it's the dictionary built into the bloody thing. I know I make lots of typos when writing, the "nice" feature of doing things behind my back is annoying (and turned on by default.) Yet it doesn't come close to the "missing" words, misspelled words and grammar markings which do not have anything to do with grammar.
Now for the real part of the blog. The preface was just because of some red and green lines appearing on my screen for reasons that Ol' Bill markets as gold. Though I guess it's your gold.
When building a program there appear to be lots of methods to "get it done". While some methods focus on speed, others are focused on scalability. At the bottom line it's about a "customer" and a "product". The usual implementations apply, customer doesn't want to pay too much, product has base cost.
For most cases (meaning the small needed programs) the cycle is
1. Get a list of requirements
2. Set the price (based on the list)
3. Build a demo
4. Show the demo
5. Build a real model
6. Customer gives a list of rejects
7. Fix rejects
8. Put final version
9. Get the paycheck
Note that some customers repeat steps 5 & 6 for a very long time.
Strangely enough this cycle is the base for large projects too. Even if a few other things like milestones, meetings and committees are added.
From my own experience I can tell that the steps involving the customer's decision are the worst. And the closer you are to the customer the worse it gets.
I did a small app for my dad once; he just forgot to mention that the check numbers should be up to 8 digits with a possibility for leading zeros. He mentioned it after he was using the program for a few months, by then he already found a way to bypass it: put 1 instead of a leading 0. Once the checks with the 1 came it was very messy business… Of course I couldn't charge him for the hours spent fixing this problem (he's my dad after all.)
At the current time I'm trying to get another family computer, it's the only explanation to putting Hebrew UI (the family.) It's not that I don't know Hebrew or have problem reading it. It's just that Windows Hebrew UI is at best inconsistent; the terms change from version to version, sometimes the translation is ludicrous, at other times the translation does not exist, and to top it all M$ tested it on a bunch of apes which have nothing to do with Hebrew. If it was a paying customer I'd put the price high enough for him to run away for someone who's shameless. But when it's from your family you can't, thus you end up trashing a newly bought computer with a UI that's not better than a Linux UI (sorry fellows, but that's the point Linux is missing.)
That's all for today, no source code, no punch line, just some rantings and an insight to how they can be reached.
Now for the real part of the blog. The preface was just because of some red and green lines appearing on my screen for reasons that Ol' Bill markets as gold. Though I guess it's your gold.
When building a program there appear to be lots of methods to "get it done". While some methods focus on speed, others are focused on scalability. At the bottom line it's about a "customer" and a "product". The usual implementations apply, customer doesn't want to pay too much, product has base cost.
For most cases (meaning the small needed programs) the cycle is
1. Get a list of requirements
2. Set the price (based on the list)
3. Build a demo
4. Show the demo
5. Build a real model
6. Customer gives a list of rejects
7. Fix rejects
8. Put final version
9. Get the paycheck
Note that some customers repeat steps 5 & 6 for a very long time.
Strangely enough this cycle is the base for large projects too. Even if a few other things like milestones, meetings and committees are added.
From my own experience I can tell that the steps involving the customer's decision are the worst. And the closer you are to the customer the worse it gets.
I did a small app for my dad once; he just forgot to mention that the check numbers should be up to 8 digits with a possibility for leading zeros. He mentioned it after he was using the program for a few months, by then he already found a way to bypass it: put 1 instead of a leading 0. Once the checks with the 1 came it was very messy business… Of course I couldn't charge him for the hours spent fixing this problem (he's my dad after all.)
At the current time I'm trying to get another family computer, it's the only explanation to putting Hebrew UI (the family.) It's not that I don't know Hebrew or have problem reading it. It's just that Windows Hebrew UI is at best inconsistent; the terms change from version to version, sometimes the translation is ludicrous, at other times the translation does not exist, and to top it all M$ tested it on a bunch of apes which have nothing to do with Hebrew. If it was a paying customer I'd put the price high enough for him to run away for someone who's shameless. But when it's from your family you can't, thus you end up trashing a newly bought computer with a UI that's not better than a Linux UI (sorry fellows, but that's the point Linux is missing.)
That's all for today, no source code, no punch line, just some rantings and an insight to how they can be reached.
Monday, October 12, 2009
Get the pixel's color
The title was supposed to be "Get that bloody pixel's color", but I guess the reason for that is that I somehow managed to spray coffee leftovers on the screen, keyboard & myself, the mouse got away.... Anyway the ARGB value of the coffee stain is 255,225,212,192:)
First thing, the reason:
A few days ago I needed to copy a certain color from the document into the app I'm developing. As usual the "color" was copied from a website by the "printscreen - crop - paste" method, which left me with the image and a customer saying "like this".
Digging a bit into the .NET I've found the easiest way would be to do a similar thing:
1. Capture the screen into an image.
2. Get the pixel corresponding to the mouse location
3. Display it's RGB values.
Easy said, and thanks to the M$ .NET team easy done.
The code for the 1st step is:
int w = Screen.PrimaryScreen.Bounds.Width;
int h = Screen.PrimaryScreen.Bounds.Height;
Bitmap img = new Bitmap(w, h);
Graphics g = Graphics.FromImage(img);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(w, h));
For the second step a call to the user32.dll is needed:
[System.Runtime.InteropServices.DllImport("user32")]
public static extern int GetCursorPos(out POINTAPI lpPoint);
public struct POINTAPI
{
public int x;
public int y;
}
And the actual code is:
POINTAPI tPOS;
GetCursorPos(out tPOS);
The 3rd step is the trivial step:
Color color = img.GetPixel(tPOS.x, tPOS.y);
label1.Text = color.A.ToString() + ":" + color.R.ToString() + ":" + color.G.ToString() + ":" + color.B.ToString();
I've wrapped it all in a timer's tick (laziness again...) The resulting method is:
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
POINTAPI tPOS;
GetCursorPos(out tPOS);
int w = Screen.PrimaryScreen.Bounds.Width;
int h = Screen.PrimaryScreen.Bounds.Height;
Bitmap img = new Bitmap(w, h);
Graphics g = Graphics.FromImage(img);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(w, h));
Color color = img.GetPixel(tPOS.x, tPOS.y);
label1.Text = color.A.ToString() + ":" + color.R.ToString() + ":" + color.G.ToString() + ":" + color.B.ToString();
label1.ForeColor = color;
System.Threading.Thread.Sleep(1);
timer1.Start();
}
This code works, though the screen capturing is a bit consuming in CPU terms.
First thing, the reason:
A few days ago I needed to copy a certain color from the document into the app I'm developing. As usual the "color" was copied from a website by the "printscreen - crop - paste" method, which left me with the image and a customer saying "like this".
Digging a bit into the .NET I've found the easiest way would be to do a similar thing:
1. Capture the screen into an image.
2. Get the pixel corresponding to the mouse location
3. Display it's RGB values.
Easy said, and thanks to the M$ .NET team easy done.
The code for the 1st step is:
int w = Screen.PrimaryScreen.Bounds.Width;
int h = Screen.PrimaryScreen.Bounds.Height;
Bitmap img = new Bitmap(w, h);
Graphics g = Graphics.FromImage(img);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(w, h));
For the second step a call to the user32.dll is needed:
[System.Runtime.InteropServices.DllImport("user32")]
public static extern int GetCursorPos(out POINTAPI lpPoint);
public struct POINTAPI
{
public int x;
public int y;
}
And the actual code is:
POINTAPI tPOS;
GetCursorPos(out tPOS);
The 3rd step is the trivial step:
Color color = img.GetPixel(tPOS.x, tPOS.y);
label1.Text = color.A.ToString() + ":" + color.R.ToString() + ":" + color.G.ToString() + ":" + color.B.ToString();
I've wrapped it all in a timer's tick (laziness again...) The resulting method is:
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
POINTAPI tPOS;
GetCursorPos(out tPOS);
int w = Screen.PrimaryScreen.Bounds.Width;
int h = Screen.PrimaryScreen.Bounds.Height;
Bitmap img = new Bitmap(w, h);
Graphics g = Graphics.FromImage(img);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(w, h));
Color color = img.GetPixel(tPOS.x, tPOS.y);
label1.Text = color.A.ToString() + ":" + color.R.ToString() + ":" + color.G.ToString() + ":" + color.B.ToString();
label1.ForeColor = color;
System.Threading.Thread.Sleep(1);
timer1.Start();
}
This code works, though the screen capturing is a bit consuming in CPU terms.
Subscribe to:
Posts (Atom)