Change process name for Windows Task Manager - c#

I have an C#/.NET application that behaves similarly to svchost--we use it to start our services, each of which resides in a separate DLL. When looking in the Task Manager, all of these show up with the same name--the name of the executable process that started them.
We would like to make each of these be named uniquely. Is there an API call that can be made to set the process name dynamically--i.e. to a string that is read from a configuration file?
I've read the other similar topics, but they haven't helped. A response to Question #14711100 suggested using symlinks, to which the response was that doesn't work. That question was also about killing and starting, so the answers were geared toward that problem.
Others mentioned setting the window title bar text or the process name of the executable. Those don't apply here because there is no window title bar, and the same executable is used to launch different processes.
Question #1402824 seems to be the closest. Is there any libc implementation available under Windows that would work?
If this can't be done, then are there any ways to somehow fake it? Our main goal is to be able to distinguish which process is which in Task Manager and similar process lists.
If we could even use the PID to get at the full command line, that would probably help.
As a last resort, if I set up some sort of supervisor that copies the EXE to a new name before launching, what are the implications that I should consider? Would I need to worry about anything duplicated in memory? Anything shared in memory? Anyone stomping on anyone's data, files, etc? An answer to Question #1402824 mentioned the same context. What do we need to know about that?
Thanks.
EDIT
I learned that I could get the process information using the wmic tool:
wmic service where (pathname like "%%svchostOrWhatever.exe%%" and state="Running") get DisplayName,Name,PathName,ProcessId,StartMode
This might end up being what we have to live with if we can't change the image name. Regarding that, I did find this VB 6.0 project by Billy Conner:
http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=66443&lngWId=1
I understand things have changed a lot since 2006, but I thought it's worth a try. (FYI I'm on Windows 7.)
It looks like it's basically using SendMessage to send a LVM_SETITEMTEXT message with the desired process name. I translated the calls to C# using P/Invoke, but it doesn't appear to work.
If I understand the API correctly, SendMessage will return true (nonzero) for LVM_SETITEMTEXT if it succeeded and false (zero) if failed, and then I can find out more information as usual using the managed version of GetLastError.
When I ran this in my svchost equivalent, SendMessage() returned zero. I called Marshal.GetLastWin32Error() and got back 1400, which looks like I'm getting ERROR_INVALID_WINDOW_HANDLE. Ok, maybe I can't run this on a Windows service since it doesn't have a window.
Then, I tried it in a dummy WPF application. This time, I still got a 0 back from SendMessage(), but GetLastWin32Error is also returning zero.
The dummy application has an App.xaml and a MainWindow.xaml. I placed the following call at the end of my MainWindow constructor in the code behind:
IntPtr handle = System.Diagnostics.Process.GetCurrentProcess().Handle;
SetItemText(handle, "Gobbledygook.exe", 0);
Here is the definition of SetItemText as taken and translated from Connor's project:
public static void SetItemText(IntPtr handle,
string desiredImageName,
long index,
long subIndex = 0)
{
// TODO: Check return values for errors...
desiredImageName = string.Format("{0}\0", desiredImageName); // TODO: Is the nul character required?
byte[] memStorage = System.Text.Encoding.ASCII.GetBytes(desiredImageName);
long size = memStorage.Length;
// allocate some shared memory for our string
IntPtr sharedProcMemString = VirtualAllocEx(handle,
IntPtr.Zero,
(uint)size,
AllocationType.Reserve | AllocationType.Commit,
MemoryProtection.ReadWrite);
// setup some info
LVITEM lvi = new LVITEM()
{
iItem = (int)index,
iSubItem = (int)subIndex,
cchTextMax = (int)size,
pszText = sharedProcMemString // store our string handle
};
// allocate some shared memory for our Struct
IntPtr sharedProcMem = VirtualAllocEx(handle,
IntPtr.Zero,
(uint)System.Runtime.InteropServices.Marshal.SizeOf(lvi),
AllocationType.Reserve | AllocationType.Commit,
MemoryProtection.ReadWrite);
// write to memory
WriteProcessMemory(handle, sharedProcMemString, memStorage);
WriteProcessMemory(handle, sharedProcMem, GetBytes(lvi));
// get the text
IntPtr result = SendMessage(handle, LVM_SETITEMTEXTA, (IntPtr)index, sharedProcMem);
if ((int)result == 0) // false, i.e. error
{
int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
// TODO: do something with errorCode - e.g. log it?
}
// clean up
VirtualFreeEx(handle, sharedProcMem, System.Runtime.InteropServices.Marshal.SizeOf(lvi), AllocationType.Release);
VirtualFreeEx(handle, sharedProcMemString, (int)size, AllocationType.Release);
}
Here are some supporting routines:
private static byte[] GetBytes(LVITEM str)
{
int size = System.Runtime.InteropServices.Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);
System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr, true);
System.Runtime.InteropServices.Marshal.Copy(ptr, arr, 0, size);
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr);
return arr;
}
public static void WriteProcessMemory(IntPtr handle, IntPtr writeAddress, byte[] buffer)
{
int bytesWritten;
WriteProcessMemory(handle, writeAddress, buffer, (uint)buffer.Length, out bytesWritten);
}
Here are the necessary P/Invoke declarations:
private const int LVM_FIRST = 0x1000;
private const int LVM_GETITEMCOUNT = LVM_FIRST + 4;
private const int LVM_GETITEM = LVM_FIRST + 75;
private const int LVIF_TEXT = 0x0001;
private const int LVM_SETITEMTEXTA = (LVM_FIRST + 46);
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct LVITEM
{
public uint mask;
public int iItem;
public int iSubItem;
public uint state;
public uint stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
public IntPtr lParam;
}
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd,
int Msg,
IntPtr wParam,
IntPtr lParam);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess,
IntPtr lpAddress,
uint dwSize,
AllocationType flAllocationType,
MemoryProtection flProtect);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern bool VirtualFreeEx(IntPtr hProcess,
IntPtr lpAddress,
int dwSize,
AllocationType dwFreeType);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteProcessMemory(IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
uint nSize,
out int lpNumberOfBytesWritten);
Any thoughts? Thanks.

Related

Console.Out Output is showing in Output Window, Needed in AllocConsole()

Ok, I've always used the AllocConsole() method for console output when it comes to needing a Winform as well, because I use a wide variety of color when it comes to writing to console.
Using VS 2015 and below, AllocConsole in Debug mode always worked properly, Console.WriteLine wrote to it properly. Now using VS 2017, The Console Shows when AllocConsole is called, however, instead of console.WriteLine outputs going to that console, it is going to the Output window of Visual Studio.
I prefer to use the AllocConsole rather than the Output window because I rely heavily on color. I've done plenty of searching on how to fix this, but I can't seem to find an answer.
AllocConsole() does not work on it's own, because VS 2017 does some "debug stdout redirect magic". To fix this you need to create a console with AllocConsole() and fix the stdout handle.
Here is the snipped I found:
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
uint lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
uint hTemplateFile);
private const int MY_CODE_PAGE = 437;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_WRITE = 0x2;
private const uint OPEN_EXISTING = 0x3;
public static void CreateConsole()
{
AllocConsole();
IntPtr stdHandle = CreateFile(
"CONOUT$",
GENERIC_WRITE,
FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0
);
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = System.Text.Encoding.GetEncoding(MY_CODE_PAGE);
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
Console.Write("This will show up in the Console window.");
}
Special thanks to Ramkumar Ramesh for the work-around:
Console Output is gone in VS2017
Building on the answer from wischi, if you want properties for the static Console class to work correctly, for instance Console.ForegroundColor it is important to set the desiredAccess to GENERIC_READ | GENERIC_WRITE. I think the reason for this is that Console is using GetConsoleScreenBufferInfo internally and when I tried to use that method on the handle returned by CreateFile with only GENERIC_WRITE that gave me an ACCESS_DENIED error.
[DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(string lpFileName
, [MarshalAs(UnmanagedType.U4)] DesiredAccess dwDesiredAccess
, [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode
, uint lpSecurityAttributes
, [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition
, [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes
, uint hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetStdHandle(StdHandle nStdHandle, IntPtr hHandle);
private enum StdHandle : int
{
Input = -10,
Output = -11,
Error = -12
}
[Flags]
enum DesiredAccess : uint
{
GenericRead = 0x80000000,
GenericWrite = 0x40000000,
GenericExecute = 0x20000000,
GenericAll = 0x10000000
}
public static void CreateConsole()
{
if (AllocConsole())
{
//https://developercommunity.visualstudio.com/content/problem/12166/console-output-is-gone-in-vs2017-works-fine-when-d.html
// Console.OpenStandardOutput eventually calls into GetStdHandle. As per MSDN documentation of GetStdHandle: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231(v=vs.85).aspx will return the redirected handle and not the allocated console:
// "The standard handles of a process may be redirected by a call to SetStdHandle, in which case GetStdHandle returns the redirected handle. If the standard handles have been redirected, you can specify the CONIN$ value in a call to the CreateFile function to get a handle to a console's input buffer. Similarly, you can specify the CONOUT$ value to get a handle to a console's active screen buffer."
// Get the handle to CONOUT$.
var stdOutHandle = CreateFile("CONOUT$", DesiredAccess.GenericRead | DesiredAccess.GenericWrite, FileShare.ReadWrite, 0, FileMode.Open, FileAttributes.Normal, 0);
if (stdOutHandle == new IntPtr(-1))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (!SetStdHandle(StdHandle.Output, stdOutHandle))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var standardOutput = new StreamWriter(Console.OpenStandardOutput());
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
}
}

AccessViolationException when try to read memory from pointer in C# using Marshal class

I try to create a program that will programatically set Windows Color Management to archive an effect like f.lux as a hobby project.
**The definition of WINAPI WcsGetDefaultColorProfileSize. **
BOOL WINAPI WcsGetDefaultColorProfileSize(
_In_ WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope,
_In_opt_ PCWSTR pDeviceName,
_In_ COLORPROFILETYPE cptColorProfileType,
_In_ COLORPROFILESUBTYPE cpstColorProfileSubType,
_In_ DWORD dwProfileID,
_Out_ PDWORD pcbProfileName
);
**This is the signature of managed WcsGetDefaultColorProfileSize. **
[DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfileSize", CharSet = CharSet.Unicode)]
private static extern bool GetDefaultColorProfileSize(
WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope,
[MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName,
COLORPROFILETYPE cptColorProfileType,
COLORPROFILESUBTYPE cpstColorProfileSubType,
Int32 dwProfileID,
out IntPtr pcbProfileSize
);
The problem is when I try to get the string which is return as a pointer from WINAPI using Marshal class. Like this
// Need to get the size of ICC profile file first
GetDefaultColorProfileSize(
WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER,
monitor_name.DeviceKey,
COLORPROFILETYPE.CPT_ICC,
COLORPROFILESUBTYPE.CPST_RGB_WORKING_SPACE,
1,
out SizePointer);
System.Diagnostics.Debug.WriteLine("Size is " + Marshal.ReadInt32(SizePointer));
the GetDefaultColorProfileSize return TRUE but when I try to access the address it return (It return this address 0x0000003e) using Marshal.ReadInt32
It throw this error
System.AccessViolationException Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
How can I able to read the memory at that pointer?
I try to allocate the memory first as suggesting by nvoigt
Changing from IntPtr SizePointer to IntPtr SizePointer = Marshal.AllocHGlobal(4);
But it still throw the same exception
The full code is below here.
Enumnerate Display Devices
[DllImport("User32.dll")]
private static extern bool EnumDisplayDevices(
string lpDevice, int iDevNum,
ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAY_DEVICE
{
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
public int StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
public DISPLAY_DEVICE(int flags) {
cb = 0;
StateFlags = flags;
DeviceName = new string((char)32, 32);
DeviceString = new string((char)32, 128);
DeviceID = new string((char)32, 128);
DeviceKey = new string((char)32, 128);
cb = Marshal.SizeOf(this);
}
}
Window Color System
enum WCS_PROFILE_MANAGEMENT_SCOPE
{
WCS_PROFILE_MANAGEMENT_SCOPE_SYSTEM_WIDE = 0,
WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER
}
enum COLORPROFILETYPE
{
CPT_ICC = 0x0001,
CPT_DMP,
CPT_CAMP,
CPT_GMMP
}
enum COLORPROFILESUBTYPE
{
CPST_NONE = 0x0000,
CPST_RGB_WORKING_SPACE = 0x0001,
CPST_PERCEPTUAL = 0x0002,
CPST_ABSOLUTE_COLORIMETRIC = 0x0004,
CPST_RELATIVE_COLORIMETRIC = 0x0008,
CPST_SATURATION = 0x0010,
CPST_CUSTOM_WORKING_SPACE = 0x0020
}
[DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfileSize", CharSet = CharSet.Unicode)]
private static extern bool GetDefaultColorProfileSize(
WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope,
[MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName,
COLORPROFILETYPE cptColorProfileType,
COLORPROFILESUBTYPE cpstColorProfileSubType,
Int32 dwProfileID,
out IntPtr pcbProfileSize
);
[DllImport("Mscms.dll", EntryPoint = "WcsGetDefaultColorProfile" , CharSet =CharSet.Unicode, SetLastError =true)]
private unsafe static extern bool GetDefaultColorProfile(WCS_PROFILE_MANAGEMENT_SCOPE profileManagementScope,
[MarshalAs(UnmanagedType.LPWStr), In] string pDeviceName,
COLORPROFILETYPE cptColorProfileType,
COLORPROFILESUBTYPE cpstColorProfileSubType,
Int32 dwProfileID,
Int32 cbProfileName,
out IntPtr pProfileName);
[DllImport("Mscms.dll", EntryPoint = "WcsSetUsePerUserProfiles", CharSet = CharSet.Unicode)]
private static extern bool SetUsePerUserProfiles([MarshalAs(UnmanagedType.LPWStr), In]string pDeviceName, Int32 dwDeviceClass, bool usePerUserProfiles);
[DllImport("Mscms.dll", EntryPoint = "WcsGetUsePerUserProfiles", CharSet = CharSet.Unicode)]
private static extern bool GetUsePerUserProfiles([MarshalAs(UnmanagedType.LPWStr), In]string pDeviceName, Int32 dwDeviceClass, out bool pUsePerUserProfiles);
The Actual Code
public unsafe static void GetProfile() {
DISPLAY_DEVICE lpDisplayDevice = new DISPLAY_DEVICE(0); // OUT
DISPLAY_DEVICE monitor_name = new DISPLAY_DEVICE(0); // OUT
int devNum = 0;
while (EnumDisplayDevices(null, devNum, ref lpDisplayDevice, 0)) {
int devNum2 = 0;
while (EnumDisplayDevices(lpDisplayDevice.DeviceName, devNum2, ref monitor_name, 0)) {
IntPtr SizePointer;
// Need to get the size of ICC profile file first
GetDefaultColorProfileSize(
WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER,
monitor_name.DeviceKey,
COLORPROFILETYPE.CPT_ICC,
COLORPROFILESUBTYPE.CPST_RGB_WORKING_SPACE,
1,
out SizePointer);
System.Diagnostics.Debug.WriteLine("Size is " + Marshal.ReadInt32(SizePointer));
// Try to get a location of ICC profile file.
// Not Implement Yet
break;
}
break;
}
}
Your SizePointer is a local variable that you never used. I don't know what you expect to happen, but this is not going to work. You probably meant to use profileSize.
In the future, you should fix your warnings first. They are important.
Okay, now you are at least passing the correct variable. You still have not initialized it to anything. You are passing a NULL pointer to a method that is supposed to write there. It won't be able to. I cannot imagine you actually got a TRUE back from that method. And reading from a NULL pointer will obviously fail. You need to make sure that pointer actually points to a part in memory that can be written to.
You need a DWORD. As you are using ReadInt32, I'll assume you are on 32bit.
You need to allocate memory first:
int size = 4; // 4 byte = 32 bit
IntPtr p = Marshal.AllocHGlobal(size);
Don't forget to free it later, this is not garbage collected:
Marshal.FreeHGlobal(p);

Microchip HID_PnP_Demo, WinForm to WPF

I've been trying to learn about WPF since I've been using VB.NET and WindowsForm for the past 10 years in a very few small projects.
I'm planning a simple interface to control my house with a PIC18F97J94.
Microchip provides an example (That's part of the MLA solution, it's in C# and WinForm) which I could workaround and finish my project but I want to learn WPF and C#.
The problem I'm encountering is with the .Handle:
RegisterDeviceNotification(this.Handle, pDeviceBroadcastHeader, DEVICE_NOTIFY_WINDOW_HANDLE);
Error CS1061 'MainWindow' does not contain a definition for 'Handle' and no extension method 'Handle' accepting a first argument of type 'MainWindow' could be found.
The full code block is the next one:
public MainWindow()
{
InitializeComponent();
ProgressBar1.ToolTip = ("If using a board/PIM without a potentiometer, apply an adjustable voltage to the I/O pin.");
ANxVoltage_lbl.ToolTip = ("If using a board/PIM without a potentiometer, apply an adjustable voltage to the I/O pin.");
ToggleLEDs_btn.ToolTip = ("Sends a packet of data to the USB device.");
PushbuttonState_lbl.ToolTip = ("Try pressing pushbuttons on the USB demo board/PIM.");
//Register for WM_DEVICECHANGE notifications. This code uses these messages to detect plug and play connection/disconnection events for USB devices
DEV_BROADCAST_DEVICEINTERFACE DeviceBroadcastHeader = new DEV_BROADCAST_DEVICEINTERFACE();
DeviceBroadcastHeader.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
DeviceBroadcastHeader.dbcc_size = (uint)Marshal.SizeOf(DeviceBroadcastHeader);
DeviceBroadcastHeader.dbcc_reserved = 0; //Reserved says not to use...
DeviceBroadcastHeader.dbcc_classguid = InterfaceClassGuid;
//Need to get the address of the DeviceBroadcastHeader to call RegisterDeviceNotification(), but
//can't use "&DeviceBroadcastHeader". Instead, using a roundabout means to get the address by
//making a duplicate copy using Marshal.StructureToPtr().
IntPtr pDeviceBroadcastHeader = IntPtr.Zero; //Make a pointer.
pDeviceBroadcastHeader = Marshal.AllocHGlobal(Marshal.SizeOf(DeviceBroadcastHeader)); //allocate memory for a new DEV_BROADCAST_DEVICEINTERFACE structure, and return the address
Marshal.StructureToPtr(DeviceBroadcastHeader, pDeviceBroadcastHeader, false); //Copies the DeviceBroadcastHeader structure into the memory already allocated at DeviceBroadcastHeaderWithPointer
RegisterDeviceNotification(this.Handle, pDeviceBroadcastHeader, DEVICE_NOTIFY_WINDOW_HANDLE);
//Now make an initial attempt to find the USB device, if it was already connected to the PC and enumerated prior to launching the application.
//If it is connected and present, we should open read and write handles to the device so we can communicate with it later.
//If it was not connected, we will have to wait until the user plugs the device in, and the WM_DEVICECHANGE callback function can process
//the message and again search for the device.
if (CheckIfPresentAndGetUSBDevicePath()) //Check and make sure at least one device with matching VID/PID is attached
{
uint ErrorStatusWrite;
uint ErrorStatusRead;
//We now have the proper device path, and we can finally open read and write handles to the device.
WriteHandleToUSBDevice = CreateFile(DevicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
ErrorStatusWrite = (uint)Marshal.GetLastWin32Error();
ReadHandleToUSBDevice = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
ErrorStatusRead = (uint)Marshal.GetLastWin32Error();
if ((ErrorStatusWrite == ERROR_SUCCESS) && (ErrorStatusRead == ERROR_SUCCESS))
{
AttachedState = true; //Let the rest of the PC application know the USB device is connected, and it is safe to read/write to it
AttachedButBroken = false;
StatusBox_txtbx.Text = "Device Found, AttachedState = TRUE";
}
else //for some reason the device was physically plugged in, but one or both of the read/write handles didn't open successfully...
{
AttachedState = false; //Let the rest of this application known not to read/write to the device.
AttachedButBroken = true; //Flag so that next time a WM_DEVICECHANGE message occurs, can retry to re-open read/write pipes
if (ErrorStatusWrite == ERROR_SUCCESS)
WriteHandleToUSBDevice.Close();
if (ErrorStatusRead == ERROR_SUCCESS)
ReadHandleToUSBDevice.Close();
}
}
else //Device must not be connected (or not programmed with correct firmware)
{
AttachedState = false;
AttachedButBroken = false;
}
if (AttachedState == true)
{
StatusBox_txtbx.Text = "Device Found, AttachedState = TRUE";
}
else
{
StatusBox_txtbx.Text = "Device not found, verify connect/correct firmware";
}
ReadWriteThread.RunWorkerAsync();
}
Added info:
The next code block is what I transferred from the WinForm example, however I get the warning CS0649 in the line:
internal char[] DevicePath; //TCHAR array of any size
and
internal char[] dbcc_name; //TCHAR array
Code:
public partial class MainWindow : Window
{
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------BEGIN CUT AND PASTE BLOCK-----------------------------------------------------------------------------------
//Constant definitions from setupapi.h, which we aren't allowed to include directly since this is C#
internal const uint DIGCF_PRESENT = 0x02;
internal const uint DIGCF_DEVICEINTERFACE = 0x10;
//Constants for CreateFile() and other file I/O functions
internal const short FILE_ATTRIBUTE_NORMAL = 0x80;
internal const short INVALID_HANDLE_VALUE = -1;
internal const uint GENERIC_READ = 0x80000000;
internal const uint GENERIC_WRITE = 0x40000000;
internal const uint CREATE_NEW = 1;
internal const uint CREATE_ALWAYS = 2;
internal const uint OPEN_EXISTING = 3;
internal const uint FILE_SHARE_READ = 0x00000001;
internal const uint FILE_SHARE_WRITE = 0x00000002;
//Constant definitions for certain WM_DEVICECHANGE messages
internal const uint WM_DEVICECHANGE = 0x0219;
internal const uint DBT_DEVICEARRIVAL = 0x8000;
internal const uint DBT_DEVICEREMOVEPENDING = 0x8003;
internal const uint DBT_DEVICEREMOVECOMPLETE = 0x8004;
internal const uint DBT_CONFIGCHANGED = 0x0018;
//Other constant definitions
internal const uint DBT_DEVTYP_DEVICEINTERFACE = 0x05;
internal const uint DEVICE_NOTIFY_WINDOW_HANDLE = 0x00;
internal const uint ERROR_SUCCESS = 0x00;
internal const uint ERROR_NO_MORE_ITEMS = 0x00000103;
internal const uint SPDRP_HARDWAREID = 0x00000001;
enum WM_DEVICECHANGE_ENUM : int//Public Enum WM_DEVICECHANGE As Integer
{
DBT_CONFIGCHANGECANCELED = 0x19,
DBT_CONFIGCHANGED = 0x18,
DBT_CUSTOMEVENT = 0x8006,
DBT_DEVICEARRIVAL = 0x8000,
DBT_DEVICEQUERYREMOVE = 0x8001,
DBT_DEVICEQUERYREMOVEFAILED = 0x8002,
DBT_DEVICEREMOVECOMPLETE = 0x8004,
DBT_DEVICEREMOVEPENDING = 0x8003,
DBT_DEVICETYPESPECIFIC = 0x8005,
DBT_DEVNODES_CHANGED = 0x7,
DBT_QUERYCHANGECONFIG = 0x17,
DBT_USERDEFINED = 0xFFFF
}//End Enum
//Various structure definitions for structures that this code will be using
internal struct SP_DEVICE_INTERFACE_DATA
{
internal uint cbSize; //DWORD
internal Guid InterfaceClassGuid; //GUID
internal uint Flags; //DWORD
internal uint Reserved; //ULONG_PTR MSDN says ULONG_PTR is "typedef unsigned __int3264 ULONG_PTR;"
}
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
internal uint cbSize; //DWORD
internal char[] DevicePath; //TCHAR array of any size
}
internal struct SP_DEVINFO_DATA
{
internal uint cbSize; //DWORD
internal Guid ClassGuid; //GUID
internal uint DevInst; //DWORD
internal uint Reserved; //ULONG_PTR MSDN says ULONG_PTR is "typedef unsigned __int3264 ULONG_PTR;"
}
internal struct DEV_BROADCAST_DEVICEINTERFACE
{
internal uint dbcc_size; //DWORD
internal uint dbcc_devicetype; //DWORD
internal uint dbcc_reserved; //DWORD
internal Guid dbcc_classguid; //GUID
internal char[] dbcc_name; //TCHAR array
}
//DLL Imports. Need these to access various C style unmanaged functions contained in their respective DLL files.
//--------------------------------------------------------------------------------------------------------------
//Returns a HDEVINFO type for a device information set. We will need the
//HDEVINFO as in input parameter for calling many of the other SetupDixxx() functions.
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr SetupDiGetClassDevs(
ref Guid ClassGuid, //LPGUID Input: Need to supply the class GUID.
IntPtr Enumerator, //PCTSTR Input: Use NULL here, not important for our purposes
IntPtr hwndParent, //HWND Input: Use NULL here, not important for our purposes
uint Flags); //DWORD Input: Flags describing what kind of filtering to use.
//Gives us "PSP_DEVICE_INTERFACE_DATA" which contains the Interface specific GUID (different
//from class GUID). We need the interface GUID to get the device path.
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetupDiEnumDeviceInterfaces(
IntPtr DeviceInfoSet, //Input: Give it the HDEVINFO we got from SetupDiGetClassDevs()
IntPtr DeviceInfoData, //Input (optional)
ref Guid InterfaceClassGuid, //Input
uint MemberIndex, //Input: "Index" of the device you are interested in getting the path for.
ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData); //Output: This function fills in an "SP_DEVICE_INTERFACE_DATA" structure.
//SetupDiDestroyDeviceInfoList() frees up memory by destroying a DeviceInfoList
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetupDiDestroyDeviceInfoList(
IntPtr DeviceInfoSet); //Input: Give it a handle to a device info list to deallocate from RAM.
//SetupDiEnumDeviceInfo() fills in an "SP_DEVINFO_DATA" structure, which we need for SetupDiGetDeviceRegistryProperty()
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetupDiEnumDeviceInfo(
IntPtr DeviceInfoSet,
uint MemberIndex,
ref SP_DEVINFO_DATA DeviceInterfaceData);
//SetupDiGetDeviceRegistryProperty() gives us the hardware ID, which we use to check to see if it has matching VID/PID
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetupDiGetDeviceRegistryProperty(
IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
uint Property,
ref uint PropertyRegDataType,
IntPtr PropertyBuffer,
uint PropertyBufferSize,
ref uint RequiredSize);
//SetupDiGetDeviceInterfaceDetail() gives us a device path, which is needed before CreateFile() can be used.
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetupDiGetDeviceInterfaceDetail(
IntPtr DeviceInfoSet, //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, //Input: Pointer to an structure which defines the device interface.
IntPtr DeviceInterfaceDetailData, //Output: Pointer to a SP_DEVICE_INTERFACE_DETAIL_DATA structure, which will receive the device path.
uint DeviceInterfaceDetailDataSize, //Input: Number of bytes to retrieve.
ref uint RequiredSize, //Output (optional): The number of bytes needed to hold the entire struct
IntPtr DeviceInfoData); //Output (optional): Pointer to a SP_DEVINFO_DATA structure
//Overload for SetupDiGetDeviceInterfaceDetail(). Need this one since we can't pass NULL pointers directly in C#.
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetupDiGetDeviceInterfaceDetail(
IntPtr DeviceInfoSet, //Input: Wants HDEVINFO which can be obtained from SetupDiGetClassDevs()
ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, //Input: Pointer to an structure which defines the device interface.
IntPtr DeviceInterfaceDetailData, //Output: Pointer to a SP_DEVICE_INTERFACE_DETAIL_DATA structure, which will contain the device path.
uint DeviceInterfaceDetailDataSize, //Input: Number of bytes to retrieve.
IntPtr RequiredSize, //Output (optional): Pointer to a DWORD to tell you the number of bytes needed to hold the entire struct
IntPtr DeviceInfoData); //Output (optional): Pointer to a SP_DEVINFO_DATA structure
//Need this function for receiving all of the WM_DEVICECHANGE messages. See MSDN documentation for
//description of what this function does/how to use it. Note: name is remapped "RegisterDeviceNotificationUM" to
//avoid possible build error conflicts.
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr RegisterDeviceNotification(
IntPtr hRecipient,
IntPtr NotificationFilter,
uint Flags);
//Takes in a device path and opens a handle to the device.
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
//Uses a handle (created with CreateFile()), and lets us write USB data to the device.
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool WriteFile(
SafeFileHandle hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
ref uint lpNumberOfBytesWritten,
IntPtr lpOverlapped);
//Uses a handle (created with CreateFile()), and lets us read USB data from the device.
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool ReadFile(
SafeFileHandle hFile,
IntPtr lpBuffer,
uint nNumberOfBytesToRead,
ref uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
//--------------- Global Varibles Section ------------------
//USB related variables that need to have wide scope.
bool AttachedState = false; //Need to keep track of the USB device attachment status for proper plug and play operation.
bool AttachedButBroken = false;
SafeFileHandle WriteHandleToUSBDevice = null;
SafeFileHandle ReadHandleToUSBDevice = null;
String DevicePath = null; //Need the find the proper device path before you can open file handles.
//Variables used by the application/form updates.
bool PushbuttonPressed = false; //Updated by ReadWriteThread, read by FormUpdateTimer tick handler (needs to be atomic)
bool ToggleLEDsPending = false; //Updated by ToggleLED(s) button click event handler, used by ReadWriteThread (needs to be atomic)
uint ADCValue = 0; //Updated by ReadWriteThread, read by FormUpdateTimer tick handler (needs to be atomic)
uint ADCDiff = 0;
//Globally Unique Identifier (GUID) for HID class devices. Windows uses GUIDs to identify things.
Guid InterfaceClassGuid = new Guid(0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);
//--------------- End of Global Varibles ------------------
//-------------------------------------------------------END CUT AND PASTE BLOCK-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
WindowInteropHelper interopHelper;
private BackgroundWorker ReadWriteThread = new BackgroundWorker();
private DispatcherTimer timer;
private Int32 BytesControl = 0;//Convert.ToInt32("000000000000000000000001", 2);
Replace this.Handle with the following:
new WindowInteropHelper(myWindow).Handle
WindowInteropHelper class is in the System.Windows.Interop namespace. And myWindow is the name of your Window.
Nevermind. The Window_Loaded event wasn't related to the function:
Here's my fix:
MainWindow_Loaded isn't triggered on my WPF Application

Detect heap corruption BEFORE garbage collect

I am using CDB (Microsoft Console Debugger,) and WinDbg to try to force a break when heap corruption occurs by P/Invoke into ReadFile. I read many more bytes from a text file than what I've allocated to the chBuf array. The debugger does not see the access violation until after GC.Collect, which is too late for me. Prior to running my program, I run
gflags -p /enable testheap.exe /unaligned
The effect seems useless. I wrote this little test program to apply what I find to debugging a much larger commercial program that is having heap corruption issues.
I have also tried DebugDiag with Application Verifier and MDA callbackOnCollectedDelegate without success. Isn't my use of gflags supposed to detect heap corruption immediately after ReadFile?
The code:
namespace TestHeap
public partial class Form1 : Form
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadFile(SafeFileHandle hFile, [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
string fileName = "testHeap.txt";
const uint GENERIC_READ = 0x80000000;
const uint OPEN_EXISTING = 3;
SafeFileHandle sh;
byte[] chBuf = new byte[8];
public Form1()
{
InitializeComponent();
}
private void testBtn_Click(object sender, EventArgs e)
{
bool nStat;
uint bytesToRead = 1025;
uint bytesRead = 0;
if (!(nStat = ReadFile( sh, chBuf, bytesToRead, out bytesRead, IntPtr.Zero)))
Debug.Print("testBtn_Click error in ReadFile, nStat = {0}", nStat);
MessageBox.Show(string.Format("After ReadFile, bytesToRead = {0},\n bytes read = {1}", bytesToRead, bytesRead));
GC.Collect();
MessageBox.Show("testBtn_Click end, after GC.Collect");
}
private void Form1_Load(object sender, EventArgs e)
{
sh = CreateFile(fileName, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
}
}
}
Just a guess but I believe the unexpected gflags behaviour is caused by this line:
byte[] chBuf = new byte[8];
Since chBuf is managed by the CLR, gflags is not able to put the fill pattern after it to detect buffer overruns. Try changing that to:
IntPtr chBuf = Marshal.AllocHGlobal(8);
So that you will be allocating in the unmanaged heap. Gflags should be able to work with that. Also, you may need to change the signature of ReadFile for that to work:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadFile(SafeFileHandle hFile, [Out] IntPtr lpBuffer,
uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);

Load an EXE file and run it from memory

I'm trying to run an executable from memory such as outlined in this article. I can run any .net/managed exes quite easily. But I cannot run executables such as notepad.exe or calc.exe. How can I get it so I can also run unmanaged exes?
In the case of running .NET executables from memory, the libraries and CLR itself are doing a lot of heavy lifting for you. For native executables like notepad.exe and calc.exe, you'll have to do a lot of manual work to get it to happen. Basically, you have to act like the Windows loader.
There's probably pages of caveats here, but this in-depth article has the steps you need to load a PE wiki, msdn into memory and do the correct rebasing and fixups. Then, you should be able to find the entry point (like in the article) and run it.
If you're really just wanting to run notepad.exe and calc.exe, the easiest way, of course, would be to use Process.Start and run them off disk. Otherwise, if you have an executable embedded as a resource in your process, then the next easiest way would be to just write the contents out to disk in a temporary location (see Path.GetTempFileName) and then execute it from there.
I am not sure but the following code from this thread might be helpful:
using System;
using System.Runtime.InteropServices;
/*
* Title: CMemoryExecute.cs
* Description: Runs an EXE in memory using native WinAPI. Very optimized and tiny.
*
* Developed by: affixiate
* Release date: December 10, 2010
* Released on: http://opensc.ws
* Credits:
* MSDN (http://msdn.microsoft.com)
* NtInternals (http://undocumented.ntinternals.net)
* Pinvoke (http://pinvoke.net)
*
* Comments: If you use this code, I require you to give me credits. Don't be a ripper! ;]
*/
// ReSharper disable InconsistentNaming
public static unsafe class CMemoryExecute
{
public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
/// <summary>
/// Runs an EXE (which is loaded in a byte array) in memory.
/// </summary>
/// <param name="exeBuffer">The EXE buffer.</param>
/// <param name="hostProcess">Full path of the host process to run the buffer in.</param>
/// <param name="optionalArguments">Optional command line arguments.</param>
/// <returns></returns>
public static bool Run(byte[] exeBuffer, string hostProcess, string optionalArguments = "")
{
// STARTUPINFO
STARTUPINFO StartupInfo = new STARTUPINFO();
StartupInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_HIDE;
var IMAGE_SECTION_HEADER = new byte[0x28]; // pish
var IMAGE_NT_HEADERS = new byte[0xf8]; // pinh
var IMAGE_DOS_HEADER = new byte[0x40]; // pidh
var PROCESS_INFO = new int[0x4]; // pi
var CONTEXT = new byte[0x2cc]; // ctx
byte* pish;
fixed (byte* p = &IMAGE_SECTION_HEADER[0])
pish = p;
byte* pinh;
fixed (byte* p = &IMAGE_NT_HEADERS[0])
pinh = p;
byte* pidh;
fixed (byte* p = &IMAGE_DOS_HEADER[0])
pidh = p;
byte* ctx;
fixed (byte* p = &CONTEXT[0])
ctx = p;
// Set the flag.
*(uint*)(ctx + 0x0 /* ContextFlags */) = CONTEXT_FULL;
// Get the DOS header of the EXE.
Buffer.BlockCopy(exeBuffer, 0, IMAGE_DOS_HEADER, 0, IMAGE_DOS_HEADER.Length);
/* Sanity check: See if we have MZ header. */
if (*(ushort*)(pidh + 0x0 /* e_magic */) != IMAGE_DOS_SIGNATURE)
return false;
var e_lfanew = *(int*)(pidh + 0x3c);
// Get the NT header of the EXE.
Buffer.BlockCopy(exeBuffer, e_lfanew, IMAGE_NT_HEADERS, 0, IMAGE_NT_HEADERS.Length);
/* Sanity check: See if we have PE00 header. */
if (*(uint*)(pinh + 0x0 /* Signature */) != IMAGE_NT_SIGNATURE)
return false;
// Run with parameters if necessary.
if (!string.IsNullOrEmpty(optionalArguments))
hostProcess += " " + optionalArguments;
if (!CreateProcess(null, hostProcess, IntPtr.Zero, IntPtr.Zero, false, CREATE_SUSPENDED, IntPtr.Zero, null, ref StartupInfo, PROCESS_INFO))
return false;
var ImageBase = new IntPtr(*(int*)(pinh + 0x34));
NtUnmapViewOfSection((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase);
if (VirtualAllocEx((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase, *(uint*)(pinh + 0x50 /* SizeOfImage */), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) == IntPtr.Zero)
Run(exeBuffer, hostProcess, optionalArguments); // Memory allocation failed; try again (this can happen in low memory situations)
fixed (byte* p = &exeBuffer[0])
NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, ImageBase, (IntPtr)p, *(uint*)(pinh + 84 /* SizeOfHeaders */), IntPtr.Zero);
for (ushort i = 0; i < *(ushort*)(pinh + 0x6 /* NumberOfSections */); i++)
{
Buffer.BlockCopy(exeBuffer, e_lfanew + IMAGE_NT_HEADERS.Length + (IMAGE_SECTION_HEADER.Length * i), IMAGE_SECTION_HEADER, 0, IMAGE_SECTION_HEADER.Length);
fixed (byte* p = &exeBuffer[*(uint*)(pish + 0x14 /* PointerToRawData */)])
NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, (IntPtr)((int)ImageBase + *(uint*)(pish + 0xc /* VirtualAddress */)), (IntPtr)p, *(uint*)(pish + 0x10 /* SizeOfRawData */), IntPtr.Zero);
}
NtGetContextThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, (IntPtr)ctx);
NtWriteVirtualMemory((IntPtr)PROCESS_INFO[0] /* pi.hProcess */, (IntPtr)(*(uint*)(ctx + 0xAC /* ecx */)), ImageBase, 0x4, IntPtr.Zero);
*(uint*)(ctx + 0xB0 /* eax */) = (uint)ImageBase + *(uint*)(pinh + 0x28 /* AddressOfEntryPoint */);
NtSetContextThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, (IntPtr)ctx);
NtResumeThread((IntPtr)PROCESS_INFO[1] /* pi.hThread */, IntPtr.Zero);
return true;
}
#region WinNT Definitions
private const uint CONTEXT_FULL = 0x10007;
private const int CREATE_SUSPENDED = 0x4;
private const int MEM_COMMIT = 0x1000;
private const int MEM_RESERVE = 0x2000;
private const int PAGE_EXECUTE_READWRITE = 0x40;
private const ushort IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ
private const uint IMAGE_NT_SIGNATURE = 0x00004550; // PE00
private static short SW_SHOW = 5;
private static short SW_HIDE = 0;
private const uint STARTF_USESTDHANDLES = 0x00000100;
private const uint STARTF_USESHOWWINDOW = 0x00000001;
#region WinAPI
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, int[] lpProcessInfo);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern uint NtUnmapViewOfSection(IntPtr hProcess, IntPtr lpBaseAddress);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtWriteVirtualMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, IntPtr lpNumberOfBytesWritten);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtGetContextThread(IntPtr hThread, IntPtr lpContext);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtSetContextThread(IntPtr hThread, IntPtr lpContext);
[DllImport("ntdll.dll", SetLastError = true)]
private static extern uint NtResumeThread(IntPtr hThread, IntPtr SuspendCount);
#endregion
#endregion
}
if you are looking for running Exe files using C#, then this link provides a good explanation with a simple but easy to follow example on how Process and Process.Start should be used.
In a nutshell, you can do a
Process.Start("notepad.exe")
to run unmanaged exe/applications.
if that does not work, provide the fullpath of the application, like
Process.Start(#"c:\windows\system32\notepad.exe")
(I am just assuming notepad.exe exists on that folder, but you get the idea.
Use [Process.Start()][1] (or another overload), and let the O/S do the loading into memory.

Categories

Resources