diff --git a/Greenshot/Destinations/EmailDestination.cs b/Greenshot/Destinations/EmailDestination.cs
index bc3b401b0..41162f690 100644
--- a/Greenshot/Destinations/EmailDestination.cs
+++ b/Greenshot/Destinations/EmailDestination.cs
@@ -72,6 +72,7 @@ namespace Greenshot.Destinations {
exePath = GetExePath("OUTLOOK.EXE");
if (exePath != null && File.Exists(exePath)) {
applicationIcon = GetExeIcon(exePath, 0);
+ WindowDetails.AddProcessToExcludeFromFreeze("outlook");
if (conf.OutlookAllowExportInMeetings) {
meetingIcon = GetExeIcon(exePath, 2);
}
diff --git a/Greenshot/Destinations/ExcelDestination.cs b/Greenshot/Destinations/ExcelDestination.cs
index 6f6bd929e..5cd87b4eb 100644
--- a/Greenshot/Destinations/ExcelDestination.cs
+++ b/Greenshot/Destinations/ExcelDestination.cs
@@ -48,6 +48,7 @@ namespace Greenshot.Destinations {
if (exePath != null && File.Exists(exePath)) {
applicationIcon = GetExeIcon(exePath, 0);
workbookIcon = GetExeIcon(exePath, 1);
+ WindowDetails.AddProcessToExcludeFromFreeze("excel");
} else {
exePath = null;
}
diff --git a/Greenshot/Destinations/OneNoteDestination.cs b/Greenshot/Destinations/OneNoteDestination.cs
index 1fdbda61c..96a6c04be 100644
--- a/Greenshot/Destinations/OneNoteDestination.cs
+++ b/Greenshot/Destinations/OneNoteDestination.cs
@@ -47,6 +47,7 @@ namespace Greenshot.Destinations {
if (exePath != null && File.Exists(exePath)) {
applicationIcon = GetExeIcon(exePath, 0);
notebookIcon = GetExeIcon(exePath, 0);
+ WindowDetails.AddProcessToExcludeFromFreeze("onenote");
} else {
exePath = null;
}
diff --git a/Greenshot/Destinations/PowerpointDestination.cs b/Greenshot/Destinations/PowerpointDestination.cs
index e99f6e89c..cd0d842c3 100644
--- a/Greenshot/Destinations/PowerpointDestination.cs
+++ b/Greenshot/Destinations/PowerpointDestination.cs
@@ -48,6 +48,7 @@ namespace Greenshot.Destinations {
if (exePath != null && File.Exists(exePath)) {
applicationIcon = GetExeIcon(exePath, 0);
presentationIcon = GetExeIcon(exePath, 1);
+ WindowDetails.AddProcessToExcludeFromFreeze("powerpnt");
} else {
exePath = null;
}
diff --git a/Greenshot/Forms/CaptureForm.cs b/Greenshot/Forms/CaptureForm.cs
index 4a8b3404f..c402aeb91 100644
--- a/Greenshot/Forms/CaptureForm.cs
+++ b/Greenshot/Forms/CaptureForm.cs
@@ -107,7 +107,10 @@ namespace Greenshot.Forms {
// Make sure we never capture the captureform
WindowDetails.RegisterIgnoreHandle(this.Handle);
- // TODO: Need to call unregister at close
+ // Unregister at close
+ this.FormClosing += delegate {
+ WindowDetails.UnregisterIgnoreHandle(this.Handle);
+ };
// set cursor location
cursorPos = WindowCapture.GetCursorLocation();
diff --git a/Greenshot/Helpers/Log4NET.cs b/Greenshot/Helpers/Log4NET.cs
deleted file mode 100644
index 91a0be796..000000000
--- a/Greenshot/Helpers/Log4NET.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * User: Robin
- * Date: 05.04.2010
- */
-using System;
-using System.IO;
-using log4net.Util;
-
-namespace Greenshot.Helpers {
- ///
- /// Description of Log4NET.
- ///
- public class SpecialFolderPatternConverter : PatternConverter {
- override protected void Convert(TextWriter writer, object state) {
- Environment.SpecialFolder specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), base.Option, true);
- writer.Write(Environment.GetFolderPath(specialFolder));
- }
- }
-}
diff --git a/GreenshotPlugin/Core/WindowsHelper.cs b/GreenshotPlugin/Core/WindowsHelper.cs
index 8b6e1235f..af0b065bf 100644
--- a/GreenshotPlugin/Core/WindowsHelper.cs
+++ b/GreenshotPlugin/Core/WindowsHelper.cs
@@ -166,7 +166,14 @@ namespace GreenshotPlugin.Core {
private static CoreConfiguration conf = IniConfig.GetIniSection();
private static List ignoreHandles = new List();
private static Dictionary iconCache = new Dictionary();
-
+ private static List excludeProcessesFromFreeze = new List();
+
+ public static void AddProcessToExcludeFromFreeze(string processname) {
+ if (!excludeProcessesFromFreeze.Contains(processname)) {
+ excludeProcessesFromFreeze.Add(processname);
+ }
+ }
+
internal static bool isIgnoreHandle(IntPtr handle) {
return ignoreHandles.Contains(handle);
}
@@ -223,13 +230,67 @@ namespace GreenshotPlugin.Core {
frozen = false;
}
+ public string ProcessPath {
+ get {
+ if (Handle == IntPtr.Zero) {
+ // not a valid window handle
+ return string.Empty;
+ }
+ StringBuilder _PathBuffer = new StringBuilder(512);
+ // Get the process id
+ uint processid;
+ User32.GetWindowThreadProcessId(Handle, out processid);
+
+ // Try the GetModuleFileName method first since it's the fastest.
+ // May return ACCESS_DENIED (due to VM_READ flag) if the process is not owned by the current user.
+ // Will fail if we are compiled as x86 and we're trying to open a 64 bit process...not allowed.
+ IntPtr hprocess = Kernel32.OpenProcess(ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VMRead, false, processid);
+ if (hprocess != IntPtr.Zero) {
+ try {
+ if (Kernel32.GetModuleFileNameEx(hprocess, IntPtr.Zero, _PathBuffer, (uint)_PathBuffer.Capacity) > 0) {
+ return _PathBuffer.ToString();
+ }
+ } finally {
+ Kernel32.CloseHandle(hprocess);
+ }
+ }
+
+ hprocess = Kernel32.OpenProcess(ProcessAccessFlags.QueryInformation, false, processid);
+ if (hprocess != IntPtr.Zero) {
+ try {
+ // Try this method for Vista or higher operating systems
+ uint size = (uint)_PathBuffer.Capacity;
+ if ((Environment.OSVersion.Version.Major >= 6) && (Kernel32.QueryFullProcessImageName(hprocess, 0, _PathBuffer, ref size) && (size > 0))) {
+ return _PathBuffer.ToString();
+ }
+
+ // Try the GetProcessImageFileName method
+ if (Kernel32.GetProcessImageFileName(hprocess, _PathBuffer, (uint)_PathBuffer.Capacity) > 0) {
+ string dospath = _PathBuffer.ToString();
+ foreach (string drive in Environment.GetLogicalDrives()) {
+ if (Kernel32.QueryDosDevice(drive.TrimEnd('\\'), _PathBuffer, (uint)_PathBuffer.Capacity) > 0) {
+ if (dospath.StartsWith(_PathBuffer.ToString())) {
+ return drive + dospath.Remove(0, _PathBuffer.Length);
+ }
+ }
+ }
+ }
+ } finally {
+ Kernel32.CloseHandle(hprocess);
+ }
+ }
+
+ return string.Empty;
+ }
+ }
+
///
/// Get the icon belonging to the process
///
public Image DisplayIcon {
get {
try {
- string filename = Process.MainModule.FileName;
+ string filename = ProcessPath;
if (!iconCache.ContainsKey(filename)) {
Image icon = null;
if (File.Exists(filename)) {
@@ -244,6 +305,7 @@ namespace GreenshotPlugin.Core {
return iconCache[filename];
} catch (Exception ex) {
LOG.WarnFormat("Couldn't get icon for window {0} due to: {1}", Text, ex.Message);
+ LOG.Warn(ex);
}
return null;
}
@@ -1211,26 +1273,38 @@ namespace GreenshotPlugin.Core {
User32.SendMessage(Handle, (int)WindowsMessages.WM_VSCROLL, ptrWparam, ptrLparam);
}
+ private bool CanFreezeOrUnfreeze(string titleOrProcessname) {
+ if (string.IsNullOrEmpty(titleOrProcessname)) {
+ return false;
+ }
+ if (titleOrProcessname.ToLower().Contains("greenshot")) {
+ return false;
+ }
+
+ foreach (string excludeProcess in excludeProcessesFromFreeze) {
+ if (titleOrProcessname.ToLower().Contains(excludeProcess)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
///
/// Freezes the process belonging to the window
/// Warning: Use only if no other way!!
///
private void FreezeWindow() {
Process proc = Process.GetProcessById(this.ProcessId.ToInt32());
-
- if (proc.ProcessName == string.Empty){
+ string processName = proc.ProcessName;
+ if (!CanFreezeOrUnfreeze(processName)) {
+ LOG.DebugFormat("Not freezing {0}", processName);
return;
}
- if (proc.ProcessName.ToLower().Contains("greenshot")) {
- LOG.DebugFormat("Not freezing ourselves, process was: {0}", proc.ProcessName);
+ if (!CanFreezeOrUnfreeze(Text)) {
+ LOG.DebugFormat("Not freezing {0}", processName);
return;
}
- // TODO: Check Outlook, Office etc?
- if (proc.ProcessName.ToLower().Contains("outlook")) {
- LOG.DebugFormat("Not freezing outlook due to Destinations, process was: {0}", proc.ProcessName);
- return;
- }
- LOG.DebugFormat("Freezing process: {0}", proc.ProcessName);
+ LOG.DebugFormat("Freezing process: {0}", processName);
foreach (ProcessThread pT in proc.Threads) {
IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
@@ -1248,15 +1322,17 @@ namespace GreenshotPlugin.Core {
///
public void UnfreezeWindow() {
Process proc = Process.GetProcessById(this.ProcessId.ToInt32());
-
- if (proc.ProcessName == string.Empty) {
+
+ string processName = proc.ProcessName;
+ if (!CanFreezeOrUnfreeze(processName)) {
+ LOG.DebugFormat("Not unfreezing {0}", processName);
return;
}
- if (proc.ProcessName.ToLower().Contains("greenshot")) {
- LOG.DebugFormat("Not unfreezing ourselves, process was: {0}", proc.ProcessName);
+ if (!CanFreezeOrUnfreeze(Text)) {
+ LOG.DebugFormat("Not unfreezing {0}", processName);
return;
}
- LOG.DebugFormat("Unfreezing process: {0}", proc.ProcessName);
+ LOG.DebugFormat("Unfreezing process: {0}", processName);
foreach (ProcessThread pT in proc.Threads) {
IntPtr pOpenThread = Kernel32.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
diff --git a/GreenshotPlugin/UnmanagedHelpers/Enumerations.cs b/GreenshotPlugin/UnmanagedHelpers/Enumerations.cs
index c2a432366..364eedfb2 100644
--- a/GreenshotPlugin/UnmanagedHelpers/Enumerations.cs
+++ b/GreenshotPlugin/UnmanagedHelpers/Enumerations.cs
@@ -926,4 +926,18 @@ namespace GreenshotPlugin.UnmanagedHelpers {
SMTO_ABORTIFHUNG = 0x2,
SMTO_NOTIMEOUTIFNOTHUNG = 0x8
}
+
+ [Flags]
+ public enum ProcessAccessFlags : uint {
+ All = 0x001F0FFF,
+ Terminate = 0x00000001,
+ CreateThread = 0x00000002,
+ VMOperation = 0x00000008,
+ VMRead = 0x00000010,
+ VMWrite = 0x00000020,
+ DupHandle = 0x00000040,
+ SetInformation = 0x00000200,
+ QueryInformation = 0x00000400,
+ Synchronize = 0x00100000
+ }
}
diff --git a/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs b/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs
index e824edd72..0b0351209 100644
--- a/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs
+++ b/GreenshotPlugin/UnmanagedHelpers/Kernel32.cs
@@ -20,6 +20,7 @@
*/
using System;
using System.Runtime.InteropServices;
+using System.Text;
namespace GreenshotPlugin.UnmanagedHelpers {
[Flags]
@@ -48,11 +49,28 @@ namespace GreenshotPlugin.UnmanagedHelpers {
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AllocConsole();
- [DllImport("kernel32")]
+ [DllImport("kernel32", SetLastError = true)]
public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
- [DllImport("kernel32")]
+ [DllImport("kernel32", SetLastError = true)]
public static extern uint SuspendThread(IntPtr hThread);
- [DllImport("kernel32")]
+ [DllImport("kernel32", SetLastError = true)]
public static extern int ResumeThread(IntPtr hThread);
+ [DllImport("kernel32", SetLastError = true)]
+ public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
+ [DllImport("kernel32", SetLastError = true)]
+ public static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, StringBuilder lpExeName, ref uint lpdwSize);
+ [DllImport("kernel32", SetLastError = true)]
+ public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, uint uuchMax);
+ [DllImport("kernel32", SetLastError = true)]
+ public static extern IntPtr GetModuleHandle(string lpModuleName);
+ [DllImport("kernel32", SetLastError = true)]
+ public static extern bool CloseHandle(IntPtr hObject);
+
+ // TODO: Move to PSAPI.cs ??
+ [DllImport("psapi", SetLastError = true)]
+ public static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, StringBuilder lpFilename, uint nSize);
+ [DllImport("psapi", SetLastError = true)]
+ public static extern uint GetProcessImageFileName(IntPtr hProcess, StringBuilder lpImageFileName, uint nSize);
+
}
}