Windows form Usercontrol hosted in IE
-
I've been doing some research for a migration and am having a hard time determining whether it is possible/feasible to call javascript events from a windows form control that's embedded in a web page. Essentially I'm wanting to use the controls in an activex/applet situation and I want to call a javascript function from the compiled C# control. I would think I could put an event on my control and have the java script 'subscribe' to that event and then I could just fire it as appropriate from within the control. However I'm having a hard time finding a way to do the subscription. I'd like something like this: C#: public class Control1 : UserControl { public delegate void SomethingDelegate(); public event SomethingDelegate OnSomethingHappened = null; .. .. fire the event in the script at some point: OnSomethingHappened(); .. .. } Javascript: function doSomething() { alert("handled event in javascript"); } Anybody tried this before? Any help appreciated! Tim
-
I've been doing some research for a migration and am having a hard time determining whether it is possible/feasible to call javascript events from a windows form control that's embedded in a web page. Essentially I'm wanting to use the controls in an activex/applet situation and I want to call a javascript function from the compiled C# control. I would think I could put an event on my control and have the java script 'subscribe' to that event and then I could just fire it as appropriate from within the control. However I'm having a hard time finding a way to do the subscription. I'd like something like this: C#: public class Control1 : UserControl { public delegate void SomethingDelegate(); public event SomethingDelegate OnSomethingHappened = null; .. .. fire the event in the script at some point: OnSomethingHappened(); .. .. } Javascript: function doSomething() { alert("handled event in javascript"); } Anybody tried this before? Any help appreciated! Tim
Yes, it is possible. You must use automation interfaces in your contro, however, so that scripting engines can access them. See my old article at DevHood, User Controls for Winodws and the Web[^]. Keep in mind that you must follow COM guidelines, and writing for COM dictates that you should use good practices in .NET as well, such as never changing a published interface (instead, derive a new one and call it
IMyInterface2
or something allow those lines), and NEVER use auto-generated class interfaces. Microsoft does this in their samples, but if you read deeper (or have any experience in COM and COM interop with .NET), you'll see they tell you not too (nice, huh?). Because you can change the relative locations of properties and methods in .NET without affecting functionality, this is fine. But it screws-up auto-generated interfaces since methods and properties will be in a different VTBL order, and possibly will have different DISPIDs (if you don't explicitly set them with theDispIdAttribute
). My article covers this a little as well. You can expose methods, properties, and even events this way. Just give yourOBJECT
tag an ID and you can script it. You can hook-up event handlers using attributes or through scripting. My article covers this as well. For a little more information on following COM guidelines in .NET (since that wasn't really the focus of my article), see Nick's article, Creating a CCW for COM-Enabled, non-.NET Applications[^]. Nick even added what I mentioned above into his article, you might notice. :)Microsoft MVP, Visual C# My Articles
-
Yes, it is possible. You must use automation interfaces in your contro, however, so that scripting engines can access them. See my old article at DevHood, User Controls for Winodws and the Web[^]. Keep in mind that you must follow COM guidelines, and writing for COM dictates that you should use good practices in .NET as well, such as never changing a published interface (instead, derive a new one and call it
IMyInterface2
or something allow those lines), and NEVER use auto-generated class interfaces. Microsoft does this in their samples, but if you read deeper (or have any experience in COM and COM interop with .NET), you'll see they tell you not too (nice, huh?). Because you can change the relative locations of properties and methods in .NET without affecting functionality, this is fine. But it screws-up auto-generated interfaces since methods and properties will be in a different VTBL order, and possibly will have different DISPIDs (if you don't explicitly set them with theDispIdAttribute
). My article covers this a little as well. You can expose methods, properties, and even events this way. Just give yourOBJECT
tag an ID and you can script it. You can hook-up event handlers using attributes or through scripting. My article covers this as well. For a little more information on following COM guidelines in .NET (since that wasn't really the focus of my article), see Nick's article, Creating a CCW for COM-Enabled, non-.NET Applications[^]. Nick even added what I mentioned above into his article, you might notice. :)Microsoft MVP, Visual C# My Articles
Wow, awesome article. Really hits home on what I'm looking at. The link you had to the full source is broken however :) Do you still have a copy?
-
Wow, awesome article. Really hits home on what I'm looking at. The link you had to the full source is broken however :) Do you still have a copy?
No I don't. The article is very old and the site was down for quite some time. I guess they didn't get everything fixed properly (like I noticed my image was missing as well). There should be enough information in the article, however. Just read about the classes I use for more information in the .NET Framework SDK documentation.
Microsoft MVP, Visual C# My Articles
-
No I don't. The article is very old and the site was down for quite some time. I guess they didn't get everything fixed properly (like I noticed my image was missing as well). There should be enough information in the article, however. Just read about the classes I use for more information in the .NET Framework SDK documentation.
Microsoft MVP, Visual C# My Articles
Hey, I got it working. I've got to research the security on it a little more but it seems like it might be an option for me. thanks a lot Heath!
-
Hey, I got it working. I've got to research the security on it a little more but it seems like it might be an option for me. thanks a lot Heath!
You should read Understanding .NET Code Access Security[^], as well as follow his links to resources on MSDN. One big mistake is that some developers expect to have FullTrust permissions. This should not be. Determine which permissions your control absolutely requires and use the
SecurityPermissionAttribute
with theSecurityAction.RequestMinimum
(along with what you require) in your assembly attributes (so prefix it with "assembly:"). Then use either declaritive or imperitive security demands throughout your application to make sure you have those permissions. As far as deploying the necessary code group, either post an XML fragment with instructions for user to import it, or write a class that derives fromInstaller
and use that in a Windows Installer package in VS.NET as a custom action. See How to configure .NET Framework security settings and how to deploy a .NET Framework application[^] and read the related links at the bottom for more information and alternatives (like creating and removing the code group using the caspol.exe utility).Microsoft MVP, Visual C# My Articles
-
You should read Understanding .NET Code Access Security[^], as well as follow his links to resources on MSDN. One big mistake is that some developers expect to have FullTrust permissions. This should not be. Determine which permissions your control absolutely requires and use the
SecurityPermissionAttribute
with theSecurityAction.RequestMinimum
(along with what you require) in your assembly attributes (so prefix it with "assembly:"). Then use either declaritive or imperitive security demands throughout your application to make sure you have those permissions. As far as deploying the necessary code group, either post an XML fragment with instructions for user to import it, or write a class that derives fromInstaller
and use that in a Windows Installer package in VS.NET as a custom action. See How to configure .NET Framework security settings and how to deploy a .NET Framework application[^] and read the related links at the bottom for more information and alternatives (like creating and removing the code group using the caspol.exe utility).Microsoft MVP, Visual C# My Articles
Sounds good. Since my application is primarily for intranet use, I'm thinking I could just install dotnetfx.exe on each machine and then call caspol appropriately to set the intranet zone CAS security. Of course these steps would be in one deployment package. I still have to determine how much 'trust' to give the intranet zone. One thing that is still confusing me is that even if I strong name the controls and set up a code group in CAS for that SN and give the code group a bloated permission set, unless I set the zone security, the control still won't load. It's like the zone security is overriding the code group. Or maybe the control code is winding up in another code group that correlates to the zones.. I'm a bit leery of giving the intranet zone an elevated trust level and wish I could just elevate trust for my application's assemblies. Any thoughts on this? Tim
-
Sounds good. Since my application is primarily for intranet use, I'm thinking I could just install dotnetfx.exe on each machine and then call caspol appropriately to set the intranet zone CAS security. Of course these steps would be in one deployment package. I still have to determine how much 'trust' to give the intranet zone. One thing that is still confusing me is that even if I strong name the controls and set up a code group in CAS for that SN and give the code group a bloated permission set, unless I set the zone security, the control still won't load. It's like the zone security is overriding the code group. Or maybe the control code is winding up in another code group that correlates to the zones.. I'm a bit leery of giving the intranet zone an elevated trust level and wish I could just elevate trust for my application's assemblies. Any thoughts on this? Tim
Don't elevate the Intranet_Zone code gorup. Instead, create a new code group using the Url to your assembly, or the strong name (and assemblies should always be strongly named - there's just no excuse for not strongly naming them and it gives you many more benefits than not). Other assembly evidence doesn't work (at least in 1.0 - I reported this to Microsoft a long time ago back in the 1.0 beta days - or perhaps early after it was released), and the Site evidence doesn't always work correctly, although I haven't been able to determine why. IEExec.exe only gathers site evidence (evidence about the site where the assembly is hosted) and strong name evidence. I've sent you a class from the installer we use in the Windows Installer package.
Microsoft MVP, Visual C# My Articles
-
Don't elevate the Intranet_Zone code gorup. Instead, create a new code group using the Url to your assembly, or the strong name (and assemblies should always be strongly named - there's just no excuse for not strongly naming them and it gives you many more benefits than not). Other assembly evidence doesn't work (at least in 1.0 - I reported this to Microsoft a long time ago back in the 1.0 beta days - or perhaps early after it was released), and the Site evidence doesn't always work correctly, although I haven't been able to determine why. IEExec.exe only gathers site evidence (evidence about the site where the assembly is hosted) and strong name evidence. I've sent you a class from the installer we use in the Windows Installer package.
Microsoft MVP, Visual C# My Articles
The URL evidence is working, I still can't get it to work with the strong name. I've set up two code groups at the enterprise level. One based on URL evidence and one on a strong name key. The control is signed with the strong name. For some reason, the control is only showing up as meeting the URL evidence. I'm testing it by hitting 'evaluate assembly' in the .NET security tool, runtime security policy tree node and typing in the url to my assembly. I can't really understand why it's not thinking the assembly is meeting the strong name evidence. It does think it meets the strong name evidence if I select the assembly a different way in the tool, i.e. by browsing to the .dll. Hmm.... Well the URL evidence will work for me. It'll just make my rollout more of a pain.. because of our deployment methodology (we don't host software -- so I would have to let sysadmin type people specify these URLs somewhere in configuration - yuck).. :/ Have you noticed weirdness with the strong name evidence when doing these controls? Even if I specify levelfinal for the codegroup, it still doesn't recognize it.
-
The URL evidence is working, I still can't get it to work with the strong name. I've set up two code groups at the enterprise level. One based on URL evidence and one on a strong name key. The control is signed with the strong name. For some reason, the control is only showing up as meeting the URL evidence. I'm testing it by hitting 'evaluate assembly' in the .NET security tool, runtime security policy tree node and typing in the url to my assembly. I can't really understand why it's not thinking the assembly is meeting the strong name evidence. It does think it meets the strong name evidence if I select the assembly a different way in the tool, i.e. by browsing to the .dll. Hmm.... Well the URL evidence will work for me. It'll just make my rollout more of a pain.. because of our deployment methodology (we don't host software -- so I would have to let sysadmin type people specify these URLs somewhere in configuration - yuck).. :/ Have you noticed weirdness with the strong name evidence when doing these controls? Even if I specify levelfinal for the codegroup, it still doesn't recognize it.
Strong name should work, but there's nothing wrong with URL evidence. One way that I roll-out code groups (though I typically use the Machine policy) is to write an installer class like I mentioned, wrap that as acustom action in an MSI package, and add that to our domain's group policy so that it installs on machines that the GP covers. When written correctly, this makes it easy to roll-out your code group. This procedure is also recommended by Microsoft. Of course, this would only work if the .NET Framework was installed, but that's a given. You could always have the install detect if it's there and install regardless, or include that dependency on the .NET Framework as a Launch condition. The user would not be presented with an error in either case.
Microsoft MVP, Visual C# My Articles
-
Strong name should work, but there's nothing wrong with URL evidence. One way that I roll-out code groups (though I typically use the Machine policy) is to write an installer class like I mentioned, wrap that as acustom action in an MSI package, and add that to our domain's group policy so that it installs on machines that the GP covers. When written correctly, this makes it easy to roll-out your code group. This procedure is also recommended by Microsoft. Of course, this would only work if the .NET Framework was installed, but that's a given. You could always have the install detect if it's there and install regardless, or include that dependency on the .NET Framework as a Launch condition. The user would not be presented with an error in either case.
Microsoft MVP, Visual C# My Articles
Excellent advice. Thanks a lot. I have one other small thing that I'm wondering whether you've come across since you seem to have done this type deployment before. In a test control I'm playing with now as part of a prototype, I try to open up a tcp connection to my app server using the tcpclient class from the FCL. I have done tons of tcp so this should be trivial for me ( :> ). Anyway, when I run my control in a windows form the tcp request behaves like I expect i.e. I see the syn - syn ack - ack - and then my push and receive from the server. However, when I run the control when embedded in a web page (it's got full trust and full socket access in the CAS policy), I get the syn - syn ack - syn, but then for some reason a request is being made to the server on port 445 which is the Microsoft directory service port. My push (my request) is then waiting like 2 minutes for something to come back on port 445 before my request goes through. I can see all this in ethereal but have no idea why the control or the framework is running a request to port 445. Have you come across this? Tim
-
Excellent advice. Thanks a lot. I have one other small thing that I'm wondering whether you've come across since you seem to have done this type deployment before. In a test control I'm playing with now as part of a prototype, I try to open up a tcp connection to my app server using the tcpclient class from the FCL. I have done tons of tcp so this should be trivial for me ( :> ). Anyway, when I run my control in a windows form the tcp request behaves like I expect i.e. I see the syn - syn ack - ack - and then my push and receive from the server. However, when I run the control when embedded in a web page (it's got full trust and full socket access in the CAS policy), I get the syn - syn ack - syn, but then for some reason a request is being made to the server on port 445 which is the Microsoft directory service port. My push (my request) is then waiting like 2 minutes for something to come back on port 445 before my request goes through. I can see all this in ethereal but have no idea why the control or the framework is running a request to port 445. Have you come across this? Tim
Can't say I have. It almost seems like it's trying to authenticate the request, if that helps any.
Microsoft MVP, Visual C# My Articles
-
Can't say I have. It almost seems like it's trying to authenticate the request, if that helps any.
Microsoft MVP, Visual C# My Articles
Actually it was trying to read a configuration file from the server and was coming upon a deadlock in System.Configuration. A bug in .NET. Oh well! Check out this article: http://discuss.develop.com/archives/wa.exe?A2=ind0209a&L=advanced-dotnet&T=0&F=&S=&P=4447 Anyway it's a real pain. It applies to probably any tcp activity done in a user control including remoting with TcpChannel or just plain old tcp sockets like I am using. The suggested workaround is somewhat ok, but it's a cludge! So as another workaround, I just wrote a small managed C++ dll that wraps winsock and used it to send and receive my tcp data (thereby bypassing the framework Socket class). This is working much better for me.. Tim
-
Actually it was trying to read a configuration file from the server and was coming upon a deadlock in System.Configuration. A bug in .NET. Oh well! Check out this article: http://discuss.develop.com/archives/wa.exe?A2=ind0209a&L=advanced-dotnet&T=0&F=&S=&P=4447 Anyway it's a real pain. It applies to probably any tcp activity done in a user control including remoting with TcpChannel or just plain old tcp sockets like I am using. The suggested workaround is somewhat ok, but it's a cludge! So as another workaround, I just wrote a small managed C++ dll that wraps winsock and used it to send and receive my tcp data (thereby bypassing the framework Socket class). This is working much better for me.. Tim
Tim Kohler wrote: So as another workaround, I just wrote a small managed C++ dll that wraps winsock and used it to send and receive my tcp data (thereby bypassing the framework Socket class). This is working much better for me.. Good, but this will require FullTrust permissions since MC++ assemblies are implicitly unverifiable (at least till .NET 2.0, and only when you create a pure managed assembly). That may not be a problem, but you've been warned. :)
Microsoft MVP, Visual C# My Articles