C# WebBrowser control not firing the DocumentCompleted event - c#

I have a program that is using the C# WebBrowser control and it needs to detect which page is loaded to determine what to do next. The program works fine on most of the employee's computers at the office, but it does not work on some.
I have determined the problem is that the documentCompleted event is not firing on those computers it does not work on.
This program does use threads to process data, and the webbrowser.navigate call is made through a delegate. But I have also changed the code to not use delegates for the navigate action with no change in the result.
I also made a separate program that has just a basic WebBrowser and debug textfield, and the DocumentCompleted event does fire when using that program.
NOTE: The computers that it is not firing on are older PCs with single core/thread processors.
I am out of ideas on this one, any help would be appreciated.

As explained by CodeBlock, this seems to be related by the installation state of Microsoft.mshtml.dll
We've got customers where the Microsoft.mshtml.dll is not present in GAC (nor in computer), and then the WebBrowser component never fires any event.
By using Reflector in the WebBrowser class, the DocumentComplete event is raised by a subclass named WebBrowserEvent, which implement a private interface DWebBrowserEvents2.
This interface is a ComImport of {34A715A0-6587-11D0-924A-0020AFC7AC4D}, which, I suppose, is related to Microsoft.mshtml.dll.
So our solution was to install the Office 2003 Redistributable Primary Interop Assemblies, which install the DLL on Program Files then register it on the GAC.
Note : Don't pay attention to the .NET Framework 1.1 required or office required, it just copies some dlls.
Note 2 : The 2007 package seems to include the same dll.

#Pavel L:
The problem here is you used a web browser control from mshtml.dll but .NET framework does not include this file. The solution for this is simply copy mshtml.dll to your app dir or set 'Copy local' property of Microsoft.mshtml to True.
Sorry for my bad english :D

If it is a threading issue, make sure you are calling Application.DoEvents(). I've had problems with WebBrowser not working right when I failed to do that.

Well I'd like to share even more simple solution rather than installing a package.
As it was stated before the DocumentComplete event somehow depends on Microsoft.mshtml.dll file. You can find it on a machine with Visual Studio installed. So it needs to be copied and installed to the target machine. Here's the description of the process:
Place the Microsoft.mshtml.dll file into the "%ProgramFiles%\Microsoft.NET\Primary Interop Assemblies" folder.
Then drag and drop it into the "%SystemRoot%\Assembly" folder.
Register the library with RegAsm.exe utility (which is located in the appropriate subfolder of "%windir%\Microsoft.NET\Framework").
P.S. May be it may be done in a better way but this solution works and I hope it'll be useful for you.

In order for the documentCompleted-Event to fire,
the visible property of the web browser needs to be set to true.
It can also be on visible, if you have multiple screens.
If you have > 1 screen, switch off all but the main screen, this should resolve the problem.
Alternatively, move the window to the 2nd screen.

Make sure webbrowser.Visible=true; this works for me, I had similar problems previously.

Related

Asynchronous Drag and Drop to Windows Explorer

Question:
I need a DragAndDrop solution to download a file on drop in a folder of Windows Explorer for C# & .NET 4.0. It should not be necessary to have the file on the computer. The file will be big enough that the drag-time won't be enough to get the download done. I have found various questions, even accepted answers, but nothing that works. The very closest thing to something working is this demo project:
http://blogs.msdn.com/b/delay/archive/2009/11/16/creating-something-from-nothing-and-knowing-it-developer-friendly-virtual-file-implementation-for-net-refined.aspx
How to implement this code to download a file as part of the action of putting it to the drop place in Windows Explorer?
Web browsers solve this problem every day. Simplifying their model a little, do this:
Make a little program that performs your download given appropriate command line parameters. This little program should pop up a window with a progress bar and a cancel button.
Spawn this second program whenever the user "drops" something. This program will create the target file immediately and start filling it with data. It will maintain appropriate locks on the file until it is done downloading, at which point the "downloader" will exit.
If you're going to keep the "downloader" threads in the originating program, you will need some kind of download manager so that the user can get appropriate feedback on their downloads.
Okay, as Yahia said in the comments it's not possible without a proper shell extension for the different versions of Windows and .NET. You might have luck with the link I posted, but for me it crashes the Explorer and the developer thinks it works fine.
My honest opinion is with only .NET you can only do it with a FileSystemWatcher via copying special .temp-files, watching where they land, doing your task and replacing the .temp files when your task is done. Sad Windows.

Setup project with custom form

I’m currently working on a Visual Studio 2010 setup Project and would like to know if the following is possible:
1) Run the setup project in a way that the default forms don’t show, instead I’d show my own custom form that subscribes to setup project events. This way I'd show install messages and increase my own progress bar.
2) If 1 is possible, I would need a way to specify the default location.
3) I have a separate library project, where I have a custom install class (inherits from “System.Configuration.Install.Installer”) from within the install handler I’d like to be able to show custom windows forms, and control choices made by the user. I guess this is possible by adding a reference to system.windows.forms, but would this be the correct way to go about this? If I couldn't hide the default install form, these custom forms would appear over the default install one and I think it would look too great.
Suggestions, links etc appreciated
Thanks!
*UPDATE 1 *
Could I launch an .msi from c# code but also passing in a value.?
Just what this guy does here:
link
But passing in a value... then from my custom install class I take actions depending on this value.
UPDATE 2
Seems like I can:
link code project
UPDATE 3
I'm considering in doing the following, I'll start testing with a winforms app.
1) Launch winforms application.
2) Make a few webService calls, display data, user makes selection.
3) As per link in update 1, launch process(silent mode) and per update 2, pass in selected values.
4) Use some cross process events mechanism (WCF) so that my custom install class can notify my form of the different steps its running and update progress bar and messages.
You can create custom forms but the declaration needs to be done inside MSI. You can show a custom dialog via a custom action but that will not help you much since msi does this:
Load custom action dll
If it is managed the CLR is started and your maanged code executed
When the custom action is left the dll is unloaded and the clr is shut down
This is done every time a custom action is called. This is one of the main reasons why custom actions are normally written in C++.
To be more flexible you should use the WIX toolkit which allows .NET integration as good as it can be with MSI. MSI itself knows nothing about .NET and is a world of its own.
MSI itself defines dialogs and controls inside the msi via tables like the Dialog and Control table.
You could create a dialog and store your state in a msi property between each several msi actions which need to happen e.g. to calculate the disc space for the selected features and so on. But I doubt that this solution will be performant and I fear that starting and shutting down the CLR so often inside one process will expose you to CLR bugs that no one has encountered before.
To set the target location you only need to call the MSI method MsiSetTargetPath which you can PInvoke very easy.
To disable the normal UI you can override it completely or partially vis MsiSetExternalUI but I have not tried to disable only specific dialogs. If you want to hide specific dialogs you should check the msi tables of your current MSI to check if you can set a msi property to make the dialog think it has already been shown.
Yours,
Alois Kraus
As far as I know the setup projects made by Visual Studio are very limited unless you use custom actions. These Custom Actions can take a lot of time to create and debug so it might be wiser to use a more mature/featured tools such as Installshield
EDIT As for showing windows using winforms: that is ok but: a nice setup allows a silent/scripted install, make sure you allow this. Another thing to look out for is machines not having .NET and thus not being able to show the Forms... IMHO that is a no-no unless you are sure .NET (correct version) is present.
EDIT 2 In response to some comments: There are some scenarios that can't be implemented with VISUAL STUDIO Setup and Deployment projects. I am not saying that Windows Installer is bad. E.g., Try to make a custom installer to decide where an application will be installed and skipping the standard window that the project generates. I am not saying that custom actions are limited but they are IMHO not easy either.
Also, when you want use custom WinForms instead of Installer forms you have to make sure that the bootstrap of the .NET framework is done BEFORE showing any (WinForm) windows. It might be possible but if you want such customisation you might be better of with a more flexible tool.

Prevent C# Dll from being loaded for certain apps

Greetings all,
I have a shell toolbar extension written in C#. It's only meant to be used in Windows Explorer, so I want to prevent the DLL from being loaded in Internet Explorer. Windows provides tons of ways to load extensions in IE only, but seemingly no way to do Explorer only. I know there are various checks I could perform in different places after the DLL is loaded, but the ideal would be to prevent the DLL from loading at all.
Now, if it were written C++, I would call GetModuleFileName in DllMain, check if the executable was iexplore.exe, and return false on attach if so. But there is no DllMain in C#; Microsoft doesn't trust us to play nice with loader lock. Is there any other way I can selectively prevent a C# DLL from loading?
Don't do Shell Extension Handlers in .NET
http://blogs.msdn.com/b/junfeng/archive/2005/11/18/494572.aspx
Section 3: Registering our AppBar
http://www.codeproject.com/KB/shell/csdoesshell3.aspx?print=true
I had to send this one in a separate post as a new user is not allowed to send more than one link in 1 post.

Do you have ideas for a workaround for this Known bug in Visual Studio 2010's addIn model?

When developing AddIns for Visual Studio 2010 the following line fails:
CommandBarEvents handler = (EnvDTE.CommandBarEvents)m_VSStudio.DTE.Events.get_CommandBarEvents(popup);
Update: Forgot to tell that m_VSStudio is of the type DTE2
Where popup is of the type CommandBarPopup (for the type CommandBarControl it works though)
The line fails with this Exception:
System.Runtime.InteropServices.COMException (0x80020003): Member not found. (Exception from HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND))
The exact same line worked in Visual Studio 2008.
The purpose of the line is to get a handler which handles clickevents, when one clicks the Popup.
After som searching I found this link: http://connect.microsoft.com/VisualStudio/feedback/details/524335/events-get-commandbarevents-exception-on-submenus-reproducible-bug-addin
Which basicly states that it is a known bug, which will not be fixed, because there is a workaround. But unfortunately it does not state the workaround :(
I would be extremely pleased if anybody has a great idea for a workaround ?
The reason why I want to listen to the click events is because I want to show or hide the submenuitems (CommandBarControl) given some condition, when one clicks a menu (CommandBarPopup).
So a workaround that uses something else than the click event would also be appreciated.
Jesper and I talked about this in e-mail. What he was trying to do was ensure that members of a popup menu that he created were in the proper state right before they were shown. He was using the Click even on CommandBarPopup (which was deprecated in 2010 in the move to WPF) to have a way of knowing when he needed to do the state updating. I mentioned the preferred method for doing this (even in 2008) would be to implement IDtCommandtarget on his AddIn class. The VS shell will call this method when it needs to find the status of commands. It will call this method at all the 'regular' times it updates command state (i.e. on idle if needed, right before showing a menu, etc..). Moving to this method works for his scenario and seems to solve his problem.
Ryan
It is unfortunate that the phrase 'our e-mail correspondance' and 'you found a workaround' was put in a public bug with no indication of what the work around was. I suspect the person was trying to do something quite different from you (even if he was using the same event mechanism to hook in), so perhaps we found a better way to do what he needed. I can't think of any easy way to do what you are doing, though if I understood why you were trying to do what you are doing (i.e. are you hiding your own commands? The commands of other people? To what end?) then perhaps we could think of something. Feel free to mail me directly, address is rmolden AT microsoft DOT com, sorry for the inconvienence. We can also follow up here with any work around we find so it will be captured by the internet rememberance machine for all time.

Integrating into Windows Explorer context menu

I want to write a small tool, that does the following:
When you right click on a file with a certain file-extension the Windows Explorer context menu shows an additional entry.
When you click this entry a certain EXE is launched with this file as one of its parameters.
I would like to use C#/.NET 2.0 for this. If it's not possible I could also do it with C++/Win32.
My questions are:
Is it possible with C# .NET 2.0?
What are the necessary functions for integrating into the Windows Explorer context menu?
How can I make this permanent? (I don't want to relaunch this tool after every boot)
What do I have to take special care of? (different OS, security permissions, etc.)
You will need to access the registry and add a key under root\\File\\shell or root\Folder\\shell, depending on which items you want the menu item visible on.
Try this article at CodeProject, it's quite useful.
Edit: There's another article here which may be of help.
It is, incidentally, not supported to use .NET for shell extensions, due to the current inability to host multiple runtime versions in the same process (.NET 4 will lift this restriction).
Consider the case where you have two shell extensions; one for .NET 3.5, one for .NET 1. Which runtime will get loaded into your process? Well, it's more or less random--it depends which shell extension gets loaded first. Sometimes it might be the 2.0 runtime, sometimes it might be the 1.1 runtime.
This is also an issue if a .NET program creates common file dialogs; your shell extension may or may not load, and may or may not run with the correct runtime version.
As such, if you go down the Shell extension route you should use native C++/COM/Win32.

Categories