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
Related
I am using Windows 10 & Visual Studio 2015 for development and targeting Android, iOS, Windows Phone, Windows Universal.
I wanted to use XLabs SecureStorage Service.
I am using XLabs.Platform package 2.3.0-pre02.
at this line i am getting exception (only for UWP)
secureStorage.Store(key, Encoding.UTF8.GetBytes(value));
And Exception Details are :
FileName : System.Runtime.WindowsRuntime, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
HResult : -2146234304
HelpLink : null
InnerException : null
Message : Could not load file or assembly 'System.Runtime.WindowsRuntime, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Source : XLabs.Platform.UWP
SourceTrack : at XLabs.Platform.Services.SecureStorage.d__6.MoveNext()
at System.Runtime.CompilerServices.AsyncVoidMethodBuilder.StartTStateMachine
at XLabs.Platform.Services.SecureStorage.Store(String key, Byte[] dataBytes)
at UWPTest.SecureStorageService.Store(String key, String value, Boolean overwrite)
After some trial and error i am able to run SecureStorage service successfully on Xamarin UWP.
SecureStorage.cs(Code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ABC.UWP.Common
{
using System;
using System.IO;
using Windows.Storage;
using System.Threading;
using System.Runtime.InteropServices.WindowsRuntime;
using XLabs.Platform.Services;
using Windows.Security.Cryptography.DataProtection;
/// <summary>
/// Implements <see cref="ISecureStorage"/> for WP using <see cref="IsolatedStorageFile"/> and <see cref="ProtectedData"/>.
/// </summary>
public class SecureStorage : ISecureStorage
{
private static Windows.Storage.ApplicationData AppStorage { get { return ApplicationData.Current; } }
private static Windows.Security.Cryptography.DataProtection.DataProtectionProvider _dataProtectionProvider = new DataProtectionProvider();
private readonly byte[] _optionalEntropy;
/// <summary>
/// Initializes a new instance of <see cref="SecureStorage"/>.
/// </summary>
/// <param name="optionalEntropy">Optional password for additional entropy to make encyption more complex.</param>
public SecureStorage(byte[] optionalEntropy)
{
this._optionalEntropy = optionalEntropy;
}
/// <summary>
/// Initializes a new instance of <see cref="SecureStorage"/>.
/// </summary>
public SecureStorage() : this(null)
{
}
#region ISecureStorage Members
/// <summary>
/// Stores the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="dataBytes">The data bytes.</param>
public async void Store(string key, byte[] dataBytes)
{
//var mutex = new Mutex(false, key);
using (var mutex = new Mutex(false, key))
{
try
{
mutex.WaitOne();
var buffer = dataBytes.AsBuffer();
if (_optionalEntropy != null)
{
buffer = await _dataProtectionProvider.ProtectAsync(buffer);
}
var file = await AppStorage.LocalFolder.CreateFileAsync(key, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBufferAsync(file, buffer);
}
catch (Exception ex)
{
throw new Exception(string.Format("No entry found for key {0}.", key), ex);
}
}
//finally
//{
// mutex.ReleaseMutex();
//}
}
/// <summary>
/// Retrieves the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns>System.Byte[].</returns>
/// <exception cref="System.Exception"></exception>
public byte[] Retrieve(string key)
{
var mutex = new Mutex(false, key);
try
{
mutex.WaitOne();
return Task.Run(async () =>
{
var file = await AppStorage.LocalFolder.GetFileAsync(key);
var buffer = await FileIO.ReadBufferAsync(file);
if (_optionalEntropy != null)
{
buffer = _dataProtectionProvider.UnprotectAsync(buffer).GetResults();
}
return buffer.ToArray();
}).Result;
}
catch (Exception ex)
{
throw new Exception(string.Format("No entry found for key {0}.", key), ex);
}
finally
{
mutex.ReleaseMutex();
}
}
/// <summary>
/// Deletes the specified key.
/// </summary>
/// <param name="key">The key.</param>
public void Delete(string key)
{
var mutex = new Mutex(false, key);
try
{
mutex.WaitOne();
Task.Run(async () =>
{
var file = await AppStorage.LocalFolder.GetFileAsync(key);
await file.DeleteAsync();
});
}
finally
{
mutex.ReleaseMutex();
}
}
/// <summary>
/// Checks if the storage contains a key.
/// </summary>
/// <param name="key">The key to search.</param>
/// <returns>True if the storage has the key, otherwise false. </returns>
public bool Contains(string key)
{
try
{
return Task.Run(async() => await AppStorage.LocalFolder.GetFileAsync(key)).Result.IsAvailable;
}
catch
{
return false;
}
}
#endregion
}
}
In latest version of Facebook C# SDk 6.4. Can we use FacebookSubscriptionVerify Action Method Attribute ? As this is not available in the FacebookClient Class
I was using the older version of Facebok C# SDK in my MVC3 project. Now, After switching to Facebook C# SDK 6.4 this class is not available.
Do we have any substitute for this?
I took a little more time this morning and confirmed that the attribute that you referenced was removed in version 6 (along with tons of other items). Since this project is open source, here is the code for the FacebookSubscriptionVerify ActionFilter that you used to use. For any references to functions within here that I did not include, this version on CodePlex has all of the code available for you to look at: http://facebooksdk.codeplex.com/SourceControl/changeset/view/08cb51f372b5#Source/Facebook.Web/FacebookSubscriptionsHttpHandler.cs
The new version (version 6.X) and the last few branches of version 5 can be found on the GitHub site - https://github.com/facebook-csharp-sdk/facebook-csharp-sdk/tree/master/Source
With the availability of the source code, you should be able to, in tandem with how you were using this function, create your own ActionFilterAttribute that can replicate the functionality that you had previously.
// --------------------------------
// <copyright file="FacebookSubscriptionVerifyAttribute.cs" company="Thuzi LLC (www.thuzi.com)">
// Microsoft Public License (Ms-PL)
// </copyright>
// <author>Nathan Totten (ntotten.com), Jim Zimmerman (jimzimmerman.com) and Prabir Shrestha (prabir.me)</author>
// <license>Released under the terms of the Microsoft Public License (Ms-PL)</license>
// <website>http://facebooksdk.codeplex.com</website>
// ---------------------------------
namespace Facebook.Web.Mvc
{
using System.Web.Mvc;
public class FacebookSubscriptionVerifyAttribute : ActionFilterAttribute
{
public string VerificationToken { get; set; }
public FacebookSubscriptionVerifyAttribute(string verificationToken)
{
VerificationToken = verificationToken;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.ContentType = "text/plain";
var request = filterContext.HttpContext.Request;
var modelState = filterContext.Controller.ViewData.ModelState;
string errorMessage;
if (request.HttpMethod == "GET")
{
if (string.IsNullOrEmpty(VerificationToken))
{
errorMessage = "Verification Token is empty.";
}
else
{
if (FacebookSubscriptionVerifier.VerifyGetSubscription(request, VerificationToken, out errorMessage))
{
return;
}
}
}
else
{
errorMessage = "Invalid http method.";
}
modelState.AddModelError("facebook-subscription", errorMessage);
filterContext.HttpContext.Response.StatusCode = 401;
}
}
}
And the code for the FacebookSubscriptionVerifier Class
namespace Facebook.Web
{
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web;
/// <summary>
/// Facebook helper methods for web.
/// </summary>
internal static class FacebookSubscriptionVerifier
{
internal const string HTTP_X_HUB_SIGNATURE_KEY = "HTTP_X_HUB_SIGNATURE";
internal static byte[] ComputeHmacSha1Hash(byte[] data, byte[] key)
{
Contract.Requires(data != null);
Contract.Requires(key != null);
Contract.Ensures(Contract.Result<byte[]>() != null);
using (var crypto = new System.Security.Cryptography.HMACSHA1(key))
{
return crypto.ComputeHash(data);
}
}
/// <summary>
/// Verify HTTP_X_HUB_SIGNATURE.
/// </summary>
/// <param name="secret">
/// The secret.
/// </param>
/// <param name="httpXHubSignature">
/// The http x hub signature.
/// </param>
/// <param name="jsonString">
/// The json string.
/// </param>
/// <returns>
/// Returns true if validation is successful.
/// </returns>
internal static bool VerifyHttpXHubSignature(string secret, string httpXHubSignature, string jsonString)
{
Contract.Requires(!string.IsNullOrEmpty(secret));
if (!string.IsNullOrEmpty(httpXHubSignature) && httpXHubSignature.StartsWith("sha1=") && httpXHubSignature.Length > 5 && !string.IsNullOrEmpty(jsonString))
{
// todo: test inner parts
var expectedSignature = httpXHubSignature.Substring(5);
var sha1 = ComputeHmacSha1Hash(Encoding.UTF8.GetBytes(jsonString), Encoding.UTF8.GetBytes(secret));
var hashString = new StringBuilder();
foreach (var b in sha1)
{
hashString.Append(b.ToString("x2"));
}
if (expectedSignature == hashString.ToString())
{
return true;
}
}
return false;
}
/// <summary>
/// Verify HTTP_X_HUB_SIGNATURE for http GET method.
/// </summary>
/// <param name="request">
/// The http request.
/// </param>
/// <param name="verifyToken">
/// The verify token.
/// </param>
/// <param name="errorMessage">
/// The error message.
/// </param>
/// <returns>
/// Returns true if successful otherwise false.
/// </returns>
internal static bool VerifyGetSubscription(HttpRequestBase request, string verifyToken, out string errorMessage)
{
Contract.Requires(request != null);
Contract.Requires(request.HttpMethod == "GET");
Contract.Requires(request.Params != null);
Contract.Requires(!string.IsNullOrEmpty(verifyToken));
errorMessage = null;
if (request.Params["hub.mode"] == "subscribe")
{
if (request.Params["hub.verify_token"] == verifyToken)
{
if (string.IsNullOrEmpty(request.Params["hub.challenge"]))
{
errorMessage = Properties.Resources.InvalidHubChallenge;
}
else
{
return true;
}
}
else
{
errorMessage = Properties.Resources.InvalidVerifyToken;
}
}
else
{
errorMessage = Properties.Resources.InvalidHubMode;
}
return false;
}
/// <summary>
/// Verify HTTP_X_HUB_SIGNATURE for http POST method.
/// </summary>
/// <param name="request">
/// The request.
/// </param>
/// <param name="secret">
/// The secret.
/// </param>
/// <param name="jsonString">
/// The json string.
/// </param>
/// <param name="errorMessage">
/// The error message.
/// </param>
/// <returns>
/// Returns true if successful otherwise false.
/// </returns>
internal static bool VerifyPostSubscription(HttpRequestBase request, string secret, string jsonString, out string errorMessage)
{
Contract.Requires(request != null);
Contract.Requires(request.HttpMethod == "POST");
Contract.Requires(request.Params != null);
Contract.Requires(!string.IsNullOrEmpty(secret));
errorMessage = null;
// signatures looks somewhat like "sha1=4594ae916543cece9de48e3289a5ab568f514b6a"
var signature = request.Params["HTTP_X_HUB_SIGNATURE"];
if (!string.IsNullOrEmpty(signature) && signature.StartsWith("sha1="))
{
var expectedSha1 = signature.Substring(5);
if (string.IsNullOrEmpty(expectedSha1))
{
errorMessage = Properties.Resources.InvalidHttpXHubSignature;
}
else
{
if (string.IsNullOrEmpty(jsonString))
{
errorMessage = Properties.Resources.InvalidJsonString;
return false;
}
var sha1 = ComputeHmacSha1Hash(Encoding.UTF8.GetBytes(jsonString), Encoding.UTF8.GetBytes(secret));
var hashString = new StringBuilder();
foreach (var b in sha1)
{
hashString.Append(b.ToString("x2"));
}
if (expectedSha1 == hashString.ToString())
{
// todo: test
return true;
}
// todo: test
errorMessage = Properties.Resources.InvalidHttpXHubSignature;
}
}
else
{
errorMessage = Properties.Resources.InvalidHttpXHubSignature;
}
return false;
}
}
}
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();
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);
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Find IMEI no in wp7?
Is there any api that gets the device IMEI number in windows phone 7, all i can get it "device unique id" by using DeviceExtendedProperties.GetValue("DeviceUniqueId"), but i need to get IMEI.
cc:http://www.cnblogs.com/xjb/archive/2007/02/05/640360.html
the following code is not tested by me.
public struct GeneralInfo
{
public string Manufacturer;
public string Model;
public string Revision;
public string SerialNumber;
public string SubscriberNumber;
}
/// <summary>
/// Tapi control class
/// </summary>
public class ControlTapi
{
[DllImport("cellcore.dll")]
private static extern int lineGetGeneralInfo(IntPtr hLigne,byte[]lpLineGeneralInfo );
/// <summary>
/// Invoke cellcore.dll to get info of sim
/// </summary>
/// <param name="l"></param>
/// <returns></returns>
private GeneralInfo GetGeneralInfo(Line l)
{
GeneralInfo lgi = new GeneralInfo();
byte[] buffer = new byte[512];
BitConverter.GetBytes(512).CopyTo(buffer, 0);
if (lineGetGeneralInfo(l.hLine, buffer) != 0)
{
throw new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error(), "TAPI Error: " + System.Runtime.InteropServices.Marshal.GetLastWin32Error().ToString("X"));
}
int subscsize = BitConverter.ToInt32(buffer, 44);
int subscoffset = BitConverter.ToInt32(buffer, 48);
lgi.SubscriberNumber = System.Text.Encoding.Unicode.GetString(buffer, subscoffset, subscsize).ToString();
lgi.SubscriberNumber = lgi.SubscriberNumber.Replace("\0", "");
return lgi;
}
/// <summary>
/// GET IMSI of SIM Card
/// </summary>
/// <returns></returns>
public static string GetIMSINumber()
{
string result = "";
try
{
Tapi t = new Tapi();
t.Initialize();
Line l = t.CreateLine(0, LINEMEDIAMODE.INTERACTIVEVOICE, OpenNETCF.Tapi.LINECALLPRIVILEGE.MONITOR);
ControlTapi ctapi = new ControlTapi();
GeneralInfo gi = ctapi.GetGeneralInfo(l);
result = gi.SubscriberNumber;
l.Dispose();
t.Shutdown();
}
catch// (Exception ex)
{
result = "";
}
return result;
}
/// <summary>
/// Get IMEI
/// </summary>
/// <returns></returns>
public static string GetIMEINumber()
{
string result = "";
try
{
Tapi t = new Tapi();
t.Initialize();
Line l = t.CreateLine(0, LINEMEDIAMODE.INTERACTIVEVOICE, OpenNETCF.Tapi.LINECALLPRIVILEGE.MONITOR);
ControlTapi ctapi = new ControlTapi();
GeneralInfo gi = ctapi.GetGeneralInfo(l);
result = gi.SerialNumber;
l.Dispose();
t.Shutdown();
}
catch// (Exception ex)
{
result = "";
}
return result;
}
}