Changing color of console after hiding and showing again - c#

With the code, what I found on this thread
no-output-to-console-from-a-wpf-application
i can show and hide the console as expected with the "Toggle()" function.
The first time when I do it, setting the "Console.BackgroundColor" and "Console.ForegroundColor" is working.
After hiding and showing again, the Console output with "Console.WriteLine" is working, but setting the color have no effect anymore.
What I also notices, that the function "GetConsoleWindow()" returns every time a new IntPtr, maybe this helps.
I hope you understand my problem and can help me.
Many Thanks,
bfrey
[SuppressUnmanagedCodeSecurity]
public static class ConsoleManager
{
private const string Kernel32DllName = "kernel32.dll";
[DllImport(Kernel32DllName)]
private static extern bool AllocConsole();
[DllImport(Kernel32DllName)]
private static extern bool AttachConsole();
[DllImport(Kernel32DllName)]
private static extern bool FreeConsole();
[DllImport(Kernel32DllName)]
public static extern IntPtr GetConsoleWindow();
public static bool HasConsole
{
get { return GetConsoleWindow() != IntPtr.Zero; }
}
/// <summary>
/// Creates a new console instance if the process is not attached to a console already.
/// </summary>
public static void Show()
{
//#if DEBUG
if (!HasConsole)
{
AllocConsole();
InvalidateOutAndError();
}
//#endif
}
/// <summary>
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
/// </summary>
public static void Hide()
{
//#if DEBUG
if (HasConsole)
{
SetOutAndErrorNull();
FreeConsole();
}
//#endif
}
public static void Toggle()
{
if (HasConsole)
{
Hide();
}
else
{
Show();
}
}
static void InvalidateOutAndError()
{
Type lType = typeof(Console);
System.Reflection.FieldInfo lOut = lType.GetField("_out",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
System.Reflection.FieldInfo lError = lType.GetField("_error",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
System.Reflection.MethodInfo lInitializeStdOutError = lType.GetMethod("InitializeStdOutError",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
Debug.Assert(lOut != null);
Debug.Assert(lError != null);
Debug.Assert(lInitializeStdOutError != null);
lOut.SetValue(null, null);
lError.SetValue(null, null);
lInitializeStdOutError.Invoke(null, new object[] {true});
}
static void SetOutAndErrorNull()
{
Console.SetOut(TextWriter.Null);
Console.SetError(TextWriter.Null);
}
}

Related

Out of memory when reading a gif file in wpf (C#)

I wrote a control read gif file using c# as follows:
public class AnimatedGIFControl : System.Windows.Controls.Image
{
public static readonly DependencyProperty IsPlayProperty = DependencyProperty.Register("IsPlay", typeof(bool), typeof(AnimatedGIFControl), new UIPropertyMetadata(false, new PropertyChangedCallback(OnIsPlayChanged)));
public bool IsPlay
{
get
{
return (bool)this.GetValue(IsPlayProperty);
}
set
{
this.SetValue(IsPlayProperty, value);
}
}
private static void OnIsPlayChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if((bool)e.NewValue)
{
(d as AnimatedGIFControl).StartAnimate();
}
else
{
(d as AnimatedGIFControl).StopAnimate();
}
}
public static readonly DependencyProperty GifSourceProperty = DependencyProperty.Register("GifSource", typeof(string), typeof(AnimatedGIFControl), new UIPropertyMetadata(null, new PropertyChangedCallback(OnGifSourceChanged)));
public string GifSource
{
get
{
return (string)this.GetValue(GifSourceProperty);
}
set
{
this.SetValue(GifSourceProperty, value);
}
}
private static void OnGifSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as AnimatedGIFControl).AnimatedGIFControl_Loaded();
}
private Bitmap _bitmap; // Local bitmap member to cache image resource
public delegate void FrameUpdatedEventHandler();
/// <summary>
/// Delete local bitmap resource
/// Reference: http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx
/// </summary>
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool DeleteObject(IntPtr hObject);
/// <summary>
/// Override the OnInitialized method
/// </summary>
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
this.Unloaded += new RoutedEventHandler(AnimatedGIFControl_Unloaded);
}
/// <summary>
/// Load the embedded image for the Image.Source
/// </summary>
public void AnimatedGIFControl_Loaded()
{
_bitmap = new Bitmap(Application.GetResourceStream(new Uri(#"pack://application:,,,/" + this.GifSource)).Stream);
Source = GetBitmapSource(_bitmap);
if (this.IsPlay && _bitmap.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Gif))
{
StartAnimate();
}
}
/// <summary>
/// Close the FileStream to unlock the GIF file
/// </summary>
private void AnimatedGIFControl_Unloaded(object sender, RoutedEventArgs e)
{
StopAnimate();
}
/// <summary>
/// Start animation
/// </summary>
public void StartAnimate()
{
ImageAnimator.Animate(_bitmap, OnFrameChanged);
}
/// <summary>
/// Stop animation
/// </summary>
public void StopAnimate()
{
ImageAnimator.StopAnimate(_bitmap, OnFrameChanged);
}
/// <summary>
/// Event handler for the frame changed
/// </summary>
private void OnFrameChanged(object sender, EventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle,
new FrameUpdatedEventHandler(FrameUpdatedCallback));
}
private void FrameUpdatedCallback()
{
ImageAnimator.UpdateFrames();
if (Source != null && Source.CanFreeze)
{
Source.Freeze();
}
// Convert the bitmap to BitmapSource that can be display in WPF Visual Tree
Source = GetBitmapSource(_bitmap);
InvalidateVisual();
}
private BitmapSource GetBitmapSource(Bitmap bitmap)
{
IntPtr handle = IntPtr.Zero;
BitmapSource bitmapSource = null;
try
{
handle = bitmap.GetHbitmap();
bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
finally
{
if (handle != IntPtr.Zero)
{
DeleteObject(handle);
}
}
return bitmapSource;
}
}
I use it in wpf as follows:
<customControl:AnimatedGIFControl x:Name="faultImage" HorizontalAlignment="Center" VerticalAlignment="Center"
IsPlay="True"
GifSource="Images/RouteWindow/BigFaultReportImage.gif"/>
I let applications run 24 hours, rising on a 1GB memory.
If it was because I forgot to clean up the memory or not?
I don't know why. Please, help me!
I think the problem is that you create a bitmap every frame update and you never call garbage collector. Did you tried to call GC.Collect(); after InvalidateVisual(); ?

C#: comctl32.dll version 6 in debugger

I'm using the WindowsAPICodePack for TaskDialog. When I try to show the dialog it says that it needs to load version 6 of comctl32.dll. So I added version 6 to the app.manifest and tried running it. Still no luck. I went to the Debug folder and ran the program without Visual Studio and it works fine. I'm guessing that Visual Studio isn't using the manifest file... I was wondering if there was a way to make it do this.
Robpol86, your code is throwing SEHExceptions, because the signatures for ActivateActCtx and DeactivateActCtx are not correct. You have to use UIntPtr instead of uint for the lpCookie.
Therefore, the correct code for EnableThemingInScope.cs would be:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows.Forms;
namespace Microsoft.WindowsAPICodePack.Dialogs
{
/// http://support.microsoft.com/kb/830033
/// <devdoc>
/// This class is intended to use with the C# 'using' statement in
/// to activate an activation context for turning on visual theming at
/// the beginning of a scope, and have it automatically deactivated
/// when the scope is exited.
/// </devdoc>
[SuppressUnmanagedCodeSecurity]
internal class EnableThemingInScope : IDisposable
{
// Private data
private UIntPtr cookie;
private static ACTCTX enableThemingActivationContext;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
private static IntPtr hActCtx;
private static bool contextCreationSucceeded = false;
public EnableThemingInScope(bool enable)
{
cookie = UIntPtr.Zero;
if (enable && OSFeature.Feature.IsPresent(OSFeature.Themes))
{
if (EnsureActivateContextCreated())
{
if (!ActivateActCtx(hActCtx, out cookie))
{
// Be sure cookie always zero if activation failed
cookie = UIntPtr.Zero;
}
}
}
}
~EnableThemingInScope()
{
Dispose();
}
void IDisposable.Dispose()
{
Dispose();
GC.SuppressFinalize(this);
}
private void Dispose()
{
if (cookie != UIntPtr.Zero)
{
try
{
if (DeactivateActCtx(0, cookie))
{
// deactivation succeeded...
cookie = UIntPtr.Zero;
}
}
catch (SEHException)
{
//Hopefully solved this exception
}
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity")]
private static bool EnsureActivateContextCreated()
{
lock (typeof(EnableThemingInScope))
{
if (!contextCreationSucceeded)
{
// Pull manifest from the .NET Framework install
// directory
string assemblyLoc = null;
FileIOPermission fiop = new FileIOPermission(PermissionState.None);
fiop.AllFiles = FileIOPermissionAccess.PathDiscovery;
fiop.Assert();
try
{
assemblyLoc = typeof(Object).Assembly.Location;
}
finally
{
CodeAccessPermission.RevertAssert();
}
string manifestLoc = null;
string installDir = null;
if (assemblyLoc != null)
{
installDir = Path.GetDirectoryName(assemblyLoc);
const string manifestName = "XPThemes.manifest";
manifestLoc = Path.Combine(installDir, manifestName);
}
if (manifestLoc != null && installDir != null)
{
enableThemingActivationContext = new ACTCTX();
enableThemingActivationContext.cbSize = Marshal.SizeOf(typeof(ACTCTX));
enableThemingActivationContext.lpSource = manifestLoc;
// Set the lpAssemblyDirectory to the install
// directory to prevent Win32 Side by Side from
// looking for comctl32 in the application
// directory, which could cause a bogus dll to be
// placed there and open a security hole.
enableThemingActivationContext.lpAssemblyDirectory = installDir;
enableThemingActivationContext.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
// Note this will fail gracefully if file specified
// by manifestLoc doesn't exist.
hActCtx = CreateActCtx(ref enableThemingActivationContext);
contextCreationSucceeded = (hActCtx != new IntPtr(-1));
}
}
// If we return false, we'll try again on the next call into
// EnsureActivateContextCreated(), which is fine.
return contextCreationSucceeded;
}
}
// All the pinvoke goo...
[DllImport("Kernel32.dll")]
private extern static IntPtr CreateActCtx(ref ACTCTX actctx);
[DllImport("Kernel32.dll")]
private extern static bool ActivateActCtx(IntPtr hActCtx, out UIntPtr lpCookie);
[DllImport("Kernel32.dll")]
private extern static bool DeactivateActCtx(uint dwFlags, UIntPtr lpCookie);
private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004;
private struct ACTCTX
{
public int cbSize;
public uint dwFlags;
public string lpSource;
public ushort wProcessorArchitecture;
public ushort wLangId;
public string lpAssemblyDirectory;
public string lpResourceName;
public string lpApplicationName;
}
}
}
I recently ran into this problem when debugging code with the TaskDialogDemo in the CodePack. This is how I kind of fixed it. The problem with using this is if I open two or three dialogs it throws an SEHException, which I haven't figured out how to fix. So buyer beware.
Add Core\Interop\TaskDialogs\EnableThemingInScope.cs:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows.Forms;
namespace Microsoft.WindowsAPICodePack.Dialogs {
/// http://support.microsoft.com/kb/830033
/// <devdoc>
/// This class is intended to use with the C# 'using' statement in
/// to activate an activation context for turning on visual theming at
/// the beginning of a scope, and have it automatically deactivated
/// when the scope is exited.
/// </devdoc>
[SuppressUnmanagedCodeSecurity]
internal class EnableThemingInScope : IDisposable {
// Private data
private uint cookie;
private static ACTCTX enableThemingActivationContext;
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources" )]
private static IntPtr hActCtx;
private static bool contextCreationSucceeded = false;
public EnableThemingInScope( bool enable ) {
cookie = 0;
if ( enable && OSFeature.Feature.IsPresent( OSFeature.Themes ) ) {
if ( EnsureActivateContextCreated() ) {
if ( !ActivateActCtx( hActCtx, out cookie ) ) {
// Be sure cookie always zero if activation failed
cookie = 0;
}
}
}
}
~EnableThemingInScope() {
Dispose();
}
void IDisposable.Dispose() {
Dispose();
GC.SuppressFinalize( this );
}
private void Dispose() {
if ( cookie != 0 ) {
try {
if ( DeactivateActCtx( 0, cookie ) ) {
// deactivation succeeded...
cookie = 0;
}
} catch ( SEHException ) {
// Robpol86: I don't know how to fix this!
}
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity" )]
private static bool EnsureActivateContextCreated() {
lock ( typeof( EnableThemingInScope ) ) {
if ( !contextCreationSucceeded ) {
// Pull manifest from the .NET Framework install
// directory
string assemblyLoc = null;
FileIOPermission fiop = new FileIOPermission( PermissionState.None );
fiop.AllFiles = FileIOPermissionAccess.PathDiscovery;
fiop.Assert();
try {
assemblyLoc = typeof( Object ).Assembly.Location;
} finally {
CodeAccessPermission.RevertAssert();
}
string manifestLoc = null;
string installDir = null;
if ( assemblyLoc != null ) {
installDir = Path.GetDirectoryName( assemblyLoc );
const string manifestName = "XPThemes.manifest";
manifestLoc = Path.Combine( installDir, manifestName );
}
if ( manifestLoc != null && installDir != null ) {
enableThemingActivationContext = new ACTCTX();
enableThemingActivationContext.cbSize = Marshal.SizeOf( typeof( ACTCTX ) );
enableThemingActivationContext.lpSource = manifestLoc;
// Set the lpAssemblyDirectory to the install
// directory to prevent Win32 Side by Side from
// looking for comctl32 in the application
// directory, which could cause a bogus dll to be
// placed there and open a security hole.
enableThemingActivationContext.lpAssemblyDirectory = installDir;
enableThemingActivationContext.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
// Note this will fail gracefully if file specified
// by manifestLoc doesn't exist.
hActCtx = CreateActCtx( ref enableThemingActivationContext );
contextCreationSucceeded = (hActCtx != new IntPtr( -1 ));
}
}
// If we return false, we'll try again on the next call into
// EnsureActivateContextCreated(), which is fine.
return contextCreationSucceeded;
}
}
// All the pinvoke goo...
[DllImport( "Kernel32.dll" )]
private extern static IntPtr CreateActCtx( ref ACTCTX actctx );
[DllImport( "Kernel32.dll" )]
private extern static bool ActivateActCtx( IntPtr hActCtx, out uint lpCookie );
[DllImport( "Kernel32.dll" )]
private extern static bool DeactivateActCtx( uint dwFlags, uint lpCookie );
private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004;
private struct ACTCTX {
public int cbSize;
public uint dwFlags;
public string lpSource;
public ushort wProcessorArchitecture;
public ushort wLangId;
public string lpAssemblyDirectory;
public string lpResourceName;
public string lpApplicationName;
}
}
}
Then in Core\Interop\TaskDialogs\NativeTaskDialog.cs on line 93 (above HResult hresult = TaskDialogNativeMethods.TaskDialogIndirect) make the section look like this (in the end you will have three new lines):
// Here is the way we use "vanilla" P/Invoke to call TaskDialogIndirect().
HResult hresult;
using ( new EnableThemingInScope( true ) ) {
hresult = TaskDialogNativeMethods.TaskDialogIndirect(
nativeDialogConfig,
out selectedButtonId,
out selectedRadioButtonId,
out checkBoxChecked );
}
I have the same issue with Visual Studio in Debug mode. So far I haven't found a workaround, it works fine in Release mode.
This page describes how to add a custom manifest to your project in order to tell Windows to load the new comctl32.dll (version 6.0):
Setting the correct manifest version
Does your manifest have the right dependency on comctl32.dll? Did you embed the created manifest?

Drawing On Top Of TitleBar (With Graphics.FromHWnd())

I am attempting to overlay a status message on an external application.
Previously, I achieved this by using a TransparencyKey on a Form and the following API call to get the window location with a hook to capture the window moved event.
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref Rect lpRect);
This works on my development machine, however, on the target machine it fails, the transparent area actually has hatch markings over it. Presumably something to do with that machine being a VM and having no hardware graphics accelleration.
So, I've done away with the Form and have the following code (with DrawFrame() being called every 60ms) to draw manually to the screen:
class DirectDisplay:IDisposable
{
private Graphics window;
private SolidBrush b;
private string Status;
private NativeMethods.Rect location;
private bool running;
public DirectDisplay(IntPtr _targetHWnd, string status)
{
Status = status;
b = new SolidBrush(Color.FromArgb(255,0,149,48));
window = Graphics.FromHwnd(_targetHWnd);
}
public void DrawFrame()
{
window.DrawString(Status, new Font("Arial", 12),b, 0, -20);
}
public void Dispose()
{
window?.Dispose();
b?.Dispose();
}
}
Which works fine:
However, I need to be able to draw up here on the title bar:
It appears as though utilising Graphics.FromHwnd() limits me to using the typeable space in notepad so I can't draw directly into the button bar.
How do I get a graphics object encompassing the entire Window that I can draw over?
For reference, here is the rest of my code:
namespace OnScreenOverlay
{
class DataManager:IDisposable
{
private const string USER_CACHE = #"C:\test.txt";
private DirectDisplay directDisplay;
private volatile bool exiting;
private readonly Process _target;
private readonly IntPtr _targetHWnd;
private string _currentUser;
private int _daysUntilExpiry;
private NativeMethods.Rect _location;
public DataManager()
{
_target= Process.GetProcessesByName("notepad")[0];
if (_target== null)
{
MessageBox.Show("No target detected... Closing");
}
_targetHWnd = _target.MainWindowHandle;
//InitializeWinHook();
GetCurrentUser();
GetExpiryDate();
directDisplay = new DirectDisplay(_targetHWnd, $"Current User: {_currentUser} --- Password Expires: {_daysUntilExpiry} days");
}
private void GetCurrentUser()
{
if (File.Exists(USER_CACHE))
{
_currentUser = File.ReadAllLines(USER_CACHE)[0].Split('=')[0];
}
else
{
Application.Exit();
}
}
private void GetExpiryDate()
{
using (PrincipalContext domain = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal user = UserPrincipal.FindByIdentity(domain, IdentityType.SamAccountName, _currentUser))
{
DateTime? pwLastSet = user?.LastPasswordSet;
if (pwLastSet.HasValue)
{
_daysUntilExpiry = (int)(TimeSpan.FromDays(7) - (DateTime.Now - pwLastSet.Value)).TotalDays;
}
else
{
_daysUntilExpiry = int.MinValue;
}
}
}
}
public void Start()
{
while (!exiting)
{
directDisplay.DrawFrame();
Thread.Sleep(1000/60); //Prevent method returning
}
}
private void InitializeWinHook()
{
NativeMethods.SetWinEventHook(NativeMethods.EVENT_OBJECT_LOCATIONCHANGE, NativeMethods.EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, TargetMoved, (uint)_target.Id,
NativeMethods.GetWindowThreadProcessId(_target.MainWindowHandle, IntPtr.Zero), NativeMethods.WINEVENT_OUTOFCONTEXT | NativeMethods.WINEVENT_SKIPOWNPROCESS | NativeMethods.WINEVENT_SKIPOWNTHREAD);
}
private void TargetMoved(IntPtr hWinEventHook, uint eventType, IntPtr lParam, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
NativeMethods.GetWindowRect(_targetHWnd, ref _location);
}
public void Dispose()
{
directDisplay?.Dispose();
_target?.Dispose();
}
}
}
I realise that I don't need the WindowsHook stuff if I'm utilising this method to get the Graphics object, I just haven't removed it yet in-case this method doesn't work.
Further to this, I know I could get the Graphics object for the Desktop using IntPtr.Zero but I only want my overlay to be a Single Z-level above the target application.

WPF WebBrowser control - how to suppress script errors?

I found a similar question here:
How do I suppress script errors when using the WPF WebBrowser control?
But non of those solutions work for me. I need to stop the popups from appearing as i am using the WebBrowser to automate admin tasks on a website.
SuppressScriptErrors does not appear to be an available attribute on my WebControl :(
Here is a C# routine that is capable of putting WPF's WebBrowser in silent mode. You can't call it at WebBrowser initialization as it 's too early, but instead after navigation occured. Here is a WPF sample app with a wbMain WebBrowser component:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
wbMain.Navigated += new NavigatedEventHandler(wbMain_Navigated);
}
void wbMain_Navigated(object sender, NavigationEventArgs e)
{
SetSilent(wbMain, true); // make it silent
}
private void button1_Click(object sender, RoutedEventArgs e)
{
wbMain.Navigate(new Uri("... some url..."));
}
}
public static void SetSilent(WebBrowser browser, bool silent)
{
if (browser == null)
throw new ArgumentNullException("browser");
// get an IWebBrowser2 from the document
IOleServiceProvider sp = browser.Document as IOleServiceProvider;
if (sp != null)
{
Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E");
object webBrowser;
sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out webBrowser);
if (webBrowser != null)
{
webBrowser.GetType().InvokeMember("Silent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.PutDispProperty, null, webBrowser, new object[] { silent });
}
}
}
[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IOleServiceProvider
{
[PreserveSig]
int QueryService([In] ref Guid guidService, [In] ref Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject);
}
Thought it'd be relevant to add here. There is another option to get to the WPF WebBrowser's underlying WebBorwser ActiveX Control and its otherwise inaccessible methods and events. I just discovered it a few days ago. It's very simple and doesn't require initial navigation on WB:
dynamic activeX = this.WB.GetType().InvokeMember("ActiveXInstance",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, this.WB, new object[] { });
activeX.Silent = true;
Of course, there's a chance this method may not work in future version of the Framework, but so is true about any other undocumented method. So far, it's been there since .NET 3.0.
More details with a working code sample here.
Thanks to Simon Mourier for elegant way to solve this problem. I made a little improvement and encapsulated Simon's solution into attached property.
In my application I use WebBrowser control databounded to viewmodel, the webbrowser might be hidden on inactive TabItem, so I have to check that it has been Loaded and Navigated before setting javascript errors silent. And of cource this setting should be done just once, so after setting I release hooked events.
XAML Code:
<TabControl xmlns:b="clr-namespace:MyApplication.Behaviors">
<TabItem Header="foo">...</TabItem>
<TabItem Header="Google map">
<WebBrowser b:BindableSource="{Binding Path=MapUrl}"
b:DisableJavascriptErrors="True" />
</TabItem>
</TabControl>
Behavior code:
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace MyApplication.Behaviors
{
public class WebBrowserBehavior
{
private static readonly Type OwnerType = typeof (WebBrowserBehavior);
#region BindableSource
public static readonly DependencyProperty BindableSourceProperty =
DependencyProperty.RegisterAttached(
"BindableSource",
typeof(string),
OwnerType,
new UIPropertyMetadata(OnBindableSourcePropertyChanged));
[AttachedPropertyBrowsableForType(typeof(WebBrowser))]
public static string GetBindableSource(DependencyObject obj)
{
return (string)obj.GetValue(BindableSourceProperty);
}
[AttachedPropertyBrowsableForType(typeof(WebBrowser))]
public static void SetBindableSource(DependencyObject obj, string value)
{
obj.SetValue(BindableSourceProperty, value);
}
public static void OnBindableSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var browser = d as WebBrowser;
if (browser == null) return;
browser.Source = (e.NewValue != null) ? new Uri(e.NewValue.ToString()) : null;
}
#endregion
#region DisableJavascriptErrors
#region SilentJavascriptErrorsContext (private DP)
private static readonly DependencyPropertyKey SilentJavascriptErrorsContextKey =
DependencyProperty.RegisterAttachedReadOnly(
"SilentJavascriptErrorsContext",
typeof (SilentJavascriptErrorsContext),
OwnerType,
new FrameworkPropertyMetadata(null));
private static void SetSilentJavascriptErrorsContext(DependencyObject depObj, SilentJavascriptErrorsContext value)
{
depObj.SetValue(SilentJavascriptErrorsContextKey, value);
}
private static SilentJavascriptErrorsContext GetSilentJavascriptErrorsContext(DependencyObject depObj)
{
return (SilentJavascriptErrorsContext) depObj.GetValue(SilentJavascriptErrorsContextKey.DependencyProperty);
}
#endregion
public static readonly DependencyProperty DisableJavascriptErrorsProperty =
DependencyProperty.RegisterAttached(
"DisableJavascriptErrors",
typeof (bool),
OwnerType,
new FrameworkPropertyMetadata(OnDisableJavascriptErrorsChangedCallback));
[AttachedPropertyBrowsableForType(typeof(WebBrowser))]
public static void SetDisableJavascriptErrors(DependencyObject depObj, bool value)
{
depObj.SetValue(DisableJavascriptErrorsProperty, value);
}
[AttachedPropertyBrowsableForType(typeof(WebBrowser))]
public static bool GetDisableJavascriptErrors(DependencyObject depObj)
{
return (bool)depObj.GetValue(DisableJavascriptErrorsProperty);
}
private static void OnDisableJavascriptErrorsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var webBrowser = d as WebBrowser;
if (webBrowser == null) return;
if (Equals(e.OldValue, e.NewValue)) return;
var context = GetSilentJavascriptErrorsContext(webBrowser);
if (context != null) {
context.Dispose();
}
if (e.NewValue != null) {
context = new SilentJavascriptErrorsContext(webBrowser);
SetSilentJavascriptErrorsContext(webBrowser, context);
}
else {
SetSilentJavascriptErrorsContext(webBrowser, null);
}
}
private class SilentJavascriptErrorsContext : IDisposable
{
private bool? _silent;
private readonly WebBrowser _webBrowser;
public SilentJavascriptErrorsContext(WebBrowser webBrowser)
{
_silent = new bool?();
_webBrowser = webBrowser;
_webBrowser.Loaded += OnWebBrowserLoaded;
_webBrowser.Navigated += OnWebBrowserNavigated;
}
private void OnWebBrowserLoaded(object sender, RoutedEventArgs e)
{
if (!_silent.HasValue) return;
SetSilent();
}
private void OnWebBrowserNavigated(object sender, NavigationEventArgs e)
{
var webBrowser = (WebBrowser)sender;
if (!_silent.HasValue) {
_silent = GetDisableJavascriptErrors(webBrowser);
}
if (!webBrowser.IsLoaded) return;
SetSilent();
}
/// <summary>
/// Solution by Simon Mourier on StackOverflow
/// http://stackoverflow.com/a/6198700/741414
/// </summary>
private void SetSilent()
{
_webBrowser.Loaded -= OnWebBrowserLoaded;
_webBrowser.Navigated -= OnWebBrowserNavigated;
// get an IWebBrowser2 from the document
var sp = _webBrowser.Document as IOleServiceProvider;
if (sp != null)
{
var IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
var IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E");
object webBrowser2;
sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out webBrowser2);
if (webBrowser2 != null)
{
webBrowser2.GetType().InvokeMember(
"Silent",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.PutDispProperty,
null,
webBrowser2,
new object[] { _silent });
}
}
}
[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IOleServiceProvider
{
[PreserveSig]
int QueryService([In] ref Guid guidService, [In] ref Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject);
}
public void Dispose()
{
if (_webBrowser != null) {
_webBrowser.Loaded -= OnWebBrowserLoaded;
_webBrowser.Navigated -= OnWebBrowserNavigated;
}
}
}
#endregion
}
}
The answer by #SimonMourier didn't work for me, but this did:
public void HideScriptErrors(WebBrowser wb, bool Hide)
{
FieldInfo fiComWebBrowser = typeof(WebBrowser)
.GetField("_axIWebBrowser2",
BindingFlags.Instance | BindingFlags.NonPublic);
if (fiComWebBrowser == null) return;
object objComWebBrowser = fiComWebBrowser.GetValue(wb);
if (objComWebBrowser == null) return;
objComWebBrowser.GetType().InvokeMember(
"Silent", BindingFlags.SetProperty, null, objComWebBrowser,
new object[] { Hide });
}
Note that I got it from here.
I've also found an interesting way to disable JavaScript errors. But you need to use at least .Net Framework 4.0 because of using elegant dynamic type.
You need to subscribe to the LoadCompleted event of the WebBrowser element:
<WebBrowser x:Name="Browser"
LoadCompleted="Browser_OnLoadCompleted" />
After that you need to write an event handler that looks like below:
void Browser_OnLoadCompleted(object sender, NavigationEventArgs e)
{
var browser = sender as WebBrowser;
if (browser == null || browser.Document == null)
return;
dynamic document = browser.Document;
if (document.readyState != "complete")
return;
dynamic script = document.createElement("script");
script.type = #"text/javascript";
script.text = #"window.onerror = function(msg,url,line){return true;}";
document.head.appendChild(script);
}
You can look at my solution:
Disabling JavaScript errors in WebBrowser control in Silverlight - it's for Silverlight but should also work for WPF.
Well if it was necessary i would have gone for WinformHost and added WebBrowser Control to it and used it.
You can easily do those tasks here in WinformHost also because i have made whole applications that does bundle of things
Here is an example of how to do this without using reflection.
/// <summary>
/// Gets an interop web browser.
/// </summary>
/// <param name="browser"></param>
/// <returns></returns>
public static SHDocVw.WebBrowser GetInteropWebBrowser(this WebBrowser browser)
{
Guid serviceGuid = new Guid("0002DF05-0000-0000-C000-000000000046");
Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;
Interop.IServiceProvider serviceProvider = (Interop.IServiceProvider)browser.Document;
SHDocVw.IWebBrowser2 browser2 = (SHDocVw.IWebBrowser2)serviceProvider.QueryService(ref serviceGuid, ref iid);
SHDocVw.WebBrowser wb = (SHDocVw.WebBrowser)browser2;
return wb;
}
/// <summary>
/// Disables script errors for the browser.
/// </summary>
/// <param name="browser"></param>
/// <param name="silent"></param>
public static void SetSilent(this WebBrowser browser, bool silent)
{
SHDocVw.WebBrowser browser2 = browser.GetInteropWebBrowser();
if (browser2 != null)
browser2.Silent = silent;
}
/// <summary>
/// Provides the COM interface for the IServiceProvider.
/// </summary>
[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IServiceProvider
{
/// <summary>
/// Queries the service.
/// </summary>
/// <param name="serviceGuid"></param>
/// <param name="riid"></param>
/// <returns></returns>
[return: MarshalAs(UnmanagedType.IUnknown)]
object QueryService(ref Guid serviceGuid, ref Guid riid);
}
Then in the constructor for the view that hosts the Browser control you have:
Browser.Navigated += (s, e) =>
{
Browser.SetSilent(true);
};
Really very simple, thank you for your solution.
http://social.msdn.microsoft.com/Forums/en-US/6996b0c5-b44d-4040-9dbe-6206b1d9185e/webbrowser-script-error-when-using-google-maps?forum=wpf&prof=required
Dim sb As New StringBuilder
sb.Append("<html>")
sb.Append("<head>")
sb.Append("</head")
sb.Append("<body>")
sb.Append("<iframe src ='" + url + "' height='" + webBrowser1.Height + "' width='" + webBrowser1.Width + "'></iframe>")
sb.Append("</body")
sb.Append("</html>")
WebBrowser1.DocumentText = sb.ToString

Show detailed Folder Browser from a PropertyGrid

Please note it is not a duplicate question.
How to show a detailed FolderBrowser as in the image below from a PropertyGrid (from the field/property which has ellipses ...)
Using
[EditorAttribute(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
[EditorAttribute(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
We get the minimalistic folder browser
Here is a custom UITypeEditor that allows you to use the Vista Folder Browser:
You can use it like any other editor:
[EditorAttribute(typeof(FolderNameEditor2), typeof(System.Drawing.Design.UITypeEditor))]
It relies on a custom FolderBrowser2 class that I have written for the occasion. Of course, this will work only on Windows Vista and higher. On previous Windows version, there is no other folder browser than the simple one.
public class FolderNameEditor2 : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
FolderBrowser2 browser = new FolderBrowser2();
if (value != null)
{
browser.DirectoryPath = string.Format("{0}", value);
}
if (browser.ShowDialog(null) == DialogResult.OK)
return browser.DirectoryPath;
return value;
}
}
public class FolderBrowser2
{
public string DirectoryPath { get; set; }
public DialogResult ShowDialog(IWin32Window owner)
{
IntPtr hwndOwner = owner != null ? owner.Handle : GetActiveWindow();
IFileOpenDialog dialog = (IFileOpenDialog)new FileOpenDialog();
try
{
IShellItem item;
if (!string.IsNullOrEmpty(DirectoryPath))
{
IntPtr idl;
uint atts = 0;
if (SHILCreateFromPath(DirectoryPath, out idl, ref atts) == 0)
{
if (SHCreateShellItem(IntPtr.Zero, IntPtr.Zero, idl, out item) == 0)
{
dialog.SetFolder(item);
}
Marshal.FreeCoTaskMem(idl);
}
}
dialog.SetOptions(FOS.FOS_PICKFOLDERS | FOS.FOS_FORCEFILESYSTEM);
uint hr = dialog.Show(hwndOwner);
if (hr == ERROR_CANCELLED)
return DialogResult.Cancel;
if (hr != 0)
return DialogResult.Abort;
dialog.GetResult(out item);
string path;
item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out path);
DirectoryPath = path;
return DialogResult.OK;
}
finally
{
Marshal.ReleaseComObject(dialog);
}
}
[DllImport("shell32.dll")]
private static extern int SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)] string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
[DllImport("shell32.dll")]
private static extern int SHCreateShellItem(IntPtr pidlParent, IntPtr psfParent, IntPtr pidl, out IShellItem ppsi);
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
private const uint ERROR_CANCELLED = 0x800704C7;
[ComImport]
[Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")]
private class FileOpenDialog
{
}
[ComImport]
[Guid("42f85136-db7e-439c-85f1-e4075d135fc8")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IFileOpenDialog
{
[PreserveSig]
uint Show([In] IntPtr parent); // IModalWindow
void SetFileTypes(); // not fully defined
void SetFileTypeIndex([In] uint iFileType);
void GetFileTypeIndex(out uint piFileType);
void Advise(); // not fully defined
void Unadvise();
void SetOptions([In] FOS fos);
void GetOptions(out FOS pfos);
void SetDefaultFolder(IShellItem psi);
void SetFolder(IShellItem psi);
void GetFolder(out IShellItem ppsi);
void GetCurrentSelection(out IShellItem ppsi);
void SetFileName([In, MarshalAs(UnmanagedType.LPWStr)] string pszName);
void GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
void SetTitle([In, MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
void SetOkButtonLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszText);
void SetFileNameLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
void GetResult(out IShellItem ppsi);
void AddPlace(IShellItem psi, int alignment);
void SetDefaultExtension([In, MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
void Close(int hr);
void SetClientGuid(); // not fully defined
void ClearClientData();
void SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter);
void GetResults([MarshalAs(UnmanagedType.Interface)] out IntPtr ppenum); // not fully defined
void GetSelectedItems([MarshalAs(UnmanagedType.Interface)] out IntPtr ppsai); // not fully defined
}
[ComImport]
[Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellItem
{
void BindToHandler(); // not fully defined
void GetParent(); // not fully defined
void GetDisplayName([In] SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
void GetAttributes(); // not fully defined
void Compare(); // not fully defined
}
private enum SIGDN : uint
{
SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
SIGDN_FILESYSPATH = 0x80058000,
SIGDN_NORMALDISPLAY = 0,
SIGDN_PARENTRELATIVE = 0x80080001,
SIGDN_PARENTRELATIVEEDITING = 0x80031001,
SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
SIGDN_PARENTRELATIVEPARSING = 0x80018001,
SIGDN_URL = 0x80068000
}
[Flags]
private enum FOS
{
FOS_ALLNONSTORAGEITEMS = 0x80,
FOS_ALLOWMULTISELECT = 0x200,
FOS_CREATEPROMPT = 0x2000,
FOS_DEFAULTNOMINIMODE = 0x20000000,
FOS_DONTADDTORECENT = 0x2000000,
FOS_FILEMUSTEXIST = 0x1000,
FOS_FORCEFILESYSTEM = 0x40,
FOS_FORCESHOWHIDDEN = 0x10000000,
FOS_HIDEMRUPLACES = 0x20000,
FOS_HIDEPINNEDPLACES = 0x40000,
FOS_NOCHANGEDIR = 8,
FOS_NODEREFERENCELINKS = 0x100000,
FOS_NOREADONLYRETURN = 0x8000,
FOS_NOTESTFILECREATE = 0x10000,
FOS_NOVALIDATE = 0x100,
FOS_OVERWRITEPROMPT = 2,
FOS_PATHMUSTEXIST = 0x800,
FOS_PICKFOLDERS = 0x20,
FOS_SHAREAWARE = 0x4000,
FOS_STRICTFILETYPES = 4
}
}
Here's a solution that does the same job as Simon Mourier's answer, without directly using interop (.Net takes care of that for you). It has the additional feature of falling back to the pre-Vista dialog if not in a high enough Windows version. Should work in Windows 7, 8, 10 and higher (theoretically).
There is one big caveat: Microsoft is free to change their internal classes at will. Since this uses Reflection to defeat scoping rules and this action is not supported (Microsoft is only interested in what's publicly exposed), this code could break if Microsoft does make changes.
using System;
using System.Reflection;
using System.Windows.Forms;
namespace ErikE.Shuriken {
/// <summary>
/// Present the Windows Vista-style open file dialog to select a folder. Fall back for older Windows Versions
/// </summary>
public class FolderSelectDialog {
private string _initialDirectory;
private string _title;
private string _fileName = "";
public string InitialDirectory {
get { return string.IsNullOrEmpty(_initialDirectory) ? Environment.CurrentDirectory : _initialDirectory; }
set { _initialDirectory = value; }
}
public string Title {
get { return _title ?? "Select a folder"; }
set { _title = value; }
}
public string FileName { get { return _fileName; } }
public bool Show() { return Show(IntPtr.Zero); }
/// <param name="hWndOwner">Handle of the control or window to be the parent of the file dialog</param>
/// <returns>true if the user clicks OK</returns>
public bool Show(IntPtr hWndOwner) {
var result = Environment.OSVersion.Version.Major >= 6
? VistaDialog.Show(hWndOwner, InitialDirectory, Title)
: ShowXpDialog(hWndOwner, InitialDirectory, Title);
_fileName = result.FileName;
return result.Result;
}
private struct ShowDialogResult {
public bool Result { get; set; }
public string FileName { get; set; }
}
private static ShowDialogResult ShowXpDialog(IntPtr ownerHandle, string initialDirectory, string title) {
var folderBrowserDialog = new FolderBrowserDialog {
Description = title,
SelectedPath = initialDirectory,
ShowNewFolderButton = false
};
var dialogResult = new ShowDialogResult();
if (folderBrowserDialog.ShowDialog(new WindowWrapper(ownerHandle)) == DialogResult.OK) {
dialogResult.Result = true;
dialogResult.FileName = folderBrowserDialog.SelectedPath;
}
return dialogResult;
}
private static class VistaDialog {
private const string c_foldersFilter = "Folders|\n";
private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private readonly static Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly;
private readonly static Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
private readonly static MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags);
private readonly static MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags);
private readonly static MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags);
private readonly static MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags);
private readonly static uint s_fosPickFoldersBitFlag = (uint) s_windowsFormsAssembly
.GetType("System.Windows.Forms.FileDialogNative+FOS")
.GetField("FOS_PICKFOLDERS")
.GetValue(null);
private readonly static ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly
.GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
.GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null);
private readonly static MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise");
private readonly static MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise");
private readonly static MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show");
public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory, string title) {
var openFileDialog = new OpenFileDialog {
AddExtension = false,
CheckFileExists = false,
DereferenceLinks = true,
Filter = c_foldersFilter,
InitialDirectory = initialDirectory,
Multiselect = false,
Title = title
};
var iFileDialog = s_createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { });
s_onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog });
s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint) s_getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | s_fosPickFoldersBitFlag });
var adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U };
s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);
try {
int retVal = (int) s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });
return new ShowDialogResult {
Result = retVal == 0,
FileName = openFileDialog.FileName
};
}
finally {
s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
}
}
}
// Wrap an IWin32Window around an IntPtr
private class WindowWrapper : IWin32Window {
private readonly IntPtr _handle;
public WindowWrapper(IntPtr handle) { _handle = handle; }
public IntPtr Handle { get { return _handle; } }
}
}
}
I developed this as a cleaned up version of .NET Win 7-style folder select dialog by Bill Seddon of lyquidity.com (I have no affiliation). I wrote my own because his solution requires an additional Reflection class that isn't needed for this focused purpose, uses exception-based flow control, doesn't cache the results of its reflection calls. Note that the nested static VistaDialog class is so that its static reflection variables don't try to get populated if the Show method is never called.
It is used like so in a Windows Form:
var dialog = new FolderSelectDialog {
InitialDirectory = musicFolderTextBox.Text
Title = "Select a folder to import music from"
};
if (dialog.Show(Handle)) {
musicFolderTextBox.Text = dialog.FileName;
}
You can of course play around with its options and what properties it exposes. For example, it allows multiselect in the Vista-style dialog.

Resources