Trying to send a keystroke using SENDMESSAGE rather than SENDKEYS (VB.Net) [duplicate] - vb.net

I'm trying to use SendMessage to Notepad, so that I can insert written text without making Notepad the active window.
I have done something like this in the past using SendText, but that required giving Notepad focus.
Now, first I'm retrieving the Windows handle:
Process[] processes = Process.GetProcessesByName("notepad");
Console.WriteLine(processes[0].MainWindowHandle.ToString());
I've confirmed it's the right handle for Notepad, the same shown within Windows Task Manager.
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
From here, I haven't been able to get SendMessage to work in all my experimentation. Am I going in the wrong direction?

[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
private void button1_Click(object sender, EventArgs e)
{
Process [] notepads=Process.GetProcessesByName("notepad");
if(notepads.Length==0)return;
if (notepads[0] != null)
{
IntPtr child= FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null);
SendMessage(child, 0x000C, 0, textBox1.Text);
}
}
WM_SETTEXT=0x000c

You first have to find the child window where the text is entered. You can do this by finding the child window with the window class "Edit".
Once you have that window handle, use WM_GETTEXT to get the text which is already entered, then modify that text (e.g., add your own), then use WM_SETTEXT to send the modified text back.

using System.Diagnostics;
using System.Runtime.InteropServices;
static class Notepad
{
#region Imports
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")]
private static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
//this is a constant indicating the window that we want to send a text message
const int WM_SETTEXT = 0X000C;
#endregion
public static void SendText(string text)
{
Process notepad = Process.Start(#"notepad.exe");
System.Threading.Thread.Sleep(50);
IntPtr notepadTextbox = FindWindowEx(notepad.MainWindowHandle, IntPtr.Zero, "Edit", null);
SendMessage(notepadTextbox, WM_SETTEXT, 0, text);
}
}

Related

Implementing IServiceProvider and IInternetSecurityManager for WebBrowser control

I am trying to implement the IInternetSecurityManager on a WebBrowser control in order to override some IE security restrictions.
I have extended the WebBrowser control (call it MyWebBrowser) and have subclassed the WebBrowserSite class (call it ExtendedWebBrowserSite), and I've overridden the CreateWebBrowserSiteBase method on MyWebBrowser to return an instance of ExtendedWebBrowserSite.
class MyWebBrowser : System.Windows.Forms.WebBrowser
{
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
return new ExtendedWebBrowserSite(this);
}
}
My ExtendedWebBrowserSite class implements IServiceProvider and IInternetSecurityManager interfaces:
class ExtendedWebBrowserSite : WebBrowserSite, IServiceProvider, IInternetSecurityManager
{
// constructors omitted...
// IServiceProvider implementation
public int QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject)
{
if (guidService == SID_IInternetSecurityManager && riid == SID_IInternetSecurityManager)
{
ppvObject = this;
return HRESULTS.S_OK; // = 0x0
}
ppvObject = IntPtr.Zero;
return HRESULTS.E_NOINTERFACE; // 0x80004002
}
// IInternetSecurityManager implementation ommitted...
}
COM Interface Definitions
[ComImport, GuidAttribute("6D5140C1-7436-11CE-8034-00AA006009FA")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IServiceProvider
{
int QueryService(ref Guid guidService, ref Guid riid [MarshalAs(UnmanagedType.Interface)] out object ppvObject);
}
[ComImport, Guid("79EAC9EE-BAF9-11CE-8C82-00AA004BA90B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInternetSecurityManager
{
[return: MarshalAs(UnmanagedType.I4)][PreserveSig]
int SetSecuritySite([In] IntPtr pSite);
[return: MarshalAs(UnmanagedType.I4)][PreserveSig]
int GetSecuritySite([Out] IntPtr pSite);
[return: MarshalAs(UnmanagedType.I4)][PreserveSig]
int MapUrlToZone([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, out UInt32 pdwZone, UInt32 dwFlags);
[return: MarshalAs(UnmanagedType.I4)][PreserveSig]
int GetSecurityId([MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSecurityId, ref UInt32 pcbSecurityId, uint dwReserved);
[return: MarshalAs(UnmanagedType.I4)][PreserveSig]
int ProcessUrlAction([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, UInt32 dwAction, out byte pPolicy, UInt32 cbPolicy, byte pContext, UInt32 cbContext, UInt32 dwFlags, UInt32 dwReserved);
[return: MarshalAs(UnmanagedType.I4)][PreserveSig]
int QueryCustomPolicy([In,MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, ref Guid guidKey, ref byte ppPolicy, ref UInt32 pcbPolicy, ref byte pContext, UInt32 cbContext, UInt32 dwReserved);
[return: MarshalAs(UnmanagedType.I4)][PreserveSig]
int SetZoneMapping(UInt32 dwZone, [In,MarshalAs(UnmanagedType.LPWStr)] string lpszPattern, UInt32 dwFlags);
[return: MarshalAs(UnmanagedType.I4)][PreserveSig]
int GetZoneMappings(UInt32 dwZone, out IEnumString ppenumString, UInt32 dwFlags);
}
Results
The QueryService method is called when the WebBrowser is initialized. However, right after the QueryService method finishes and returns HRESULTS.E_NOINTERFACE, an AccessViolationException is thrown:
AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Windows.Forms.UnsafeNativeMethods.IOleObject.SetClientSite(IOleClientSite pClientSite)
at System.Windows.Forms.WebBrowserBase.TransitionFromLoadedToRunning()
at System.Windows.Forms.WebBrowserBase.TransitionUpTo(AXState state)
at System.Windows.Forms.WebBrowser.get_AxIWebBrowser2()
at System.Windows.Forms.WebBrowser.set_ScriptErrorsSuppressed(Boolean value)
Note: None of the IInternetSecurityManager methods get called, because QueryService never gets the chance to assign an implementation of it. So I omitted the IInernetSecurityManager methods for brevity.
Anyone have any ideas as to why this could be happening?

Embedding Selenium ChromeDriver in Windows Form

I'd like to embed the Selenium ChromeDriver within a Windows Form panel. I've successfully followed this example for embedding notepad in a Windows Form. I think the problem where I am having trouble is getting the MainWindowHandle from the ChromeDriver. Here's what I've got so far: (pastebin link of full code: https://pastebin.com/RNv2vbJ1)
//----------------------TEST---------------------
ChromeDriverService service = ChromeDriverService.CreateDefaultService();
service.HideCommandPromptWindow = true;
ChromeDriver driver = new ChromeDriver(service);
Console.WriteLine(driver.CurrentWindowHandle);
Process chromeDriverProcess = Process.GetProcessById(service.ProcessId);
//EmbeddedWindowHandle = driver.CurrentWindowHandle;
//----------------------TEST---------------------
ProcessStartInfo processInfo = new ProcessStartInfo("notepad.exe");
Process p = Process.Start(processInfo);
p.WaitForInputIdle();
EmbeddedWindowHandle = p.MainWindowHandle;
SetParent(EmbeddedWindowHandle, panel1.Handle);
MoveWindow(EmbeddedWindowHandle, 0, 0, panel1.Width, panel1.Height, true);
SetWindowLong(EmbeddedWindowHandle, GWL_STYLE, WS_VISIBLE);
So embedding a console app is somewhat similar to your approach but it is not the same. I found lot of threads which said it is not possible or it doesn't work
How to embed a Console application inside a Winforms application
Embedding a DOS console in a windows form
Embedding a DOS console in a windows form with Visual Basic
And there is the below link to create your own control as a CMD
https://www.codeproject.com/Articles/335909/Embedding-a-Console-in-a-C-Application
But I finally managed to get the below code working
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private IntPtr cmdPtr;
private int ConsoleWidth;
private IntPtr folderViewPtr;
private const int SWP_NOOWNERZORDER = 0x200;
private const int SWP_NOREDRAW = 0x8;
private const int SWP_NOZORDER = 0x4;
private const int SWP_SHOWWINDOW = 0x0040;
private const int WS_EX_MDICHILD = 0x40;
private const int SWP_FRAMECHANGED = 0x20;
private const int SWP_NOACTIVATE = 0x10;
private const int SWP_ASYNCWINDOWPOS = 0x4000;
private const int SWP_NOMOVE = 0x2;
private const int SWP_NOSIZE = 0x1;
private const int GWL_STYLE = (-16);
private const int GWL_EXSTYLE = (-20);
private const int WS_VISIBLE = 0x10000000;
private const int WM_CLOSE = 0x10;
private const int WS_CHILD = 0x40000000;
public abstract class WS
{
public const uint WS_OVERLAPPED = 0x00000000;
public const uint WS_POPUP = 0x80000000;
public const uint WS_CHILD = 0x40000000;
public const uint WS_MINIMIZE = 0x20000000;
public const uint WS_VISIBLE = 0x10000000;
public const uint WS_DISABLED = 0x08000000;
public const uint WS_CLIPSIBLINGS = 0x04000000;
public const uint WS_CLIPCHILDREN = 0x02000000;
public const uint WS_MAXIMIZE = 0x01000000;
public const uint WS_CAPTION = 0x00C00000; /* WS_BORDER | WS_DLGFRAME */
public const uint WS_BORDER = 0x00800000;
public const uint WS_DLGFRAME = 0x00400000;
public const uint WS_VSCROLL = 0x00200000;
public const uint WS_HSCROLL = 0x00100000;
public const uint WS_SYSMENU = 0x00080000;
public const uint WS_THICKFRAME = 0x00040000;
public const uint WS_GROUP = 0x00020000;
public const uint WS_TABSTOP = 0x00010000;
public const uint WS_MINIMIZEBOX = 0x00020000;
public const uint WS_MAXIMIZEBOX = 0x00010000;
public const uint WS_TILED = WS_OVERLAPPED;
public const uint WS_ICONIC = WS_MINIMIZE;
public const uint WS_SIZEBOX = WS_THICKFRAME;
public const uint WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW;
// Common Window Styles
public const uint WS_OVERLAPPEDWINDOW =
(WS_OVERLAPPED |
WS_CAPTION |
WS_SYSMENU |
WS_THICKFRAME |
WS_MINIMIZEBOX |
WS_MAXIMIZEBOX);
public const uint WS_POPUPWINDOW =
(WS_POPUP |
WS_BORDER |
WS_SYSMENU);
public const uint WS_CHILDWINDOW = WS_CHILD;
//Extended Window Styles
public const uint WS_EX_DLGMODALFRAME = 0x00000001;
public const uint WS_EX_NOPARENTNOTIFY = 0x00000004;
public const uint WS_EX_TOPMOST = 0x00000008;
public const uint WS_EX_ACCEPTFILES = 0x00000010;
public const uint WS_EX_TRANSPARENT = 0x00000020;
//#if(WINVER >= 0x0400)
public const uint WS_EX_MDICHILD = 0x00000040;
public const uint WS_EX_TOOLWINDOW = 0x00000080;
public const uint WS_EX_WINDOWEDGE = 0x00000100;
public const uint WS_EX_CLIENTEDGE = 0x00000200;
public const uint WS_EX_CONTEXTHELP = 0x00000400;
public const uint WS_EX_RIGHT = 0x00001000;
public const uint WS_EX_LEFT = 0x00000000;
public const uint WS_EX_RTLREADING = 0x00002000;
public const uint WS_EX_LTRREADING = 0x00000000;
public const uint WS_EX_LEFTSCROLLBAR = 0x00004000;
public const uint WS_EX_RIGHTSCROLLBAR = 0x00000000;
public const uint WS_EX_CONTROLPARENT = 0x00010000;
public const uint WS_EX_STATICEDGE = 0x00020000;
public const uint WS_EX_APPWINDOW = 0x00040000;
public const uint WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
public const uint WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
//#endif /* WINVER >= 0x0400 */
//#if(_WIN32_WINNT >= 0x0500)
public const uint WS_EX_LAYERED = 0x00080000;
//#endif /* _WIN32_WINNT >= 0x0500 */
//#if(WINVER >= 0x0500)
public const uint WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children
public const uint WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring
//#endif /* WINVER >= 0x0500 */
//#if(_WIN32_WINNT >= 0x0500)
public const uint WS_EX_COMPOSITED = 0x02000000;
public const uint WS_EX_NOACTIVATE = 0x08000000;
//#endif /* _WIN32_WINNT >= 0x0500 */
}
public Form1()
{
InitializeComponent();
this.Width = 700;
this.ConsoleWidth = this.Width;
folderViewPtr = FindWindow("Progman", null);
folderViewPtr = FindWindowEx(folderViewPtr, IntPtr.Zero, "SHELLDLL_DefView", null);
folderViewPtr = FindWindowEx(folderViewPtr, IntPtr.Zero, "SysListView32", "FolderView");
//SetWindowLong(this.Handle, -8, (int)folderViewPtr); //GWL_HWNDPARENT
Process p = Process.Start("cmd.exe", "/k cd %userprofile%\\desktop");
Thread.Sleep(500); // Allow the process to open it's window
cmdPtr = p.MainWindowHandle;
SetParent(cmdPtr, this.Handle);
SetWindowLong(this.Handle, -20, (int)(GetWindowLong(this.Handle, -20) | WS.WS_CLIPCHILDREN ));
// Remove border and whatnot
SetWindowLong(cmdPtr, GWL_STYLE, (int)(WS.WS_VISIBLE ));
long exStyle = GetWindowLong(p.MainWindowHandle, GWL_EXSTYLE);
exStyle &= ~(WS.WS_EX_APPWINDOW | WS.WS_EX_CLIENTEDGE);
SetWindowLong(p.MainWindowHandle, GWL_EXSTYLE, (int)0);
MoveWindow(cmdPtr, -2, -2, this.ConsoleWidth, this.Height, true);
SetWindowPos(this.Handle, (IntPtr)1, this.Left, this.Top, this.Width, this.Height, 0);
timer1.Start();
}
protected override void WndProc(ref Message message)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MOVE = 0xF010;
const int WM_WINDOWPOSCHANGING = 0x0046;
switch (message.Msg)
{
case WM_SYSCOMMAND:
int command = message.WParam.ToInt32() & 0xfff0;
if (command == SC_MOVE)
{
//return;
}
break;
case WM_WINDOWPOSCHANGING:
SetWindowPos(this.Handle, (IntPtr)1, this.Left, this.Top, this.Width, this.Height, 0x0004);
Debug.Print("WM_WINDOWPOSCHANGING");
break;
}
base.WndProc(ref message);
}
protected override void OnResize(EventArgs e)
{
if (this.cmdPtr != IntPtr.Zero)
{
MoveWindow(cmdPtr, 0, 0, this.ConsoleWidth, this.Height, true);
}
base.OnResize(e);
}
protected override void OnHandleDestroyed(EventArgs e)
{
if (cmdPtr != IntPtr.Zero)
{
PostMessage(cmdPtr, 0x0010, 0, 0);
}
base.OnHandleDestroyed(e);
}
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("User32.dll")]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool repaint);
[DllImport("User32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint message, int wparam, int lparam);
[DllImport("User32.dll")]
static extern void SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")]
static extern void SetWindowPos(IntPtr hWnd, IntPtr hWndNew, int x, int y, int cx, int cy, UInt32 uFlags);
[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(int xPoint, int yPoint);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr hWnd, IntPtr hWndA, string lpClassName, string lpWindowName);
private void Form1_Load(object sender, EventArgs e)
{
this.Left = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Right/2 - this.Width/2;
this.Top = 0;
}
private void timer1_Tick(object sender, EventArgs e)
{
//check if cmd still exists
if (!IsWindow(cmdPtr))
{
Application.Exit();
}
}
}
}
PS: Credits to https://github.com/KillPinguin/CommandLineWidget

IIS Hosted WCF Service permission to use interop

Is it possible to execute the following code, in any way through an IIS hosted wcf service? Any way I can give the appropriate permissions to the appPool? This code simply changes global printer settings:
public class PrinterSettings
{
#region "Private Variables"
private IntPtr hPrinter = new System.IntPtr();
private PRINTER_DEFAULTS PrinterValues = new PRINTER_DEFAULTS();
private PRINTER_INFO_2 pinfo = new PRINTER_INFO_2();
private DEVMODE dm;
private IntPtr ptrDM;
private IntPtr ptrPrinterInfo;
private int sizeOfDevMode = 0;
private int lastError;
private int nBytesNeeded;
private long nRet;
private int intError;
private System.Int32 nJunk;
private IntPtr yDevModeData;
#endregion
#region "Win API Def"
[DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern Int32 GetLastError();
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesA", SetLastError = true,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter,
[MarshalAs(UnmanagedType.LPStr)] string pDeviceNameg,
IntPtr pDevModeOutput, ref IntPtr pDevModeInput, int fMode);
[DllImport("winspool.Drv", EntryPoint = "GetPrinterA", SetLastError = true,
CharSet = CharSet.Ansi, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
private static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel,
IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);
/*[DllImport("winspool.Drv", EntryPoint="OpenPrinterA",
SetLastError=true, CharSet=CharSet.Ansi,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd)
[ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,
CallingConvention=CallingConvention.StdCall )]
public static extern long OpenPrinter(string pPrinterName,
ref IntPtr phPrinter, int pDefault);*/
/*[DllImport("winspool.Drv", EntryPoint="OpenPrinterA",
SetLastError=true, CharSet=CharSet.Ansi,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd);
*/
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA",
SetLastError = true, CharSet = CharSet.Ansi,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool
OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd);
[DllImport("winspool.drv", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr
pPrinter, int Command);
/*[DllImport("winspool.drv", CharSet=CharSet.Ansi, SetLastError=true)]
private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr
pPrinter, int Command);*/
// Wrapper for Win32 message formatter.
/*[DllImport("kernel32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private unsafe static extern int FormatMessage( int dwFlags,
ref IntPtr pMessageSource,
int dwMessageID,
int dwLanguageID,
ref string lpBuffer,
int nSize,
IntPtr* pArguments);*/
#endregion
#region "Data structure"
[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_DEFAULTS
{
public int pDatatype;
public int pDevMode;
public int DesiredAccess;
}
/*[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct PRINTER_DEFAULTS
{
public int pDataType;
public IntPtr pDevMode;
public ACCESS_MASK DesiredAccess;
}*/
[StructLayout(LayoutKind.Sequential)]
private struct PRINTER_INFO_2
{
[MarshalAs(UnmanagedType.LPStr)]
public string pServerName;
[MarshalAs(UnmanagedType.LPStr)]
public string pPrinterName;
[MarshalAs(UnmanagedType.LPStr)]
public string pShareName;
[MarshalAs(UnmanagedType.LPStr)]
public string pPortName;
[MarshalAs(UnmanagedType.LPStr)]
public string pDriverName;
[MarshalAs(UnmanagedType.LPStr)]
public string pComment;
[MarshalAs(UnmanagedType.LPStr)]
public string pLocation;
public IntPtr pDevMode;
[MarshalAs(UnmanagedType.LPStr)]
public string pSepFile;
[MarshalAs(UnmanagedType.LPStr)]
public string pPrintProcessor;
[MarshalAs(UnmanagedType.LPStr)]
public string pDatatype;
[MarshalAs(UnmanagedType.LPStr)]
public string pParameters;
public IntPtr pSecurityDescriptor;
public Int32 Attributes;
public Int32 Priority;
public Int32 DefaultPriority;
public Int32 StartTime;
public Int32 UntilTime;
public Int32 Status;
public Int32 cJobs;
public Int32 AveragePPM;
}
private const short CCDEVICENAME = 32;
private const short CCFORMNAME = 32;
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)]
public string dmFormName;
public short dmUnusedPadding;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}
#endregion
#region "Constants"
private const int DM_DUPLEX = 0x1000;
private const int DM_IN_BUFFER = 8;
private const int DM_OUT_BUFFER = 2;
private const int PRINTER_ACCESS_ADMINISTER = 0x4;
private const int PRINTER_ACCESS_USE = 0x8;
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
private const int PRINTER_ALL_ACCESS =
(STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER
| PRINTER_ACCESS_USE);
#endregion
#region "Function to change printer settings"
public bool ChangePrinterSetting(string PrinterName, PrinterData PS)
{
if (((int)PS.Duplex < 1) || ((int)PS.Duplex > 3))
{
throw new ArgumentOutOfRangeException("nDuplexSetting",
"nDuplexSetting is incorrect.");
}
else
{
dm = this.GetPrinterSettings(PrinterName);
dm.dmDefaultSource = (short)PS.source;
dm.dmOrientation = (short)PS.Orientation;
dm.dmPaperSize = (short)PS.Size;
dm.dmDuplex = (short)PS.Duplex;
Marshal.StructureToPtr(dm, yDevModeData, true);
pinfo.pDevMode = yDevModeData;
pinfo.pSecurityDescriptor = IntPtr.Zero;
/*update driver dependent part of the DEVMODE
1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
, ref pinfo.pDevMode, (DM_IN_BUFFER | DM_OUT_BUFFER));*/
try
{
Marshal.StructureToPtr(pinfo, ptrPrinterInfo, false);
}
catch
{
}
lastError = Marshal.GetLastWin32Error();
nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0));
if (nRet == 0)
{
//Unable to set shared printer settings.
lastError = Marshal.GetLastWin32Error();
//string myErrMsg = GetErrorMessage(lastError);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (hPrinter != IntPtr.Zero)
ClosePrinter(hPrinter);
return Convert.ToBoolean(nRet);
}
}
private DEVMODE GetPrinterSettings(string PrinterName)
{
PrinterData PData = new PrinterData();
DEVMODE dm;
const int PRINTER_ACCESS_ADMINISTER = 0x4;
const int PRINTER_ACCESS_USE = 0x8;
const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
PrinterValues.pDatatype = 0;
PrinterValues.pDevMode = 0;
PrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;
nRet = Convert.ToInt32(OpenPrinter(PrinterName,
out hPrinter, ref PrinterValues));
if (nRet == 0)
{
lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error());
}
GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out nBytesNeeded);
if (nBytesNeeded <= 0)
{
throw new System.Exception("Unable to allocate memory");
}
else
{
// Allocate enough space for PRINTER_INFO_2...
{// ptrPrinterIn fo =
Marshal.AllocCoTaskMem(nBytesNeeded);
};
ptrPrinterInfo = Marshal.AllocHGlobal(nBytesNeeded);
// The second GetPrinter fills in all the current settings, so all you
// need to do is modify what you're interested in...
nRet = Convert.ToInt32(GetPrinter(hPrinter, 2,
ptrPrinterInfo, nBytesNeeded, out nJunk));
if (nRet == 0)
{
lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error());
}
pinfo = (PRINTER_INFO_2)Marshal.PtrToStructure(ptrPrinterInfo,
typeof(PRINTER_INFO_2));
IntPtr Temp = new IntPtr();
if (pinfo.pDevMode == IntPtr.Zero)
{
// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
// DocumentProperties...
IntPtr ptrZero = IntPtr.Zero;
//get the size of the devmode structure
sizeOfDevMode = DocumentProperties(IntPtr.Zero, hPrinter,
PrinterName, ptrZero, ref ptrZero, 0);
ptrDM = Marshal.AllocCoTaskMem(sizeOfDevMode);
int i;
i = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, ptrDM,
ref ptrZero, DM_OUT_BUFFER);
if ((i < 0) || (ptrDM == IntPtr.Zero))
{
//Cannot get the DEVMODE structure.
throw new System.Exception("Cannot get DEVMODE data");
}
pinfo.pDevMode = ptrDM;
}
intError = DocumentProperties(IntPtr.Zero, hPrinter,
PrinterName, IntPtr.Zero, ref Temp, 0);
//IntPtr yDevModeData = Marshal.AllocCoTaskMem(i1);
yDevModeData = Marshal.AllocHGlobal(intError);
intError = DocumentProperties(IntPtr.Zero, hPrinter,
PrinterName, yDevModeData, ref Temp, 2);
dm = (DEVMODE)Marshal.PtrToStructure(yDevModeData, typeof(DEVMODE));
//nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
// , ref yDevModeData, (DM_IN_BUFFER | DM_OUT_BUFFER));
if ((nRet == 0) || (hPrinter == IntPtr.Zero))
{
lastError = Marshal.GetLastWin32Error();
//string myErrMsg = GetErrorMessage(lastError);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return dm;
}
#endregion
}
}
However, I cannot get this code to execute in the IIS hosted wcf service. I've tried creating an external program and then use Process.start to execute a console app that runs the code shown above - but still won't execute.

No Events when using reflection on Excel Application COM Object

I have an Excel template that I use to link to my application via this method:
Excel VBA:
objApp.SetExcelApp Application
Inside my application code, I want to use reflection to hook up to the WorkbookBeforeClose event on the Excel Application so I can do stuff when that event fires:
VB.NET:
Public Sub SetExcelApp(ByRef objExcel As Object)
Dim evWorkbookBeforeClose As Reflection.EventInfo = objExcel.GetType().GetEvent("WorkbookBeforeClose")
Dim mEvents As Reflection.EventInfo() = objExcel.GetType().GetEvents()
' do stuff
End Sub
Surprisingly, evWorkbookBeforeClose is Nothing - even mEvents is Nothing!
I can use methods and properties completely fine. Like objExcel.ActiveWorkbook and objExcel.Run("MyVBAMethod")
Anyone have ideas why this doesn't work? Is this not possible using reflection? Do I have to add a reference to the Excel interop?
EDIT: So if I add the Excel interop as a reference, it will work fine, since I can just use AddHandler on the event. But I'd still like to know why this doesn't work using reflection...
An interesting thing I saw was even when I changed this to objExcel As Microsoft.Office.Interop.Excel.Application, doing the above calls (GetEvent/GetEvents) still both return Nothing!
The events can be added using the System.Runtime.InteropServices.ComEventsHelper class.
E.g.
// source: http://www.guysmithferrier.com/downloads/csharp4.pdf
public static void ExcelExample() {
Type ty = Type.GetTypeFromProgID("Excel.Application");
Object o1 = Activator.CreateInstance(ty); // COM Object
o1.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, o1, new Object[] { true });
// Sh = Sheet?
// Target = Range
// 0x616 is the SelectionChanged event
ComEventsHelper.Combine(o1, new Guid("00024413-0000-0000-C000-000000000046"), 0x616, new Action<Object,Object>((Sh, Target) => {
int breakPoint = 1;
}));
}
public static void WordExample() {
Type ty = Type.GetTypeFromProgID("Word.Application");
Object o1 = Activator.CreateInstance(ty); // COM Object
o1.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, o1, new Object[] { true });
//var wdg4 = new Guid("00020A01-0000-0000-C000-000000000046"); // ApplicationEvents4 (Word)
//var wdg3 = new Guid("00020A00-0000-0000-C000-000000000046"); // ApplicationEvents3 (Word)
//var wdg2 = new Guid("000209FE-0000-0000-C000-000000000046"); // ApplicationEvents2 (Word)
var wdg1 = new Guid("000209F7-0000-0000-C000-000000000046"); // ApplicationEventsInterface (Word)
// 2 = Quit event
ComEventsHelper.Combine(o1, wdg1, 2, new Action(() => {
int breakPoint = 1;
}));
// 4 = Document open
ComEventsHelper.Combine(o1, wdg1, 4, new Action<Object>((Doc) => {
int breakPoint = 1;
}));
}
Seems like there is no MSDN reference for the dispatch ids (dispid) values. I found a few sources online, so I'll post them here:
Source: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/3625e60d-0e9c-4871-a0e8-bcedbbb31ce0/is-there-an-fixed-version-of-microsoftofficeinteropworddll-on-msdn?forum=worddev
Word:
[DispId(0x00000001)]
void Startup();
[DispId(0x00000002)]
void Quit();
[DispId(0x00000003)]
void DocumentChange();
[DispId(0x00000004)]
void DocumentOpen(Word.Document Doc);
[DispId(0x00000006)]
void DocumentBeforeClose(Word.Document Doc, ref bool Cancel);
[DispId(0x00000007)]
void DocumentBeforePrint(Word.Document Doc, ref bool Cancel);
[DispId(0x00000008)]
void DocumentBeforeSave(Word.Document Doc, ref bool SaveAsUI, ref bool Cancel);
[DispId(0x00000009)]
void NewDocument(Word.Document Doc);
[DispId(0x0000000a)]
void WindowActivate(Word.Document Doc, Word.Window Wn);
[DispId(0x0000000b)]
void WindowDeactivate(Word.Document Doc, Word.Window Wn);
[DispId(0x0000000c)]
void WindowSelectionChange(Word.Selection Sel);
[DispId(0x0000000d)]
void WindowBeforeRightClick(Word.Selection Sel, ref bool Cancel);
[DispId(0x0000000e)]
void WindowBeforeDoubleClick(Word.Selection Sel, ref bool Cancel);
[DispId(0x0000000f)]
void EPostagePropertyDialog(Word.Document Doc);
[DispId(0x00000010)]
void EPostageInsert(Word.Document Doc);
[DispId(0x00000011)]
void MailMergeAfterMerge(Word.Document Doc, Word.Document DocResult);
[DispId(0x00000012)]
void MailMergeAfterRecordMerge(Word.Document Doc);
[DispId(0x00000013)]
void MailMergeBeforeMerge(Word.Document Doc, int StartRecord, int endRecord, ref bool Cancel);
[DispId(0x00000014)]
void MailMergeBeforeRecordMerge(Word.Document Doc, ref bool Cancel);
[DispId(0x00000015)]
void MailMergeDataSourceLoad(Word.Document Doc);
[DispId(0x00000016)]
void MailMergeDataSourceValidate(Word.Document Doc, ref bool Handled);
[DispId(0x00000017)]
void MailMergeWizardSendToCustom(Word.Document Doc);
[DispId(0x00000018)]
void MailMergeWizardStateChange(Word.Document Doc, ref int FromState, ref int ToState, ref bool Handled);
[DispId(0x00000019)]
void WindowSize(Word.Document Doc, Word.Window Wn);
Excel:
Source: http://www.codeforge.com/read/240027/AppEvents.java__html
#DISPID(1565)
public void newWorkbook(Wb)
#DISPID(1558)
public void sheetSelectionChange(Sh, Target)
#DISPID(1559)
public void sheetBeforeDoubleClick(Sh, Target, Cancel);
#DISPID(1560)
public void sheetBeforeRightClick(Sh, Target, Cancel);
#DISPID(1561)
public void sheetActivate(Sh)
#DISPID(1562)
public void sheetDeactivate(Sh)
#DISPID(1563)
public void sheetCalculate(Sh)
#DISPID(1564)
public void sheetChange(Sh, Target)
#DISPID(1567)
public void workbookOpen(Wb)
#DISPID(1568)
public void workbookActivate(Wb)
#DISPID(1569)
public void workbookDeactivate(Wb)
#DISPID(1570)
public void workbookBeforeClose(Wb, Cancel)
#DISPID(1571)
public void workbookBeforeSave(Wb, SaveAsUI, Cancel)
#DISPID(1572)
public void workbookBeforePrint(Wb, Cancel)
#DISPID(1573)
public void workbookNewSheet(Wb, Sh)
#DISPID(1574)
public void workbookAddinInstall(Wb)
#DISPID(1575)
public void workbookAddinUninstall(Wb)
#DISPID(1554)
public void windowResize(Wb, Window)
#DISPID(1556)
public void windowActivate(Wb, Window)
#DISPID(1557)
public void windowDeactivate(Wb, Window)
#DISPID(1854)
public void sheetFollowHyperlink(Sh, Hyperlink)
#DISPID(2157)
public void sheetPivotTableUpdate(Sh, PivotTable)
#DISPID(2160)
public void workbookPivotTableCloseConnection(Wb, PivotTable)
#DISPID(2161)
public void workbookPivotTableOpenConnection(Wb, PivotTable)
#DISPID(2289)
public void workbookSync(Wb, SyncEventType)
#DISPID(2290)
public void workbookBeforeXmlImport(Wb, XmlMap, Url, IsRefresh, Cancel)
#DISPID(2291)
public void workbookAfterXmlImport(Wb, XmlMap, IsRefresh, Result)
#DISPID(2292)
public void workbookBeforeXmlExport(Wb, XmlMap, Url, Cancel)
#DISPID(2293)
public void workbookAfterXmlExport(Wb, XmlMap, Url, Result)
#DISPID(2611)
public void workbookRowsetComplete(Wb, Description, Sheet, Success)
#DISPID(2612)
public void afterCalculate()

Want to send the text to the Active Window

Want to send the text from my current vb application to the Active Window
and that text should be displayed in the text area of the active window
can anyone help me?
You need to send WM_SETTEXT message to the text control. Like this:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern void SendMessage(IntPtr hWnd, uint Msg, int wParam, string lParam);
private const int WM_SETTEXT = 0x0C;
private void button1_Click(object sender, EventArgs e)
{
string txt = "Hello World";
SendMessage(richTextBox1.Handle, WM_SETTEXT, 0, txt);
}