I have written sample IE add-on (based on samples found on internet). This addon makes log file and writes in it informations from OnDocumentComplete and OnBeforeNavigate2 events.
Unfortunatelly this is not working. I successfully instaled this addon in IE and it is visible - but as I said, it is not working(informations are not written in log file).
And here is code of this addon:
using System;
using System.Collections.Generic;
using System.Text;
using SHDocVw;
using mshtml;
using System.IO;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
namespace BHO_SampleApp
{
[ComVisible(true),
Guid("8a194578-81ea-4850-9911-13ba2d71efbd"),
ClassInterface(ClassInterfaceType.None)
]
public class BHO:IObjectWithSite
{
WebBrowser webBrowser;
public void OnDocumentComplete(object pDisp, ref object URL)
{
using (StreamWriter sw = new StreamWriter(#"C:\log.txt"))
{
sw.WriteLine(String.Format("site: {0}, {1}", URL, DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss")));
}
}
public void OnBeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)
{
using (StreamWriter sw = new StreamWriter(#"C:\log.txt"))
{
sw.WriteLine(String.Format("site: {0}, {1}", URL, DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss")));
}
}
#region BHO Internal Functions
public static string BHOKEYNAME = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects";
[ComRegisterFunction]
public static void RegisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME, true);
if (registryKey == null)
registryKey = Registry.LocalMachine.CreateSubKey(BHOKEYNAME);
string guid = type.GUID.ToString("B");
RegistryKey ourKey = registryKey.OpenSubKey(guid);
if (ourKey == null)
ourKey = registryKey.CreateSubKey(guid);
ourKey.SetValue("Alright", 1);
registryKey.Close();
ourKey.Close();
}
[ComUnregisterFunction]
public static void UnregisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME, true);
string guid = type.GUID.ToString("B");
if (registryKey != null)
registryKey.DeleteSubKey(guid, false);
}
public int SetSite(object site)
{
if (site != null)
{
webBrowser = (WebBrowser)site;
webBrowser.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
webBrowser.BeforeNavigate2+=new DWebBrowserEvents2_BeforeNavigate2EventHandler(this.OnBeforeNavigate2);
}
else
{
webBrowser.DocumentComplete -= new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);
webBrowser.BeforeNavigate2 -= new DWebBrowserEvents2_BeforeNavigate2EventHandler(this.OnBeforeNavigate2);
webBrowser = null;
}
return 0;
}
public int GetSite(ref Guid guid, out IntPtr ppvSite)
{
IntPtr punk = Marshal.GetIUnknownForObject(webBrowser);
int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
Marshal.Release(punk);
return hr;
}
#endregion
}
[
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")
]
public interface IObjectWithSite
{
[PreserveSig]
int SetSite([MarshalAs(UnmanagedType.IUnknown)]object site);
[PreserveSig]
int GetSite(ref Guid guid, out IntPtr ppvSite);
}
}
what is wrong with this addon?
If your browser is in Protected Mode (default), your add-on does not have the right to write to c:\log.txt. Try to disable he Protect Mode to check if it starts working.
http://surecode.me/aknoblog/ Here you can find one work snippet.
Related
I am developing a BHO for IE in C# that controls the navigation flow of IE by checking the URL in onBeforeNavigateEvent.
Everything works fine except that when a link is opened in a new tab then some of the tabs opened as About:Blank.
I have checked the logs and also debugged the BHO no exception is thrown. However in the case of About:Blank BHO is initiated SetSite and GetSite methods are called but navigation event is not fired.
Also it happens when links are opened in new tab rapidly.
For testing purpose I disabled the addon and IE worked fine i.e. no About:Blank page.
Loading time of BHO is 0.1s and Navigation time is 0.5s
So, what could be the issue ?
The source I followed to build this BHO is here
Current Environment: IE 11, Windows 10
Interop.cs
using System;
using System.Runtime.InteropServices;
namespace IE_BHO
{
[
ComImport(),
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")
]
interface IObjectWithSite
{
[PreserveSig]
int SetSite([In, MarshalAs(UnmanagedType.IUnknown)] object site);
[PreserveSig]
int GetSite(ref Guid guid, out IntPtr ppvSite);
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OLECMDTEXT
{
public uint cmdtextf;
public uint cwActual;
public uint cwBuf;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char rgwz;
}
[StructLayout(LayoutKind.Sequential)]
public struct OLECMD
{
public uint cmdID;
public uint cmdf;
}
[ComImport(), ComVisible(true),
Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleCommandTarget
{
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int QueryStatus(
[In] IntPtr pguidCmdGroup,
[In, MarshalAs(UnmanagedType.U4)] uint cCmds,
[In, Out, MarshalAs(UnmanagedType.Struct)] ref OLECMD prgCmds,
//This parameter must be IntPtr, as it can be null
[In, Out] IntPtr pCmdText);
[return: MarshalAs(UnmanagedType.I4)]
[PreserveSig]
int Exec(
//[In] ref Guid pguidCmdGroup,
//have to be IntPtr, since null values are unacceptable
//and null is used as default group!
[In] IntPtr pguidCmdGroup,
[In, MarshalAs(UnmanagedType.U4)] uint nCmdID,
[In, MarshalAs(UnmanagedType.U4)] uint nCmdexecopt,
[In] IntPtr pvaIn,
[In, Out] IntPtr pvaOut);
}
[Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
[InterfaceType(1)]
public interface IServiceProvider
{
int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject);
}
[
ComVisible(true),
Guid("4C1D2E51-018B-4A7C-8A07-618452573E42"),
InterfaceType(ComInterfaceType.InterfaceIsDual)
]
public interface IExtension
{
[DispId(1)]
string ActivateEndPoint(string licenseKey, string userAgent);
}
}
BHO.cs
using Microsoft.Win32;
using SHDocVw;
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Expando;
using System.Security.Permissions;
using System.Threading.Tasks;
using mshtml;
using System.Reflection;
using System.Diagnostics;
namespace IE_BHO
{
[
SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode),
ComVisible(true),
Guid("BDCB9FDA-8370-40D9-96C9-9D4B4C25C0D8"),
ClassInterface(ClassInterfaceType.None),
ProgId("myExtension"),
ComDefaultInterface(typeof(IExtension))
]
public class BHO : IObjectWithSite, IOleCommandTarget, IExtension
{
object _site;
IWebBrowser2 _webBrowser2;
#region Implementation of IObjectWithSite
int IObjectWithSite.SetSite(object site)
{
_site = site;
if (site != null)
{
var serviceProv = (IServiceProvider)_site;
var guidIWebBrowserApp = Marshal.GenerateGuidForType(typeof(IWebBrowserApp));
var guidIWebBrowser2 = Marshal.GenerateGuidForType(typeof(IWebBrowser2));
IntPtr intPtr;
serviceProv.QueryService(ref guidIWebBrowserApp, ref guidIWebBrowser2, out intPtr);
_webBrowser2 = (IWebBrowser2)Marshal.GetObjectForIUnknown(intPtr);
((DWebBrowserEvents2_Event)_webBrowser2).BeforeNavigate2 += OnBeforeNavigate2;
((DWebBrowserEvents2_Event)_webBrowser2).BeforeScriptExecute += S2_BeforeScriptExecute;
((DWebBrowserEvents2_Event)_webBrowser2).DownloadComplete += BHO_DownloadComplete;
}
else
{
((DWebBrowserEvents2_Event)_webBrowser2).BeforeNavigate2 -= OnBeforeNavigate2;
((DWebBrowserEvents2_Event)_webBrowser2).BeforeScriptExecute -= S2_BeforeScriptExecute;
((DWebBrowserEvents2_Event)_webBrowser2).DownloadComplete -= BHO_DownloadComplete;
_webBrowser2 = null;
}
return 0;
}
int IObjectWithSite.GetSite(ref Guid guid, out IntPtr ppvSite)
{
IntPtr punk = Marshal.GetIUnknownForObject(_webBrowser2);
int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
Marshal.Release(punk);
return hr;
}
public void OnBeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)
{
try
{
UrlObj dto = UrlManager.CheckUrl(URL.ToString());
if (dto.IsInList)
{
Cancel = true;
_webBrowser2.Navigate2("www.google.com");
}
}
catch (Exception ex)
{
}
}
private void S2_BeforeScriptExecute(object pDispWindow)
{
ExposeMethodstoJS();
}
private void BHO_DownloadComplete()
{
ExposeMethodstoJS();
}
private void ExposeMethodstoJS(string calledBy)
{
try
{
HTMLDocument doc = _webBrowser.Document as HTMLDocument;
if (doc != null)
{
IHTMLWindow2 tmpWindow = doc.parentWindow;
dynamic window = tmpWindow;
IExpando windowEx = (IExpando)window;
PropertyInfo p = windowEx.AddProperty("myExtension");
p.SetValue(windowEx, this);
}
}
catch (Exception ex)
{
}
}
#endregion
#region Implementation of IOleCommandTarget
int IOleCommandTarget.QueryStatus(IntPtr pguidCmdGroup, uint cCmds, ref OLECMD prgCmds, IntPtr pCmdText)
{
return 0;
}
int IOleCommandTarget.Exec(IntPtr pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
{
return 0;
}
#endregion
#region Implementation of IExtension
string IExtension.GetDetails()
{
return "Methods Exposed";
}
#endregion
#region COMRegistration
[ComRegisterFunction]
public static void RegisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.CreateSubKey(#"Software\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects");
RegistryKey guidKey = registryKey.CreateSubKey(type.GUID.ToString("B"));
registryKey.Close();
guidKey.Close();
}
[ComUnregisterFunction]
public static void UnregisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects", true);
string guid = type.GUID.ToString("B");
if (registryKey != null)
{
registryKey.DeleteSubKey(guid, false);
}
}
#endregion COMRegistration
}
}
Which version of IE and OS are you using?
I think the issue occurs because the new tab is opened and navigated at almost the same time. For the detailed information, you could refer to this link.
You could also try the resolution in the article: Install the most recent cumulative security update for Internet Explorer.
I'd like to change my desktop wallpaper. To do so I've written following code, but it doesn't work:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Background bg = new Background();
bg.DoSomething();
}
}
class Background
{
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SystemParametersInfo(uint uiAction, uint uiParam,
string pvParam, uint fWinIni);
private const uint SPI_SETDESKWALLPAPER = 0x0014;
private const uint SPIF_UPDATEINIFILE = 0x01;
private const uint SPIF_SENDWININICHANGE = 0x02;
private string pathtofiles;
private string[] filename;
private int count, o, ui;
private Object thisLock = new Object();
public Background()
{
pathtofiles = #"C:\Users\Mine\Desktop\Test\";
filename = new string[150];
count = 0;
o = 0;
ui = 0;
}
public void DoSomething()
{
System.IO.DirectoryInfo ParentDirectory = new System.IO.DirectoryInfo(#"C:\Users\Mine\Desktop\Test\");
foreach (System.IO.FileInfo f in ParentDirectory.GetFiles())
{
if (f.Name.EndsWith(".jpg"))
{
filename[count] = f.Name;
count++;
}
if (f.Name.EndsWith(".png"))
{
filename[count] = f.Name;
count++;
}
if (f.Name.EndsWith(".bmp"))
{
filename[count] = f.Name;
count++;
}
}
count = 0;
foreach (string s in filename)
{
if (System.IO.File.Exists(pathtofiles + s))
{
System.IO.Stream BitmapStream = System.IO.File.Open(pathtofiles + s, System.IO.FileMode.Open);
System.Drawing.Image img = System.Drawing.Image.FromStream(BitmapStream);
System.Drawing.Bitmap mBitmap = new System.Drawing.Bitmap(img);
mBitmap.Save(#"C:\Users\Mine\Desktop\BmpSpeichern\00" + o + ".bmp");
o++;
}
}
System.IO.DirectoryInfo ParentDirectory2 = new System.IO.DirectoryInfo(#"C:\Users\Mine\Desktop\BmpSpeichern\");
foreach (System.IO.FileInfo f in ParentDirectory2.GetFiles())
{
if (f.Name.EndsWith(".bmp"))
{
filename[count] = f.Name;
count++;
}
}
if (!SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, #"C:\Users\Mine\Desktop\BmpSpeichern\" + filename[ui],
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE))
{
throw new Win32Exception();
}
}
}
}
First I copy the image files to another directory then convert them to .bmp data type. Works perfectly but the call to the WINAPI function SystemParametersInfo fails to change the wallpaper.
What am I doing wrong?
I am trying to register a global hotkey in Visual c# 2012, build target framework .NET3, after using http://www.dreamincode.net/forums/topic/180436-global-hotkeys/ as a tutorial, I got the following (abbreviated) files:
GlobalHotkey.cs
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace barcodelabel
{
public class GlobalHotkey
{
private int modifier;
private int key;
private IntPtr hWnd;
private int id;
public GlobalHotkey(int modifier, Keys key, Form form)
{
this.modifier = modifier;
this.key = (int)key;
this.hWnd = form.Handle;
id = this.GetHashCode();
}
public bool Register()
{
return RegisterHotKey(hWnd, id, modifier, key);
}
public bool Unregister()
{
return UnregisterHotKey(hWnd, id);
}
public override int GetHashCode()
{
return modifier ^ key ^ hWnd.ToInt32();
}
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
}
}
GlobalHotkeyConstants.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace barcodelabel
{
class GlobalHotkeyConstants
{
public const int NOMOD = 0x0000;
public const int ALT = 0x0001;
public const int CTRL = 0x0002;
public const int SHIFT = 0x0004;
public const int WIN = 0x0008;
//windows message id for hotkey
public const int WM_HOTKEY_MSG_ID = 0x0312;
}
}
My Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Windows;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace barcodelabel
{
public partial class Form1 : Form
{
private GlobalHotkey ghk;
protected override void WndProc(ref Message m)
{
if (m.Msg == GlobalHotkeyConstants.WM_HOTKEY_MSG_ID) {
MessageBox.Show("HOTKEY PRESSED");
}
base.WndProc(ref m);
}
public Form1()
{
InitializeComponent();
this.ghk = new GlobalHotkey(GlobalHotkeyConstants.SHIFT, Keys.F10, this);
}
private void Form1_Load(object sender, EventArgs e)
{
if (!this.ghk.Register())
{
MessageBox.Show("Hotkey could not be registered");
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
this.ghk.Unregister();
}
}
No matter what hotkey I want to choose, it can not be registered. I tried using Hotkey Explorer from http://hkcmdr.anymania.com/ to check if the hotkey already was taken, but it only told me it was free.
What can I do to solve this?
I've wrote down your code in my VS and it worked properly. If you want to find the error, don't check a Boolean returned form API only. if it returns False, try using GetLastError API. Then you will have an error code. Refer to MSDN and get the error's description.
I created a sample bho using c# and exposed 1 function based from this post
Calling C# BHO methods from Javascript
The bho got registered to IE 9 successfully and i can access the exposed function in javascript on sites hosted in the net.
i created a test page using my local server and my bho function is now undefined.
i tried changing the url from localhost to ip address but still no effect.
below is my code. it would be great if somebody can check if something is wrong with my code;
thanks.
BHO.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms.Design;
using SHDocVw;
using mshtml;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Expando;
using Microsoft.Win32;
namespace MySampleBHO
{
[
ComVisible(true),
Guid("7bb16759-fdfc-4e3f-a081-eb65e4683640"),
ClassInterface(ClassInterfaceType.None),
ProgId("SIV"), ComDefaultInterface(typeof(IExtension))
]
public class BHO:IObjectWithSite, IExtension
{
WebBrowser webBrowser;
HTMLDocument document;
public void OnDocumentComplete(object pDisp, ref object URL) {
document = (HTMLDocument)webBrowser.Document;
dynamic window = webBrowser.Document.parentWindow;
IExpando windowEx = (IExpando)window;
windowEx.AddProperty("sEnhancer");
window.sEnhancer = this;
}
public String goEnhance(String ImageId, int Width, int Height) {
var img = document.getElementById(ImageId);
var src = img.getAttribute("src");
return src.ToString();
}
public int SetSite(object site)
{
if (site != null)
{
webBrowser = (WebBrowser)site;
webBrowser.DocumentComplete +=
new DWebBrowserEvents2_DocumentCompleteEventHandler(
this.OnDocumentComplete);
}
else
{
webBrowser.DocumentComplete -=
new DWebBrowserEvents2_DocumentCompleteEventHandler(
this.OnDocumentComplete);
webBrowser = null;
}
return 0;
}
public int GetSite(ref Guid guid, out IntPtr ppvSite)
{
IntPtr punk = Marshal.GetIUnknownForObject(webBrowser);
int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
Marshal.Release(punk);
return hr;
}
public static string BHOKEYNAME =
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects";
[ComRegisterFunction]
public static void RegisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME, true);
if (registryKey == null)
registryKey = Registry.LocalMachine.CreateSubKey(BHOKEYNAME);
string guid = type.GUID.ToString("B");
RegistryKey ourKey = registryKey.OpenSubKey(guid);
if (ourKey == null)
ourKey = registryKey.CreateSubKey(guid);
ourKey.SetValue("Alright", 1);
registryKey.Close();
ourKey.Close();
}
[ComUnregisterFunction]
public static void UnregisterBHO(Type type)
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BHOKEYNAME, true);
string guid = type.GUID.ToString("B");
if (registryKey != null)
registryKey.DeleteSubKey(guid, false);
}
}
}
IObjectWithSite.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace MySampleBHO
{
[
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")
]
public interface IObjectWithSite
{
[PreserveSig]
int SetSite([MarshalAs(UnmanagedType.IUnknown)]object site);
[PreserveSig]
int GetSite(ref Guid guid, out IntPtr ppvSite);
}
}
IExtension.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace MySampleBHO
{
[
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")
]
public interface IExtension
{
String goEnhance(String ImageId, int Width, int Height);
}
}
i already found the solution to my problem... just have to change some part in onDocumentComplete function...
Solution
Change below code:
public void OnDocumentComplete(object pDisp, ref object URL) {
document = (HTMLDocument)webBrowser.Document;
dynamic window = webBrowser.Document.parentWindow;
IExpando windowEx = (IExpando)window;
windowEx.AddProperty("sEnhancer");
window.sEnhancer = this;
}
to:
public void OnDocumentComplete(object pDisp, ref object URL) {
document = (HTMLDocument)webBrowser.Document;
dynamic window = webBrowser.Document.parentWindow;
IExpando windowEx = (IExpando)window;
PropertyInfo p = windowEx.AddProperty("sEnhancer");
p.SetValue(windowEx, this);
}
solution was based from this post BHO exposing javascript method works in IE 9+ but fails in earlier versions
I want to create a program that uses ClickOnce for installation and registers a file-association,
and always only starts a single instance, so that if a file of that file extension is clicked again it will be sent to the first (already opened) program.
Does anybody know of a good code-example of how to do that ?
Please keep in mind the ClickOnce part - because that changes how one should handle the SingleInstance bit.
I guess this will help you: http://www.openwinforms.com/single_instance_application.html
You should use a Mutex to check if you application is running:
static void Main()
{
bool createdNew;
using (Mutex mutex = new Mutex(true, Application.ProductName, out createdNew))
{
mutex.ReleaseMutex();
if (createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
}
else
{
using (Process currentProcess = Process.GetCurrentProcess())
{
foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName))
{
if (process.Id != currentProcess.Id)
{
User32.SetForegroundWindow(process.MainWindowHandle);
break;
}
}
}
}
}
}
The SetForegroundWindow:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
Same question over here: How can I build a single instance application using Click Once?
Try this on: http://northhorizon.net/2010/single-instance-clickonce/
I made an application that works this way. It uses Windows-messages to communicate. So in the seconde instance, you only need the Handle of the MainForm in the first instance. I saved this handle in a ClickOnce setting named hwnd.
using ProjectApplicationTemplate.Properties;
using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.Hosting;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace ProjectApplicationTemplate
{
static class Program
{
static Mutex mutex = new Mutex(true, guid());
static string guid()
{
// http://stackoverflow.com/questions/502303/how-do-i-programmatically-get-the-guid-of-an-application-in-net2-0
Assembly assembly = Assembly.GetExecutingAssembly();
var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
return attribute.Value;
}
static int MainWindowHandle
{
get
{
Settings.Default.Reload();
return Settings.Default.hwnd;
}
set
{
Settings sett = Settings.Default;
sett.hwnd = value;
sett.Save();
}
}
public static string GetFileName()
{
ActivationArguments a = AppDomain.CurrentDomain.SetupInformation.ActivationArguments;
// aangeklikt bestand achterhalen
string[] args = a == null ? null : a.ActivationData;
return args == null ? "" : args[0];
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
if (mutex.WaitOne(TimeSpan.Zero, true))
{
#region standaard
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#endregion
MainForm frm = new MainForm();
MainWindowHandle = (int)frm.Handle;
Application.Run(frm);
MainWindowHandle = 0;
mutex.ReleaseMutex();
}
else
{
int hwnd = 0;
while (hwnd == 0)
{
Thread.Sleep(5);
hwnd = MainWindowHandle;
}
Win32.CopyDataStruct cds = new Win32.CopyDataStruct();
try
{
string data = GetFileName();
cds.cbData = (data.Length + 1) * 2; // number of bytes
cds.lpData = Win32.LocalAlloc(0x40, cds.cbData); // known local-pointer in RAM
Marshal.Copy(data.ToCharArray(), 0, cds.lpData, data.Length); // Copy data to preserved local-pointer
cds.dwData = (IntPtr)1;
Win32.SendMessage((IntPtr)hwnd, Win32.WM_COPYDATA, IntPtr.Zero, ref cds);
}
finally
{
cds.Dispose();
}
}
}
}
}
And in your MainForm
using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Windows.Forms;
namespace ProjectApplicationTemplate
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
OpenFile(Program.GetFileName());
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case Win32.WM_COPYDATA:
Win32.CopyDataStruct st = (Win32.CopyDataStruct)Marshal.PtrToStructure(m.LParam, typeof(Win32.CopyDataStruct));
string strData = Marshal.PtrToStringUni(st.lpData);
OpenFile(strData);
Activate();
break;
default:
// let the base class deal with it
base.WndProc(ref m);
break;
}
}
void OpenFile(string filename)
{
if (filename == "") return;
if (!File.Exists(filename)) return;
IDocument[] vensters = MdiChildren.Select(T => (IDocument)T).Where(T => T.CurrentFileName == filename).ToArray();
if (vensters.Length == 0)
{
ChildForm frm = new ChildForm();
frm.OpenFile(filename);
frm.MdiParent = this;
frm.Show();
}
else
{
vensters[0].Activate();
}
}
private void fileMenu_DropDownOpening(object sender, EventArgs e)
{
IDocument active = (IDocument)ActiveMdiChild;
if (active == null)
{
saveToolStripMenuItem.Enabled = false;
saveAsToolStripMenuItem.Enabled = false;
printToolStripMenuItem.Enabled = false;
printSetupToolStripMenuItem.Enabled = false;
printPreviewToolStripMenuItem.Enabled = false;
}
else
{
saveToolStripMenuItem.Enabled = active.Changed;
saveAsToolStripMenuItem.Enabled = true;
printToolStripMenuItem.Enabled = active.CanPrint;
printSetupToolStripMenuItem.Enabled = active.CanPrint;
printPreviewToolStripMenuItem.Enabled = active.CanPrint;
}
// fill the MRU-list
tmiOnlangsGeopend.DropDownItems.Clear();
string RecentFolder = Environment.GetFolderPath(Environment.SpecialFolder.Recent);
string[] bestanden = Directory.GetFiles(RecentFolder).Where(T => T.EndsWith(".text.lnk")).ToArray();
if (bestanden.Length == 0)
{
tmiOnlangsGeopend.DropDownItems.Add(new ToolStripMenuItem(Properties.Resources.NoRecent) { Enabled = false });
}
else
{
foreach (string bestand in bestanden.OrderBy(T => File.GetLastWriteTime(T)).Reverse())
{
ToolStripMenuItem tmi = new ToolStripMenuItem(Path.GetFileNameWithoutExtension(bestand.Substring(0, bestand.Length - 4)));
tmi.Click += delegate { OpenFile(ResolveShortCut(bestand)); };
tmiOnlangsGeopend.DropDownItems.Add(tmi);
}
}
}
string ResolveShortCut(string shc)
{
// Add Reference -> COM -> Windows Script Host Object Model
if (File.Exists(shc))
{
IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell();
IWshRuntimeLibrary.IWshShortcut link = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(shc);
return link.TargetPath;
}
else
{
return "";
}
}
}
}
Win32.cs
using System;
using System.Runtime.InteropServices;
namespace ProjectApplicationTemplate
{
public partial class Win32
{
public const int WM_COPYDATA = 0x004A;
public struct CopyDataStruct : IDisposable
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
public void Dispose()
{
if (this.lpData != IntPtr.Zero)
{
LocalFree(this.lpData);
this.lpData = IntPtr.Zero;
}
}
}
/// <summary>
/// The SendMessage API
/// </summary>
/// <param name="hWnd">handle to the required window</param>
/// <param name="Msg">the system/Custom message to send</param>
/// <param name="wParam">first message parameter</param>
/// <param name="lParam">second message parameter</param>
/// <returns></returns>
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref CopyDataStruct lParam);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LocalAlloc(int flag, int size);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LocalFree(IntPtr p);
}
}
If anyone wants some more information about this:
http://pieterjan.pro/?a=Projecten_csharp_DrawIt.php
And this one is a c# template featuring loads of stuff:
- single-instance application with file-associations
- Localization (at runtime as well)
- MDI and interface for traversing the user commands
- Checking for updates
- Most-recently used list
http://pieterjan.pro/Projecten/csharp/ProjectApplicationTemplate.zip
You could do something similar to this:
using System.Diagnostics;
namespace Foo
{
class Bar
{
static void Main(string[] args)
{
Process p = Process.GetCurrentProcess();
Process [] processSearch = Process.GetProcessesByName(p.ProcessName);
if (processSearch.Length > 1)
{
return;
}
}
}
}