Calling SHGetFileInfo in thread to avoid UI freeze - windows

In a .NET 4.0 application (WPF) we're using SHGetFileInfo to obtain shell icons for a directory tree. Since this takes quite some time in some cases (i.e. for a network drive that is unreachable or for a floppy drive), we wanted to do this in a thread and then update the icon when it has been read in.
The call is basically the same, it is now just executed within a thread. Because someone said that the thread must be STA for this to work, we used Thread rather than ThreadPool for testing, with the same results. Using ThreadPool also did not work.
SHGetFileInfo succeeds (returns 1), but the hIcon member in the structure is zero.
IntPtr GetIcon(string name)
{
Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES | Shell32.SHGFI_SMALLICON;
Shell32.SHGetFileInfo(
name, System.IO.Directory.Exists(name) ? Shell32.FILE_ATTRIBUTE_DIRECTORY : Shell32.FILE_ATTRIBUTE_NORMAL,
ref shfi,
(uint) System.Runtime.InteropServices.Marshal.SizeOf(shfi),
flags );
return shfi.hIcon;
}
The very same code works fine from the GUI thread. What has to be done to make the function work from a separate thread, or, however, make it work without blocking the GUI thread?
Update: The code around this is basically this:
var thread = new System.Threading.Thread(() => {
var result = GetIcon("C:\\");
// ... do something with the result
});
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Start();
if only the lines within the thread delegate are left in, it works fine (but on the GUI thread, of course).
Update: For now, we just Invoke the call to SHGetFileInfo to make it work. This has the advantage that the original problem (the page with the file view was not displayed until all the icons have been loaded) has been solved, though it means that the page hangs for each icon. But at least the user now sees that something is going on. We're still looking for an actual solution to the problem.

Just successfully got something just like this working. It had previously been crashing badly when run outside of Visual Studio. Before that we'd often been getting back the default icon rather than the correct one for the file type (since we're after file icons, not the directory icon).
A summary of the factors to consider.
As discussed already, interacting with the Shell requires using a STA thread which pumps messages. A BackgroundWorker isn't going to be enough here.
When you initialize SHFILEINFO, set both string properties (display name and type name) to string.Empty. This isn't shown in most samples, but failing to do this was causing a crash for us. (In debug mode it meant that the first icon we got back was wrong, which could be the same as your problem.)
Check your interop declarations are right. For example, the SHFILEINFO class should presumably have a [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)] attribute.
A TaskScheduler For Background Tasks on an STA Thread
We're using the Task Parallel Library, so wanted a TaskScheduler that would schedule work on a suitable background thread. The following code sample is for a class that exposes a TaskScheduler property that can be used for this.
Note that in our we have a single instance of this class that lasts for the whole lifetime of the application, so we've not implemented IDisposable. If you want to create/destroy these you'll need to handle that.
namespace MyNamespace
{
using System;
using System.ComponentModel.Composition;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
/// <summary>
/// Exposes a <see cref="TaskScheduler"/> that schedules its work on a STA background thread.
/// </summary>
[Export]
public class StaTaskSchedulerSource
{
/// <summary>
/// A window that is used for message pumping.
/// </summary>
private Window window;
/// <summary>
/// Thread on which work is scheduled.
/// </summary>
private Thread thread;
/// <summary>
/// The <see cref="TaskScheduler"/> exposed by this class.
/// </summary>
private TaskScheduler taskScheduler;
/// <summary>
/// Initializes a new instance of the <see cref="StaTaskSchedulerSource"/> class.
/// </summary>
public StaTaskSchedulerSource()
{
using (ManualResetEvent re = new ManualResetEvent(false))
{
this.thread = new Thread(
() =>
{
this.window = new Window();
re.Set();
Dispatcher.Run();
});
this.thread.IsBackground = true;
this.thread.SetApartmentState(ApartmentState.STA);
this.thread.Start();
re.WaitOne();
}
this.window.Dispatcher.Invoke(
new Action(
() =>
{
this.taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
}));
}
/// <summary>
/// Gets a <see cref="TaskScheduler"/> that schedules work on a background STA
/// thread.
/// </summary>
public TaskScheduler TaskScheduler
{
get
{
return this.taskScheduler;
}
}
}
}
Of course, this whole thing just wraps using a dispatcher to invoke the calls on another thread. This can be a bit slow. So if processing many icons it would be better to batch them up. Also, we cache icons we've already retrieved so we don't need to use the Win Shell at all the second time around.
SafeIconHandle
You may also find the following wrapper for an icon handle useful. It derives from SafeHandle and ensures that you icon is properly destroyed under all circumstances.
namespace UnmanagedResourceLib
{
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
/// <summary>
/// A <see cref="SafeHandle"/> implementation for HICON icon handles.
/// </summary>
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
internal class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
{
/// <summary>
/// Prevents a default instance of the <see cref="SafeIconHandle"/> class from being created.
/// </summary>
private SafeIconHandle()
: base(true)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SafeIconHandle"/> class.
/// </summary>
/// <param name="nativeHandle">The HICON to wrap.</param>
/// <param name="ownsHandle"><c>true</c> if finalization of this object should cause the icon to be destroyed.</param>
public SafeIconHandle(IntPtr nativeHandle, bool ownsHandle)
: base(ownsHandle)
{
this.handle = nativeHandle;
}
/// <inheritdoc />
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
override protected bool ReleaseHandle()
{
return NativeMethods.DestroyIcon(this.handle);
}
/// <summary>
/// Exposes Windows API call to destroy an icon.
/// </summary>
[SuppressUnmanagedCodeSecurity]
internal static class NativeMethods
{
/// <summary>
/// Destroys an icon and frees any memory the icon occupied.
/// </summary>
/// <param name="hIcon">A handle to the icon to be destroyed.</param>
/// <returns><c>true</c> if the function succeeds.</returns>
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
public static extern bool DestroyIcon(IntPtr hIcon);
}
}
}

I don't think there's any problem. You don't need to use SetApartmentState. According to the documentation you do need to have called CoInitialize or OleInitialize, but I think this should have been called for you anyway by WPF.
I created a simple WPF application below. This works fine. SHGetFileInfo runs on a different thread to the UI thread and shfi.hIcon is not zero.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
Task<IntPtr> task = Task.Factory.StartNew(() => GetIcon("C:\\"));
}
private IntPtr GetIcon(string name)
{
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
var shfi = new Shell32.SHFILEINFO();
uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES | Shell32.SHGFI_SMALLICON;
Shell32.SHGetFileInfo(
name,
Directory.Exists(name) ? Shell32.FILE_ATTRIBUTE_DIRECTORY : Shell32.FILE_ATTRIBUTE_NORMAL,
ref shfi,
(uint) Marshal.SizeOf(shfi),
flags);
Debug.WriteLine(shfi.hIcon);
return shfi.hIcon;
}
}
public class Shell32
{
public const int MAX_PATH = 256;
// Browsing for directory.
public const uint BIF_RETURNONLYFSDIRS = 0x0001;
public const uint BIF_DONTGOBELOWDOMAIN = 0x0002;
public const uint BIF_STATUSTEXT = 0x0004;
public const uint BIF_RETURNFSANCESTORS = 0x0008;
public const uint BIF_EDITBOX = 0x0010;
public const uint BIF_VALIDATE = 0x0020;
public const uint BIF_NEWDIALOGSTYLE = 0x0040;
public const uint BIF_USENEWUI = (BIF_NEWDIALOGSTYLE | BIF_EDITBOX);
public const uint BIF_BROWSEINCLUDEURLS = 0x0080;
public const uint BIF_BROWSEFORCOMPUTER = 0x1000;
public const uint BIF_BROWSEFORPRINTER = 0x2000;
public const uint BIF_BROWSEINCLUDEFILES = 0x4000;
public const uint BIF_SHAREABLE = 0x8000;
public const uint SHGFI_ICON = 0x000000100; // get icon
public const uint SHGFI_DISPLAYNAME = 0x000000200; // get display name
public const uint SHGFI_TYPENAME = 0x000000400; // get type name
public const uint SHGFI_ATTRIBUTES = 0x000000800; // get attributes
public const uint SHGFI_ICONLOCATION = 0x000001000; // get icon location
public const uint SHGFI_EXETYPE = 0x000002000; // return exe type
public const uint SHGFI_SYSICONINDEX = 0x000004000; // get system icon index
public const uint SHGFI_LINKOVERLAY = 0x000008000; // put a link overlay on icon
public const uint SHGFI_SELECTED = 0x000010000; // show icon in selected state
public const uint SHGFI_ATTR_SPECIFIED = 0x000020000; // get only specified attributes
public const uint SHGFI_LARGEICON = 0x000000000; // get large icon
public const uint SHGFI_SMALLICON = 0x000000001; // get small icon
public const uint SHGFI_OPENICON = 0x000000002; // get open icon
public const uint SHGFI_SHELLICONSIZE = 0x000000004; // get shell size icon
public const uint SHGFI_PIDL = 0x000000008; // pszPath is a pidl
public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; // use passed dwFileAttribute
public const uint SHGFI_ADDOVERLAYS = 0x000000020; // apply the appropriate overlays
public const uint SHGFI_OVERLAYINDEX = 0x000000040; // Get the index of the overlay
public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
[DllImport("Shell32.dll")]
public static extern IntPtr SHGetFileInfo(
string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbFileInfo,
uint uFlags
);
#region Nested type: BROWSEINFO
[StructLayout(LayoutKind.Sequential)]
public struct BROWSEINFO
{
public IntPtr hwndOwner;
public IntPtr pidlRoot;
public IntPtr pszDisplayName;
[MarshalAs(UnmanagedType.LPTStr)] public string lpszTitle;
public uint ulFlags;
public IntPtr lpfn;
public int lParam;
public IntPtr iImage;
}
#endregion
#region Nested type: ITEMIDLIST
[StructLayout(LayoutKind.Sequential)]
public struct ITEMIDLIST
{
public SHITEMID mkid;
}
#endregion
#region Nested type: SHFILEINFO
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public const int NAMESIZE = 80;
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAMESIZE)] public string szTypeName;
};
#endregion
#region Nested type: SHITEMID
[StructLayout(LayoutKind.Sequential)]
public struct SHITEMID
{
public ushort cb;
[MarshalAs(UnmanagedType.LPArray)] public byte[] abID;
}
#endregion
}
/// <summary>
/// Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example.
/// </summary>
public class User32
{
/// <summary>
/// Provides access to function required to delete handle. This method is used internally
/// and is not required to be called separately.
/// </summary>
/// <param name="hIcon">Pointer to icon handle.</param>
/// <returns>N/A</returns>
[DllImport("User32.dll")]
public static extern int DestroyIcon(IntPtr hIcon);
}

Related

Restart Explorer.exe during MSI install doesn't work

I have a Visual Studio Setup Project that creates an MSI to install my application. My application has a shell extension with a icon overlay handler so explorer.exe needs to be restarted in order for the icon overlay handler to start working. I have registered a custom action to run on commit that restarts explorer using the following method:
public static void restartExplorer()
{
//stop the shell
try
{
Process process1 = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "CMD.exe";
startInfo.Arguments = "/C \"taskkill /f /im explorer.exe\"";
process1.StartInfo = startInfo;
process1.Start();
do
{
Thread.Sleep(100);
if (process1.HasExited)
{
break;
}
} while (true);
}
catch (Exception e)
{
Log.Error("restart explorer", e.StackTrace);
}
//restart the shell
string explorer = string.Format("{0}\\{1}", Environment.GetEnvironmentVariable("WINDIR"), "explorer.exe");
Process process = new Process();
process.StartInfo.FileName = explorer;
process.StartInfo.UseShellExecute = true;
process.Start();
}
This method works well when I test it from visual studio and call it from command line but when it is called from the MSI during install or uninstall it stops explorer, but does not restart it.
Does anyone know why it would work in all circumstances except when called by the MSI during install or uninstall?
Does anyone have an alternate way to restart the explorer from an MSI during install/uninstall?
I have honestly never had the chance to test this out, but here is a quick read: Registering Shell Extension Handlers. Essentially: you are to call SHChangeNotify specifying the SHCNE_ASSOCCHANGED event. If you do not call SHChangeNotify, the change might not be recognized until the system is rebooted.
Found this on github.com: RgssDecrypter - ShellExtension.cs. And another sample.
Killing the explorer is a bit rough... I suggest you use the Restart Manager API for that. The benefit is Explorer knows how to restart itself, and it will restore all opened windows after the restart. Here is a C# utility class that will do it for you. Just call this in you custom action:
...
var rm = new RestartManager();
rm.RestartExplorerProcesses();
...
/// <summary>
/// A utility class to restart programs the most gracefully possible. Wraps Windows <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/cc948910.aspx">Restart Manager API</see>. This class cannot be inherited.
/// </summary>
public sealed class RestartManager
{
/// <summary>
/// The default kill timeout value (2000).
/// </summary>
public const int DefaultKillTimeout = 2000;
/// <summary>
/// The default retry count value (10).
/// </summary>
public const int DefaultRetryCount = 10;
/// <summary>
/// The default retry timeout value (100).
/// </summary>
public const int DefaultRetryTimeout = 100;
/// <summary>
/// Initializes a new instance of the <see cref="RestartManager"/> class.
/// </summary>
public RestartManager()
{
KillTimeout = DefaultKillTimeout;
RetryCount = DefaultRetryCount;
RetryTimeout = DefaultRetryTimeout;
}
/// <summary>
/// Gets or sets the kill timeout in ms.
/// </summary>
/// <value>The kill timeout.</value>
public int KillTimeout { get; set; }
/// <summary>
/// Gets or sets the retry count.
/// </summary>
/// <value>The retry count.</value>
public int RetryCount { get; set; }
/// <summary>
/// Gets or sets the retry timeout in ms.
/// </summary>
/// <value>The retry timeout.</value>
public int RetryTimeout { get; set; }
/// <summary>
/// Restarts the Windows Explorer processes.
/// </summary>
/// <param name="stoppedAction">The stopped action.</param>
public void RestartExplorerProcesses() => RestartExplorerProcesses(null, false, out var error);
/// <summary>
/// Restarts the Windows Explorer processes.
/// </summary>
/// <param name="stoppedAction">The stopped action.</param>
public void RestartExplorerProcesses(ContextCallback stoppedAction) => RestartExplorerProcesses(stoppedAction, false, out var error);
/// <summary>
/// Restarts the Windows Explorer processes.
/// </summary>
/// <param name="stoppedAction">The stopped action.</param>
/// <param name="throwOnError">if set to <c>true</c> errors may be throw in case of Windows Restart Manager errors.</param>
public void RestartExplorerProcesses(ContextCallback stoppedAction, bool throwOnError) => RestartExplorerProcesses(stoppedAction, throwOnError, out var error);
/// <summary>
/// Restarts the Windows Explorer processes.
/// </summary>
/// <param name="stoppedAction">The stopped action.</param>
/// <param name="throwOnError">if set to <c>true</c> errors may be throw in case of Windows Restart Manager errors.</param>
/// <param name="error">The error, if any.</param>
public void RestartExplorerProcesses(ContextCallback stoppedAction, bool throwOnError, out Exception error)
{
var explorers = Process.GetProcessesByName("explorer").Where(p => IsExplorer(p)).ToArray();
Restart(explorers, stoppedAction, throwOnError, out error);
}
/// <summary>
/// Restarts the processes locking a specific file.
/// </summary>
/// <param name="path">The file path.</param>
/// <param name="stoppedAction">The stopped action.</param>
/// <param name="throwOnError">if set to <c>true</c> errors may be throw in case of Windows Restart Manager errors.</param>
/// <param name="error">The error, if any.</param>
/// <exception cref="ArgumentNullException">path is null.</exception>
public void RestartProcessesLockingFile(string path, ContextCallback stoppedAction, bool throwOnError, out Exception error)
{
if (path == null)
throw new ArgumentNullException(nameof(path));
var lockers = GetLockingProcesses(path, false, throwOnError, out error);
if (error != null)
return;
Restart(lockers, stoppedAction, throwOnError, out error);
}
/// <summary>
/// Restarts the Windows Explorer processes locking a specific file.
/// </summary>
/// <param name="path">The file path.</param>
/// <param name="stoppedAction">The stopped action.</param>
/// <param name="throwOnError">if set to <c>true</c> errors may be throw in case of Windows Restart Manager errors.</param>
/// <param name="error">The error, if any.</param>
/// <exception cref="ArgumentNullException">path is null.</exception>
public void RestartExplorerProcessesLockingFile(string path, ContextCallback stoppedAction, bool throwOnError, out Exception error)
{
if (path == null)
throw new ArgumentNullException(nameof(path));
var processes = GetLockingProcesses(path, false, throwOnError, out error);
if (error != null)
return;
var explorers = processes.Where(p => IsExplorer(p)).ToArray();
Restart(explorers, stoppedAction, throwOnError, out error);
}
/// <summary>
/// Determines whether the specified process is Windows Explorer.
/// </summary>
/// <param name="process">The process.</param>
/// <returns><c>true</c> if the specified process is Windows Explorer; otherwise, <c>false</c>.</returns>
public static bool IsExplorer(Process process)
{
if (process == null)
return false;
string explorerPath = Path.Combine(Environment.GetEnvironmentVariable("windir"), "explorer.exe");
return string.Compare(process.MainModule.FileName, explorerPath, StringComparison.OrdinalIgnoreCase) == 0;
}
/// <summary>
/// Gets a list of processes locking a specific file.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <param name="onlyRestartable">if set to <c>true</c> list only restartable processes.</param>
/// <param name="throwOnError">if set to <c>true</c> errors may be throw in case of Windows Restart Manager errors.</param>
/// <param name="error">The error, if any.</param>
/// <returns>A list of processes.</returns>
/// <exception cref="ArgumentNullException">filePath is null.</exception>
public IReadOnlyList<Process> GetLockingProcesses(string filePath, bool onlyRestartable, bool throwOnError, out Exception error)
{
if (filePath == null)
throw new ArgumentNullException(nameof(filePath));
return GetLockingProcesses(new[] { filePath }, onlyRestartable, throwOnError, out error);
}
// NOTE: file name comparison seems to be case insensitive
/// <summary>
/// Gets a list of processes locking a list of specific files.
/// </summary>
/// <param name="filePaths">The files paths.</param>
/// <param name="onlyRestartable">if set to <c>true</c> list only restartable processes.</param>
/// <param name="throwOnError">if set to <c>true</c> errors may be throw in case of Windows Restart Manager errors.</param>
/// <param name="error">The error, if any.</param>
/// <returns>A list of processes.</returns>
/// <exception cref="ArgumentNullException">filePaths is null.</exception>
public IReadOnlyList<Process> GetLockingProcesses(IEnumerable<string> filePaths, bool onlyRestartable, bool throwOnError, out Exception error)
{
if (filePaths == null)
throw new ArgumentNullException(nameof(filePaths));
var processes = new List<Process>();
var paths = new List<string>(filePaths);
var s = new StringBuilder(256);
int hr = RmStartSession(out int session, 0, s);
if (hr != 0)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return processes;
}
try
{
hr = RmRegisterResources(session, paths.Count, paths.ToArray(), 0, null, 0, null);
if (hr != 0)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return processes;
}
int procInfo = 0;
int rebootReasons = RmRebootReasonNone;
hr = RmGetList(session, out int procInfoNeeded, ref procInfo, null, ref rebootReasons);
if (hr == 0)
{
error = null;
return processes;
}
if (hr != ERROR_MORE_DATA)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return processes;
}
var processInfo = new RM_PROCESS_INFO[procInfoNeeded];
procInfo = processInfo.Length;
hr = RmGetList(session, out procInfoNeeded, ref procInfo, processInfo, ref rebootReasons);
if (hr != 0)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return processes;
}
for (int i = 0; i < procInfo; i++)
{
try
{
if (processInfo[i].bRestartable || !onlyRestartable)
{
var process = Process.GetProcessById(processInfo[i].Process.dwProcessId);
if (process != null)
{
processes.Add(process);
}
}
}
catch (Exception e)
{
error = e;
// do nothing, fail silently
return processes;
}
}
error = null;
return processes;
}
finally
{
RmEndSession(session);
}
}
/// <summary>
/// Restarts the specified processes.
/// </summary>
/// <param name="processes">The processes.</param>
/// <param name="stoppedAction">The stopped action.</param>
/// <param name="throwOnError">if set to <c>true</c> errors may be throw in case of Windows Restart Manager errors.</param>
/// <param name="error">The error, if any.</param>
/// <exception cref="ArgumentNullException">processes is null.</exception>
public void Restart(IEnumerable<Process> processes, ContextCallback stoppedAction, bool throwOnError, out Exception error)
{
if (processes == null)
throw new ArgumentNullException(nameof(processes));
if (processes.Count() == 0)
{
error = null;
return;
}
var s = new StringBuilder(256);
int hr = RmStartSession(out int session, 0, s);
if (hr != 0)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return;
}
try
{
var list = new List<RM_UNIQUE_PROCESS>();
foreach (var process in processes)
{
var p = new RM_UNIQUE_PROCESS()
{
dwProcessId = process.Id
};
long l = process.StartTime.ToFileTime();
p.ProcessStartTime.dwHighDateTime = (int)(l >> 32);
p.ProcessStartTime.dwLowDateTime = (int)(l & 0xFFFFFFFF);
list.Add(p);
}
hr = RmRegisterResources(session, 0, null, list.Count, list.ToArray(), 0, null);
if (hr != 0)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return;
}
int procInfo = 0;
int rebootReasons = RmRebootReasonNone;
hr = RmGetList(session, out int procInfoNeeded, ref procInfo, null, ref rebootReasons);
if (hr == 0)
{
error = null;
return;
}
if (hr != ERROR_MORE_DATA)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return;
}
var processInfo = new RM_PROCESS_INFO[procInfoNeeded];
procInfo = processInfo.Length;
hr = RmGetList(session, out procInfoNeeded, ref procInfo, processInfo, ref rebootReasons);
if (hr != 0)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return;
}
if (procInfo == 0)
{
error = null;
return;
}
bool hasError = false;
int wtk = GetWaitToKillTimeout();
var sw = new Stopwatch();
sw.Start();
bool finished = false;
var timer = new Timer((state) =>
{
if (!finished)
{
HardKill(processes);
}
}, null, wtk + 2000, Timeout.Infinite);
hr = RmShutdown(session, RmForceShutdown, percent =>
{
// add progress info code if needed
});
sw.Stop();
if (hr != 0)
{
if (!IsNonFatalError(hr))
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return;
}
hasError = true;
}
if (hasError)
{
HardKill(processes);
}
if (stoppedAction != null)
{
int retry = RetryCount;
while (retry > 0)
{
try
{
stoppedAction(session);
break;
}
catch
{
retry--;
Thread.Sleep(RetryTimeout);
}
}
}
hr = RmRestart(session, 0, percent2 =>
{
// add progress info code if needed
});
if (hr != 0)
{
error = new Win32Exception(hr);
if (throwOnError)
throw error;
return;
}
}
finally
{
RmEndSession(session);
}
error = null;
}
private void HardKill(IEnumerable<Process> processes)
{
// need a hard restart
foreach (var process in processes)
{
try
{
process.Refresh();
if (!process.HasExited)
{
process.Kill();
}
}
catch
{
// do nothing
}
}
Thread.Sleep(KillTimeout);
}
private static bool IsNonFatalError(int hr) => hr == ERROR_FAIL_NOACTION_REBOOT || hr == ERROR_FAIL_SHUTDOWN || hr == ERROR_SEM_TIMEOUT || hr == ERROR_CANCELLED;
/// <summary>
/// Gets the root Windows Explorer process.
/// </summary>
/// <returns>An instance of the Process type or null.</returns>
public static Process GetRootExplorerProcess()
{
Process oldest = null;
foreach (var process in EnumExplorerProcesses())
{
if (oldest == null || process.StartTime < oldest.StartTime)
{
oldest = process;
}
}
return oldest;
}
/// <summary>
/// Enumerates Windows Explorer processes.
/// </summary>
/// <returns>A list of Windows Explorer processes.</returns>
public static IEnumerable<Process> EnumExplorerProcesses()
{
string explorerPath = Path.Combine(Environment.GetEnvironmentVariable("windir"), "explorer.exe");
foreach (var process in Process.GetProcessesByName("explorer"))
{
if (string.Compare(process.MainModule.FileName, explorerPath, StringComparison.OrdinalIgnoreCase) == 0)
yield return process;
}
}
/// <summary>
/// Enumerates a specific process' windows.
/// </summary>
/// <param name="process">The process.</param>
/// <returns>A list of windows handles.</returns>
/// <exception cref="ArgumentNullException">process is null.</exception>
public static IReadOnlyList<IntPtr> EnumProcessWindows(Process process)
{
if (process == null)
throw new ArgumentNullException(nameof(process));
var handles = new List<IntPtr>();
EnumWindows((h, p) =>
{
GetWindowThreadProcessId(h, out int processId);
if (processId == process.Id)
{
handles.Add(h);
}
return true;
}, IntPtr.Zero);
return handles;
}
// https://technet.microsoft.com/en-us/library/cc976045.aspx
/// <summary>
/// Gets the wait to kill timeout, that is, how long the system waits for services to stop after notifying the service that the system is shutting down
/// </summary>
/// <returns>A number of milliseconds.</returns>
public static int GetWaitToKillTimeout()
{
using (var key = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Control", false))
{
if (key != null)
{
var v = key.GetValue("WaitToKillServiceTimeout", 0);
if (v != null && int.TryParse(v.ToString(), out int i))
return i;
}
return 0;
}
}
[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc callback, IntPtr extraData);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
private static extern int RmStartSession(out int pSessionHandle, int dwSessionFlags, StringBuilder strSessionKey);
[DllImport("rstrtmgr.dll")]
private static extern int RmEndSession(int pSessionHandle);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
private static extern int RmRegisterResources(int pSessionHandle, int nFiles, string[] rgsFilenames, int nApplications, RM_UNIQUE_PROCESS[] rgApplications, int nServices, string[] rgsServiceNames);
[DllImport("rstrtmgr.dll")]
private static extern int RmGetList(int dwSessionHandle, out int pnProcInfoNeeded, ref int pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, ref int lpdwRebootReasons);
[DllImport("rstrtmgr.dll")]
private static extern int RmShutdown(int dwSessionHandle, int lActionFlags, StatusHandler fnStatus);
[DllImport("rstrtmgr.dll")]
private static extern int RmRestart(int dwSessionHandle, int dwRestartFlags, StatusHandler fnStatus);
/// <summary>
/// Represents the method that handles status updates.
/// </summary>
/// <param name="percentComplete">The percentage completed.</param>
public delegate void StatusHandler(int percentComplete);
private const int RmRebootReasonNone = 0;
private const int RmForceShutdown = 1;
private const int RmShutdownOnlyRegistered = 0x10;
private const int ERROR_MORE_DATA = 234;
private const int ERROR_FAIL_NOACTION_REBOOT = 350;
private const int ERROR_FAIL_SHUTDOWN = 351;
private const int ERROR_SEM_TIMEOUT = 121;
private const int ERROR_CANCELLED = 1223;
private const int CCH_RM_MAX_APP_NAME = 255;
private const int CCH_RM_MAX_SVC_NAME = 63;
[StructLayout(LayoutKind.Sequential)]
private struct RM_UNIQUE_PROCESS
{
public int dwProcessId;
public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct RM_PROCESS_INFO
{
public RM_UNIQUE_PROCESS Process;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
public string strAppName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
public string strServiceShortName;
public RM_APP_TYPE ApplicationType;
public RM_APP_STATUS AppStatus;
public int TSSessionId;
[MarshalAs(UnmanagedType.Bool)]
public bool bRestartable;
}
[Flags]
private enum RM_APP_STATUS
{
RmStatusUnknown = 0x0,
RmStatusRunning = 0x1,
RmStatusStopped = 0x2,
RmStatusStoppedOther = 0x4,
RmStatusRestarted = 0x8,
RmStatusErrorOnStop = 0x10,
RmStatusErrorOnRestart = 0x20,
RmStatusShutdownMasked = 0x40,
RmStatusRestartMasked = 0x80
}
private enum RM_APP_TYPE
{
RmUnknownApp = 0,
RmMainWindow = 1,
RmOtherWindow = 2,
RmService = 3,
RmExplorer = 4,
RmConsole = 5,
RmCritical = 1000
}
}
Change your command to
cmd /c taskkill /f /im explorer.exe && start explorer.exe || start explorer.exe
and you will find that explorer.exe stops and restarts

Get lpbaseaddress of a suspended process

Hi i have a source that does the following.
int[] context = new int[179];
context[0] = 65538; //context integer
GetThreadContext(PI.hThread, context); //from kernel32
ReadProcessMemory(PI.hProcess, context[41]+ 8, ref BaseAddress, 4, ref ReadWrite)
After googling much, context[41] refers to EBX. Any idea why? PInvokes.net shows the following.
[StructLayout(LayoutKind.Sequential)]
public struct CONTEXT
{
public uint ContextFlags; //set this to an appropriate value
// Retrieved by CONTEXT_DEBUG_REGISTERS
public uint Dr0;
public uint Dr1;
public uint Dr2;
public uint Dr3;
public uint Dr6;
public uint Dr7;
// Retrieved by CONTEXT_FLOATING_POINT
public FLOATING_SAVE_AREA FloatSave;
// Retrieved by CONTEXT_SEGMENTS
public uint SegGs;
public uint SegFs;
public uint SegEs;
public uint SegDs;
// Retrieved by CONTEXT_INTEGER
public uint Edi;
public uint Esi;
public uint Ebx;
public uint Edx;
public uint Ecx;
public uint Eax;
// Retrieved by CONTEXT_CONTROL
public uint Ebp;
public uint Eip;
public uint SegCs;
public uint EFlags;
public uint Esp;
public uint SegSs;
// Retrieved by CONTEXT_EXTENDED_REGISTERS
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
public byte[] ExtendedRegisters;
}
Also why must we ebx+8 to get the lpbaseaddress?
The CONTEXT structure is defined in winnt.h. Beware that it has different definitions based on the processor architecture. Use this structure definition to access the ebx register instead of a specific offset to the start. The EBX register points to the process's PEB (Process Environment Block) where the Ldr pointer contains the base address. All of this is used for a technique called 'Dynamic Forking' to run a process in the context of another process. Used for example in malware applications.

Can we run jquery spellchecker by badsyntax using asp.net web services?

I have been researching for quite a while now for an appropriate spell checker for textbox and multiline textbox.
I can see that this functionality is built in for firefox but its not present in chrome.
I was checking out all the demos for spellcheck which is provided by
jquery spellchecker - badsyntax and i find it really nice and useful.
here is the link
http://jquery-spellchecker.badsyntax.co/
But my problem here is- spellchecker makes use of php webservices and i want to use it in my ASP.net Webapplication.
is there any work around so that i can run it using asp.net web services?
Please provide me with a solution.
I'm the author of the plugin and would really like to incorporate some other webservice implementations.
This popped up recently in my google alerts, I can't verify it works though:
http://www.yodotnet.com/post/2013/02/24/Jquery-Spellchecker-for-NET.aspx
https://github.com/AnthonyTerra/ASP.MVC-Jquery-Spellchecker
Hi Guys: Veerendra Prabhu, badsyntax; I've integrated Nhunspell and asp.net Web Service (.asmx) and currently I'm trying to integrate jquery spellchecker - badsyntax to the proyect, I'm jquery spellchecker now conects with my web services but Im still dealing whith the returned data type of my web service to allow jquery spellcheker does its magic, but I thinks its something.
I took ideas from:
deepinthecode.com
Here are some ideas that I used:
I used NHusnpell that helps to get the incorrect words within a passed text and look into the dictionary (open office downloaded as .oxt but you have to chante to zip to get en_US.aff, and en_US.dic) this files needs to be at bin directory.
At Glabal.asax file I created a static instance of NHuspell that does all the work.
public class Global : System.Web.HttpApplication
{
static SpellEngine spellEngine;
static public SpellEngine SpellEngine { get { return spellEngine; } }
protected void Application_Start(object sender, EventArgs e)
{
try
{
string dictionaryPath = Server.MapPath("Bin") + "\\";
Hunspell.NativeDllPath = dictionaryPath;
spellEngine = new SpellEngine();
LanguageConfig enConfig = new LanguageConfig();
enConfig.LanguageCode = "en";
enConfig.HunspellAffFile = dictionaryPath + "en_us.aff";
enConfig.HunspellDictFile = dictionaryPath + "en_us.dic";
enConfig.HunspellKey = "";
//enConfig.HyphenDictFile = dictionaryPath + "hyph_en_us.dic";
spellEngine.AddLanguage(enConfig);
}
catch (Exception ex)
{
if (spellEngine != null)
spellEngine.Dispose();
}
}
...
protected void Application_End(object sender, EventArgs e)
{
if (spellEngine != null)
spellEngine.Dispose();
spellEngine = null;
}
}
Then I created an ASMX web service for the Get_Incorrect_Words and Get_Suggestions methods
/// <summary>
/// Summary description for SpellCheckerService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class SpellCheckerService : System.Web.Services.WebService
{
[WebMethod]
//[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string get_incorrect_words(string words)
{
Dictionary<string, string> IncorrectWords = new Dictionary<string, string>();
List<string> wrongWords = new List<string>();
var palabras = words.Split(' ');
// Check spelling of each word that has been passed to the method
foreach (string word in palabras)
{
bool correct = Global.SpellEngine["en"].Spell(word);
if (!correct){
wrongWords.Add(word);
}
}
IncorrectWords.Add("data", wrongWords[0]);
return wrongWords[0];
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<string> get_suggestions(string word)
{
List<string> suggestions = new List<string>();
suggestions = Global.SpellEngine["en"].Suggest(word);
suggestions.Sort();
return suggestions;
}
And Finally I modified the calls to the get_incorrect_words and get_suggestions in jquery.Spellchecker.js
/* Config
*************************/
var defaultConfig = {
lang: 'en',
webservice: {
path: 'SpellCheckerService.asmx/get_incorrect_words'
//,driver: 'LabNET'
},
local: {
requestError: 'There was an error processing the request.',
ignoreWord: 'Ignore word',
ignoreAll: 'Ignore all',
ignoreForever: 'Add to dictionary',
loading: 'Loading...',
noSuggestions: '(No suggestions)'
},
suggestBox: {
numWords: 5,
position: 'above',
offset: 2,
appendTo: null
},
incorrectWords: {
container: 'body', //selector
position: null //function
}
};
var pluginName = 'spellchecker';
...
/* Spellchecker web service
*************************/
var WebService = function(config) {
this.config = config;
this.defaultConfig = {
url: config.webservice.path,
//contentType: "application/json; charset=utf-8",
type: 'POST',
dataType: 'text',
cache: false,
data: JSON.stringify({
lang: config.lang,
driver: config.webservice.driver
}, null,2) ,
error: function() {
alert(config.local.requestError);
}.bind(this)
};
};
WebService.prototype.makeRequest = function(config) {
var defaultConfig = $.extend(true, {}, this.defaultConfig);
return $.ajax($.extend(true, defaultConfig, config));
};
WebService.prototype.checkWords = function (text, callback) {
//action: 'get_incorrect_words',
//JSON.stringify({
// text: text
//}, null, 2)
return this.makeRequest(
{
data: { words: text },
success: callback
});
};
WebService.prototype.getSuggestions = function (word, callback) {
//action: 'get_suggestions',
return this.makeRequest({
data: JSON.stringify({
word: word
}, null, 2),
success: callback
});
};
I have found a solution for the issue and
below is the webservice which returns the JSON response for the jquery spell checker
This code is the modified verion of code found in
github.com/jackmyang/jQuery-Spell-Checker-for-ASP.NET
/// <summary>
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
< %# WebHandler Language="C#" Class="JQuerySpellCheckerHandler2" %>
/// <summary>
/// jQuery spell checker http handler class. Original server-side code was written by Richard Willis in PHP.
/// This is a version derived from the original design and implemented for ASP.NET platform.
///
/// It's very easy to use this handler with ASP.NET WebForm or MVC. Simply do the following steps:
/// 1. Include project jquery.spellchecker assembly in the website as a reference
/// 2. Include the httphandler node in the system.web node for local dev or IIS 6 or below
/// <example>
/// <![CDATA[
/// <system.web>
/// <httpHandlers>
/// <add verb="GET,HEAD,POST" type="jquery.spellchecker.JQuerySpellCheckerHandler" path="JQuerySpellCheckerHandler.ashx"/>
/// </httpHandlers>
/// </system.web>
/// ]]>
/// </example>
/// 3. If IIS7 is the target web server, also need to include the httphandler node in the system.webServer node
/// <example>
/// <![CDATA[
/// <system.webServer>
/// <handlers>
/// <add verb="GET,HEAD,POST" name="JQuerySpellCheckerHandler" type="jquery.spellchecker.JQuerySpellCheckerHandler" path="JQuerySpellCheckerHandler.ashx"/>
/// </handlers>
/// </system.webServer>
/// ]]>
/// </example>
/// 4. On the web page which included the spell checker, set the 'url' property to '~/JQuerySpellCheckerHandler.ashx'
/// <example>
/// <![CDATA[
/// $("#text-content")
/// .spellchecker({
/// url: "~/JQuerySpellCheckerHandler.ashx",
/// lang: "en",
/// engine: "google",
/// suggestBoxPosition: "above"
/// })
/// ]]>
/// </example>
/// </summary>
/// <remarks>
/// Manipulations of XmlNodeList is used for compatibility concern with lower version of .NET framework,
/// alternatively, they can be simplified using 'LINQ for XML' if .NET 3.5 or higher is available.
/// </remarks>
public class JQuerySpellCheckerHandler2 : IHttpHandler
{
#region fields
// in case google changes url, value of GoogleSpellCheckRpc can be stored in web.config instead to avoid code re-compilation
private const string GoogleSpellCheckRpc = "https://www.google.com/tbproxy/spell?";
private const string GoogleFlagTextAlreadClipped = "textalreadyclipped";
private const string GoogleFlagIgnoreDups = "ignoredups";
private const string GoogleFlagIgnoreDigits = "ignoredigits";
private const string GoogleFlagIgnoreAllCaps = "ignoreallcaps";
#endregion
#region properties
/// <summary>
/// Gets or sets a value indicating whether [ignore duplicated words].
/// </summary>
/// <value><c>true</c> if [ignore dups]; otherwise, <c>false</c>.</value>
private bool IgnoreDups { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [ignore digits].
/// </summary>
/// <value><c>true</c> if [ignore digits]; otherwise, <c>false</c>.</value>
private bool IgnoreDigits { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [ignore all capitals].
/// </summary>
/// <value><c>true</c> if [ignore all caps]; otherwise, <c>false</c>.</value>
private bool IgnoreAllCaps { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [text alread clipped].
/// </summary>
/// <value><c>true</c> if [text alread clipped]; otherwise, <c>false</c>.</value>
private bool TextAlreadClipped { get; set; }
#endregion
#region Implementation of IHttpHandler
/// <summary>
/// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface.
/// </summary>
/// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.
/// </param>
public void ProcessRequest(HttpContext context)
{
string engine = context.Request.Form[1];
string lang = context.Request.Form["lang"];
string text = context.Request.Form[3];
string suggest = context.Request.Form[2];
SetSwitches(context);
string result = SpellCheck(text, lang, engine, suggest);
context.Response.ContentType = "application/js";
string jsonStr = "{\"outcome\":\"success\",\"data\":[" + result + "]}";
if (suggest == "get_incorrect_words")
{
context.Response.Write(jsonStr);
}
else
{
context.Response.Write(result);
}
}
/// <summary>
/// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"/> instance.
/// </summary>
/// <returns>
/// true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false.
/// </returns>
public bool IsReusable
{
get { return false; }
}
#endregion
#region private methods
/// <summary>
/// Spells the check.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="lang">The lang.</param>
/// <param name="engine">The engine.</param>
/// <param name="suggest">The suggest.</param>
/// <returns></returns>
private string SpellCheck(string text, string lang, string engine, string suggest)
{
if (0 == string.Compare(suggest, "undefined", StringComparison.OrdinalIgnoreCase))
{
suggest = string.Empty;
}
if (0 != string.Compare(engine, "google", true))
{
throw new NotImplementedException("Only google spell check engine is support at this moment.");
}
string xml;
List<string> result;
if (string.IsNullOrEmpty(suggest) || suggest == "get_incorrect_words")
{
xml = GetSpellCheckRequest(text, lang);
result = GetListOfMisspelledWords(xml, text);
}
else
{
xml = GetSpellCheckRequest(text, lang);
result = GetListOfSuggestWords(xml, text);
}
return ConvertStringListToJavascriptArrayString(result);
}
/// <summary>
/// Sets the boolean switch.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="queryStringParameter">The query string parameter.</param>
/// <returns></returns>
private static bool SetBooleanSwitch(HttpContext context, string queryStringParameter)
{
byte tryParseZeroOne;
string queryStringValue = context.Request.QueryString[queryStringParameter];
if (!string.IsNullOrEmpty(queryStringValue) && byte.TryParse(queryStringValue, out tryParseZeroOne))
{
if (1 < tryParseZeroOne || 0 > tryParseZeroOne)
{
throw new InvalidOperationException(string.Format("Query string parameter '{0}' only supports values of 1 and 0.", queryStringParameter));
}
return tryParseZeroOne == 1;
}
return false;
}
/// <summary>
/// Gets the list of suggest words.
/// </summary>
/// <param name="xml">The source XML.</param>
/// <param name="suggest">The word to be suggested.</param>
/// <returns></returns>
private static List<string> GetListOfSuggestWords(string xml, string suggest)
{
if (string.IsNullOrEmpty(xml) || string.IsNullOrEmpty(suggest))
{
return null;
}
//
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(xml);
if (!xdoc.HasChildNodes)
{
return null;
}
XmlNodeList nodeList = xdoc.SelectNodes("//c");
if (null == nodeList || 0 >= nodeList.Count)
{
return null;
}
List<string> list = new List<string>();
foreach (XmlNode node in nodeList)
{
list.AddRange(node.InnerText.Split('\t'));
return list;
}
return list;
}
/// <summary>
/// Gets the list of misspelled words.
/// </summary>
/// <param name="xml">The source XML.</param>
/// <param name="text">The text.</param>
/// <returns></returns>
private static List<string> GetListOfMisspelledWords(string xml, string text)
{
if (string.IsNullOrEmpty(xml) || string.IsNullOrEmpty(text))
{
return null;
}
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(xml);
if (!xdoc.HasChildNodes)
{
return null;
}
XmlNodeList nodeList = xdoc.SelectNodes("//c");
if (null == nodeList || 0 >= nodeList.Count)
{
return null;
}
List<string> list = new List<string>();
foreach (XmlNode node in nodeList)
{
int offset = Convert.ToInt32(node.Attributes["o"].Value);
int length = Convert.ToInt32(node.Attributes["l"].Value);
list.Add(text.Substring(offset, length));
}
return list;
}
/// <summary>
/// Constructs the request URL.
/// </summary>
/// <param name="text">The text which may contain multiple words.</param>
/// <param name="lang">The language.</param>
/// <returns></returns>
private static string ConstructRequestUrl(string text, string lang)
{
if (string.IsNullOrEmpty(text))
{
return string.Empty;
}
lang = string.IsNullOrEmpty(lang) ? "en" : lang;
return string.Format("{0}lang={1}&text={2}", GoogleSpellCheckRpc, lang, text);
}
/// <summary>
/// Converts the C# string list to Javascript array string.
/// </summary>
/// <param name="list">The list.</param>
/// <returns></returns>
private static string ConvertStringListToJavascriptArrayString(ICollection<string> list)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("[");
if (null != list && 0 < list.Count)
{
bool showSeperator = false;
foreach (string word in list)
{
if (showSeperator)
{
stringBuilder.Append(",");
}
stringBuilder.AppendFormat("\"{0}\"", word);
showSeperator = true;
}
}
stringBuilder.Append("]");
return stringBuilder.ToString();
}
/// <summary>
/// Sets the switches.
/// </summary>
/// <param name="context">The context.</param>
private void SetSwitches(HttpContext context)
{
IgnoreAllCaps = SetBooleanSwitch(context, GoogleFlagIgnoreAllCaps);
IgnoreDigits = SetBooleanSwitch(context, GoogleFlagIgnoreDigits);
IgnoreDups = SetBooleanSwitch(context, GoogleFlagIgnoreDups);
TextAlreadClipped = SetBooleanSwitch(context, GoogleFlagTextAlreadClipped);
}
/// <summary>
/// Requests the spell check and get the result back.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="lang">The language.</param>
/// <returns></returns>
private string GetSpellCheckRequest(string text, string lang)
{
string requestUrl = ConstructRequestUrl(text, lang);
string requestContentXml = ConstructSpellRequestContentXml(text);
byte[] buffer = Encoding.UTF8.GetBytes(requestContentXml);
WebClient webClient = new WebClient();
webClient.Headers.Add("Content-Type", "text/xml");
try
{
byte[] response = webClient.UploadData(requestUrl, "POST", buffer);
return Encoding.UTF8.GetString(response);
}
catch (ArgumentException)
{
return string.Empty;
}
}
/// <summary>
/// Constructs the spell request content XML.
/// </summary>
/// <param name="text">The text which may contain multiple words.</param>
/// <returns></returns>
private string ConstructSpellRequestContentXml(string text)
{
XmlDocument doc = new XmlDocument(); // Create the XML Declaration, and append it to XML document
XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", null, null);
doc.AppendChild(declaration);
XmlElement root = doc.CreateElement("spellrequest");
root.SetAttribute(GoogleFlagTextAlreadClipped, TextAlreadClipped ? "1" : "0");
root.SetAttribute(GoogleFlagIgnoreDups, IgnoreDups ? "1" : "0");
root.SetAttribute(GoogleFlagIgnoreDigits, IgnoreDigits ? "1" : "0");
root.SetAttribute(GoogleFlagIgnoreAllCaps, IgnoreAllCaps ? "1" : "0");
doc.AppendChild(root);
XmlElement textElement = doc.CreateElement("text");
textElement.InnerText = text;
root.AppendChild(textElement);
return doc.InnerXml;
}
#endregion
}
Also you can use this javascript:
// Replace the Spellchecker.php path with Asp.net ashx path
spellchecker = new $.SpellChecker(body, {
lang: 'en',
parser: 'html',
webservice: {
path: "../Includes/JS/spellify/JQuerySpellCheckerHandler2.ashx",
driver: 'google'
},
suggestBox: {
position: 'below'
}
});
// Bind spellchecker handler functions
spellchecker.on('check.success', function() {
alert('There are no incorrectly spelt words.');
});
spellchecker.check();

NavigationService.GoBack() unauthorized expcetion

void CallBackVerifiedResponse(OAuthAccessToken at, TwitterResponse response)
{
if (at != null)
{
SerializeHelper.SaveSetting<TwitterAccess>("TwitterAccess", new TwitterAccess
{
AccessToken = at.Token,
AccessTokenSecret = at.TokenSecret,
ScreenName = at.ScreenName,
UserId = at.UserId.ToString()
});
}
}
private void ok_Click_1(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(pinText.Text))
MessageBox.Show("Please enter PIN");
else
{
try
{
var cb = new Action<OAuthAccessToken, TwitterResponse>(CallBackVerifiedResponse);
service.GetAccessToken(_requestToken, pinText.Text, CallBackVerifiedResponse);
}
catch
{
MessageBox.Show("Something is wrong with the PIN. Try again please.", "Error", MessageBoxButton.OK);
}
}
}
My problem in is here when I use NavigationService.GoBack() inside the CallBackVerifiedResponse method i'm getting unauthorized access exception, and if i use it inside of the click event, I CallBackVerifiedResponse is not triggered. Any ideas?
It's been solved by using UIThread
public static class UIThread
{
private static readonly Dispatcher Dispatcher;
static UIThread()
{
// Store a reference to the current Dispatcher once per application
Dispatcher = Deployment.Current.Dispatcher;
}
/// <summary>
/// Invokes the given action on the UI thread - if the current thread is the UI thread this will just invoke the action directly on
/// the current thread so it can be safely called without the calling method being aware of which thread it is on.
/// </summary>
public static void Invoke(Action action)
{
if (Dispatcher.CheckAccess())
action.Invoke();
else
Dispatcher.BeginInvoke(action);
}
}
After this static class
I have called it inside of
CallBackVerifiedResponse
like this
UIThread.Invoke(()=>NavigationService.GoBack());
You can use Dispatcher.BeginInvoke to access the UIThread
Dispatcher.BeginInvoke(() =>
{
NavigationService.GoBack();
});
Or you could use your own smart dispatcher, used like this:
SmartDispatcher.BeginInvoke(() =>
{
MissionAccomplished();
});
Coded something as the following:
{
using System.ComponentModel;
using System.Windows.Threading;
using System.Windows;
using System;
public static class SmartDispatcher
{
/// <summary>
/// A single Dispatcher instance to marshall actions to the user
/// interface thread.
/// </summary>
private static Dispatcher _instance;
/// <summary>
/// Backing field for a value indicating whether this is a design-time
/// environment.
/// </summary>
private static bool? _designer;
/// <summary>
/// Requires an instance and attempts to find a Dispatcher if one has
/// not yet been set.
/// </summary>
private static void RequireInstance()
{
if (_designer == null)
{
_designer = DesignerProperties.IsInDesignTool;
}
// Design-time is more of a no-op, won't be able to resolve the
// dispatcher if it isn't already set in these situations.
if (_designer == true)
{
return;
}
// Attempt to use the RootVisual of the plugin to retrieve a
// dispatcher instance. This call will only succeed if the current
// thread is the UI thread.
try
{
_instance = Application.Current.RootVisual.Dispatcher;
}
catch (Exception e)
{
throw new InvalidOperationException("The first time SmartDispatcher is used must be from a user interface thread. Consider having the application call Initialize, with or without an instance.", e);
}
if (_instance == null)
{
throw new InvalidOperationException("Unable to find a suitable Dispatcher instance.");
}
}
/// <summary>
/// Initializes the SmartDispatcher system, attempting to use the
/// RootVisual of the plugin to retrieve a Dispatcher instance.
/// </summary>
public static void Initialize()
{
if (_instance == null)
{
RequireInstance();
}
}
/// <summary>
/// Initializes the SmartDispatcher system with the dispatcher
/// instance.
/// </summary>
/// <param name="dispatcher">The dispatcher instance.</param>
public static void Initialize(Dispatcher dispatcher)
{
if (dispatcher == null)
{
throw new ArgumentNullException("dispatcher");
}
_instance = dispatcher;
if (_designer == null)
{
_designer = DesignerProperties.IsInDesignTool;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static bool CheckAccess()
{
if (_instance == null)
{
RequireInstance();
}
return _instance.CheckAccess();
}
/// <summary>
/// Executes the specified delegate asynchronously on the user interface
/// thread. If the current thread is the user interface thread, the
/// dispatcher if not used and the operation happens immediately.
/// </summary>
/// <param name="a">A delegate to a method that takes no arguments and
/// does not return a value, which is either pushed onto the Dispatcher
/// event queue or immediately run, depending on the current thread.</param>
public static void BeginInvoke(Action a)
{
if (_instance == null)
{
RequireInstance();
}
// If the current thread is the user interface thread, skip the
// dispatcher and directly invoke the Action.
if (_instance.CheckAccess() || _designer == true)
{
a();
}
else
{
_instance.BeginInvoke(a);
}
}
}
}

How to create a console window from a console window on Windows?

I have a console program that needs read the window messages, but since can not be subclassed a window that belongs to another process, how to create a new console window?
I have tried to use AllocConsole but it shows the error: "Access is denied"
From the MSDN documentation for AllocConsole:
A process can be associated with only one console, so the AllocConsole function fails if the calling process already has a console. A process can use the FreeConsole function to detach itself from its current console, then it can call AllocConsole to create a new console or AttachConsole to attach to another console.
So you need to call FreeConsole before calling AllocConsole.
I have developed this code for use in my projects. I hope here is all you need and more :)
/// <summary>
/// Smart Console powered by Gregor Primar s.p.
/// </summary>
public class ConsoleWindow
{
#region EXTERNALL DLL CALLS
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeConsole();
[DllImport("user32.dll")]
static extern IntPtr RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags);
[DllImport("user32.dll")]
static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
[DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName);
internal const UInt32 SC_CLOSE = 0xF060;
internal const UInt32 MF_GRAYED = 0x00000001;
internal const UInt32 MF_ENABLED = 0x00000000;
internal const uint MF_BYCOMMAND = 0x00000000;
#endregion
#region PROPERTIES
/// <summary>
/// Gets if console window is displayed
/// </summary>
public bool Displayed { get; internal set; }
/// <summary>
/// Gets or Sets console background color
/// </summary>
public ConsoleColor BackgroundColor
{
get
{
return Console.BackgroundColor;
}
set
{
Console.BackgroundColor = value;
}
}
/// <summary>
/// Gets or Sets console foreground color
/// </summary>
public ConsoleColor ForegroundColor
{
get
{
return Console.ForegroundColor;
}
set
{
Console.ForegroundColor = value;
}
}
/// <summary>
/// Gets or Sets
/// </summary>
public ConsoleColor ForegroundErrorColor { get; set; }
#endregion
#region WRITE AND READ METHODES
/// <summary>
/// Clears console window
/// </summary>
public void Clear()
{
Console.Clear();
}
/// <summary>
/// Writes to console with ForegroundColor
/// </summary>
/// <param name="value"></param>
public void Write(string value)
{
Write(value, false);
}
/// <summary>
/// Writes to console with ForegroundColor or ForegroundErrorColor
/// </summary>
/// <param name="value"></param>
/// <param name="isError"></param>
public void Write(string value, bool isError)
{
Write_internal(value, isError, false);
}
/// <summary>
/// Writes blank line to console with ForegroundColor
/// </summary>
public void WriteLine()
{
this.WriteLine("");
}
/// <summary>
/// Writes to console with ForegroundColor
/// </summary>
/// <param name="value"></param>
public void WriteLine(string value)
{
WriteLine(value, false);
}
/// <summary>
/// Writes line to console with ForegroundColor or ForegroundErrorColor
/// </summary>
/// <param name="value"></param>
/// <param name="isError"></param>
public void WriteLine(string value, bool isError)
{
Write_internal(value, isError, true);
}
void Write_internal(string value, bool isError, bool fullLine)
{
ConsoleColor defaultColor = this.ForegroundColor;
if (isError)
{
this.ForegroundColor = this.ForegroundErrorColor;
}
if (fullLine)
{
Console.WriteLine(value);
}
else
{
Console.Write(value);
}
this.ForegroundColor = defaultColor;
}
void ReadLine_internal(Type type, bool allowNull, ref object returnValue, StringDictionary options)
{
if ((options != null) && (type != typeof(string)))
{
throw new Exception("ReadLine_internal allows options only when type is string!");
}
string currentValue = null;
string errorMessage = null;
do
{
currentValue = Console.ReadLine();
if (allowNull && currentValue == "")
{
returnValue = null;
break;
}
//probaj za točno določen tip...
bool typeResolved = false;
if (type == typeof(string))
{
typeResolved = true;
if (currentValue != "")
{
if (options != null)
{
foreach (DictionaryEntry option in options)
{
if (option.Key.ToString() == currentValue)
{
returnValue = currentValue;
return;
}
}
errorMessage = "Enter one of possible options!";
}
else
{
returnValue = currentValue;
return;
}
}
else
{
errorMessage = "String value is required!";
}
}
if (type == typeof(int?))
{
typeResolved = true;
int iVal = 0;
if (int.TryParse(currentValue, out iVal))
{
returnValue = iVal;
return;
}
errorMessage = "Int value is required!";
}
if (type == typeof(decimal?))
{
typeResolved = true;
decimal dVal = 0;
if (decimal.TryParse(currentValue, out dVal))
{
returnValue = dVal;
return;
}
errorMessage = "Decimal value is required!";
}
if (type == typeof(DateTime?))
{
typeResolved = true;
DateTime dtVal = new DateTime();
if (DateTime.TryParse(currentValue, out dtVal))
{
returnValue = dtVal;
return;
}
errorMessage = "DateTime value is required!";
}
if (typeResolved == false)
{
throw new Exception("Type='" + type.ToString() + "' not supported in ReadLine_internal void!");
}
this.WriteLine(errorMessage, true);
} while (1 == 1);
}
/// <summary>
/// Reads line from user input and returns string
/// </summary>
/// <returns></returns>
public string ReadLine()
{
return this.ReadLine(true);
}
/// <summary>
/// Reads line from user input and returns string
/// </summary>
/// <returns></returns>
public string ReadLine(bool allowNull)
{
object returnValue = null;
ReadLine_internal(typeof(string), allowNull, ref returnValue, null);
if (returnValue != null)
{
return returnValue.ToString();
}
else
{
return null;
}
}
/// <summary>
/// Reads line from user input and returns nullable integer
/// </summary>
/// <param name="allowNull"></param>
/// <returns></returns>
public int? ReadLineAsInt(bool allowNull)
{
object returnValue = null;
ReadLine_internal(typeof(int?), allowNull, ref returnValue, null);
return (int?)returnValue;
}
/// <summary>
/// Reads line from user input and returns nullable decimal
/// </summary>
/// <param name="allowNull"></param>
/// <returns></returns>
public decimal? ReadLineAsDecimal(bool allowNull)
{
object returnValue = null;
ReadLine_internal(typeof(decimal?), allowNull, ref returnValue, null);
return (decimal?)returnValue;
}
/// <summary>
/// Reads line from user input and returns nullable datetime
/// </summary>
/// <param name="allowNull"></param>
/// <returns></returns>
public DateTime? ReadLineDateTime(bool allowNull)
{
object returnValue = null;
ReadLine_internal(typeof(DateTime?), allowNull, ref returnValue, null);
return (DateTime?)returnValue;
}
/// <summary>
/// Reads line from user input and returns string from options list
/// </summary>
/// <param name="options"></param>
/// <param name="allowNull"></param>
/// <returns></returns>
public string ReadLineAsOption(StringDictionary options, bool allowNull)
{
if (options != null)
{
if (options.Count == 0)
{
throw new Exception("Options list can not be empty! You can pass only null or unempty options list!");
}
else
{
this.WriteLine("Enter one of following options:");
foreach (DictionaryEntry de in options)
{
string description = null;
if (de.Value != null)
{
description = de.Value.ToString();
}
string userLine = "[" + de.Key.ToString() + "]";
if (description != null)
{
userLine += " " + description;
}
this.WriteLine(userLine);
}
}
}
object returnValue = null;
ReadLine_internal(typeof(string), allowNull, ref returnValue, options);
if (returnValue != null)
{
return returnValue.ToString();
}
else
{
return null;
}
}
#endregion
const string consoleTitle = "Smart Console powered by Gregor Primar s.p.";
/// <summary>
/// Default constructor
/// </summary>
public ConsoleWindow()
{
}
/// <summary>
/// Set focus to console window
/// </summary>
public void SetFocus()
{
if (this.Displayed)
{
SetConsoleFocus();
}
else
{
throw new Exception("Unable to SetFocus because console is not displayed!");
}
}
/// <summary>
/// Opens console window
/// </summary>
public void Open()
{
if (this.Displayed == false)
{
AllocConsole();
Console.Title = consoleTitle;
//onemogoči zapiranje konzole...
ChangeConsoleMenu(false);
this.Displayed = true;
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
//nastavi default barve...
this.BackgroundColor = ConsoleColor.DarkBlue;
this.ForegroundColor = ConsoleColor.White;
this.ForegroundErrorColor = ConsoleColor.Red;
this.Clear();
this.SetFocus();
}
else
{
throw new Exception("Console window is allready opened!");
}
}
void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
}
/// <summary>
/// Closes console window
/// </summary>
public void Close()
{
if (this.Displayed)
{
Console.CancelKeyPress -= Console_CancelKeyPress;
ChangeConsoleMenu(true);
FreeConsole();
this.Displayed = false;
}
else
{
throw new Exception("Can not close console window because its not displayed!");
}
}
void ChangeConsoleMenu(bool enabled)
{
IntPtr hConsole = FindConsoleHandle();
IntPtr hMenu = FindMenuHandle(hConsole);
uint value = MF_ENABLED;
if (enabled == false)
{
value = MF_GRAYED;
}
EnableMenuItem(hMenu, SC_CLOSE, value);
}
void SetConsoleFocus()
{
IntPtr hConsole = FindConsoleHandle();
while (true)
{
if (SetForegroundWindow(hConsole))
{
break;
}
Thread.Sleep(50);
}
}
/// <summary>
/// Finds handle to console window
/// </summary>
/// <returns></returns>
IntPtr FindConsoleHandle()
{
string originalTitle = Console.Title;
string uniqueTitle = Guid.NewGuid().ToString();
Console.Title = uniqueTitle;
Thread.Sleep(50);
IntPtr handle = FindWindowByCaption(IntPtr.Zero, uniqueTitle);
if (handle == IntPtr.Zero)
{
Console.Title = originalTitle;
throw new Exception("Unable to find console window!");
}
Console.Title = originalTitle;
return handle;
}
/// <summary>
/// Finds handle to main menu
/// </summary>
/// <param name="windowHandle"></param>
/// <returns></returns>
IntPtr FindMenuHandle(IntPtr windowHandle)
{
IntPtr hSystemMenu = GetSystemMenu(windowHandle, false);
return hSystemMenu;
}
}
And sample code how to use this class:
ConsoleWindow cw = new ConsoleWindow();
cw.Open();
cw.WriteLine("Some text displayed on smart console", true);

Resources