I like to run IE with ActiveX for the internet set to administrator approved. This allows me to run things such as windows update, media player, macromedia flash, without all the other activex possibilities to worry about ;) This is the reg file I use to set the administrator approved controls
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\AllowedControls]
;
; ShockWave flash
"{D27CDB6E-AE6D-11CF-96B8-444553540000}"=dword:00000000
;
; MediaPlayer ( old verion, hence commented out)
;"{22D6F312-B0F6-11D0-94AB-0080C74C7E95}"=dword:00000000
;
; Media Player 10
"{6BF52A52-394A-11d3-B153-00C04F79FAA6}"=dword:00000000
;
; Microsoft Update
"{6E32070A-766D-4EE6-879C-DC1FA91D2FC3}"=dword:00000000
;
; Microsoft Tranfer Manager
"{82774781-8F4E-11D1-AB1C-0000F8773BF0}"=dword:00000000
;
; ("W3C-DOM XML Document 6.0 (Apartment)")
"{88D96A05-F192-11D4-A65F-0040963251E5}"=dword:00000000
I was reading
Richard Tallent's blog entry about a CAPS lock problem which turned out to be a keyboard scan mapping problem, and it reminded me of one of those things that's always been on my virtual TODO list to fix in regard to the Toshiba M200.
The problem with the M200 is there is no left windows key, instead it's up the top right of the keyboard. They also have moved the ` ~ key to the bottom of the keyboard where the windows key would normally go.
So I decided to put a windows key back on the left of the space bar. but that meant I'd have to remove the right windows key or something else would have to go. Well I decided that the Insert key was the most useless key on my keyboard, so that could be the windows key, but it was on the wrong side of the space bar. ah ha !! The ` ~ key is really a pain where toshiba put it. I can never find it (well I can but I really do have to search).
So my solution was to physically swap the `~ key with the Ins key. You just pry the keys up from the back and they snap off, and just press them back in place and they snap back on (BTW: nice to see Toshiba uses metal brackets unlike some cheaper keyboards on laptops these days) Now the Insert key is on the left of the spacebar.
The final part is to swap the mappings, making the Insert key, which is really the old `~ key the windows key, and the fixing the new `~ key mapping. This reg file will do that trick:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,29,00,52,E0,5B,E0,29,00,00,00,00,00
Last month when I went to update my MSDN DVD collection, I faced the rude awakening that the "
New and Removed Products" page was seriously broken. The search doesn't go past October 2005.
I asked in the private forums, no response. I asked MSDN online concierge.. they couldn't tell me. I even asked our own
Frank Arrigo, and yet still no response.
<black helicopters>
Is this some kind of perverted conspiracy ? Is it so MS can remove products hoping you won't realize until it is too late ?
</>
What ever the reason, it's a real pain in the you know where. It would be nice to know which DVD's have products on them you might want to or actually NEED to archive.
In Visual Studio 2005, we typically have a lot of generated code per application. Strongly typed datasets are a classic example of this. One difficulty of having generated code parts of a class alongside manually written parts has been removed due to the use of partial classes and physical separation of these parts into different files. The challenge now lays in how do you have these two parts interoperate with each other. How does code in the generated part call into code in the human written part ? VB solves this with the use of intra-class event coupling.
The problem :
Let's take an example of a Customer class with an Name property As String, and this code is generated for you. Now assume you want to intercept the property Set and do some complex validation of the value.
'generated code
Partial Class Customer
Private m_Name As String
Public Property Name() As String
Get
Return m_Name
End Get
Set(ByVal value As String)
'TODO: notify any custom code
m_Name = value
End Set
End Property
End Class
' human written code
Partial Class Customer
'TODO add code to intercept the Name being set
End Class
Solutions to the problem :
Some approaches taken to this kind of issue is to always provide stubs and use attributes etc to mark those stubs. this removes the separation of generated code by file, rather the generated code is interweaved with your own code and placeholders are inserted for you to work with. This approach works well except that clean separation is lost, and it requires more work on the code generation tools to parse your code. Another approach that can be taken is to have conditionally compiled code that checks to see if a function exists and compiled accordingly. And yet another approach that can be taken is to use inheritance and overridable methods.
The inheritance approach falls down very quickly when you have complex object models and factory methods. Admittedly this could be less fragile today due to the use of generics, but still it brings with it an un-due amount of complexity. Conditionally compiled code on the other hand falls down around inheritance, especially when we have separation of code into different assemblies. So of those three approaches I've mentioned, today in Visual studio, the method stubs approach is the preferable one. But there is one more to consider …
The approach you can take in VB is to use intra class events. I'll drill into how these actually work under the covers in a minute, but for now it's easiest to picture them as method stubs that are linked by the compiler. So these in fact work basically the same as using the method stub/placeholder approach, but also provide clean separation of generated code and user code on a per file basis.
And the nice thing is in VB they work today, straight out of the box in Visual studio 2005.
How intra class events work :
Intra class events are the same as any event in VB. The "magic" part is how the compiler injects code to wire these up. Via declarative programming, the VB compiler will inject the code necessary to wire up the generated code and the human written code. You can see this today in the Strongly Typed Datasets. In VB you can handle the CustomerRowChanging event inside the partial class for the CustomerTable. (note: today in C# you cannot)
Let's expand the example we had from above:
'generated code
Partial Class Customer
' add an event for the name changing.
' The ValidationEventHandler is just an example of the type of event we could use here
' It passes in old value, new value, property name, and a Cancel argument.
' the NewValue and OldValue are as type T, which in this case is String.
Private Event NameChanging As ValidationEventHandler(Of String)
Private m_Name As String
Public Property Name() As String
Get
Return m_Name
End Get
Set(ByVal value As String)
Dim evArgs as New ValidationEventArgs("Name", Me.m_Name, value, False)
RaiseEvent NameChanging( Me, evArgs)
If not evArgs.Cancel Then
m_Name = evArgs.Value
End If
End Set
End Property
End Class
' human written code
Partial Class Customer
Public Sub Me_NameChanging(sender As Object, ev As ValidationEventArgs) Handles Me.NameChanging
'TODO validate the values via the ev parameter's NewValue and OldValue properties
' and set ev.Cancel = True to cancel the property set.
End sub
End Class
The above example is a simplified use of events to validate the setting of the Name property. How this actually works is the VB compiler recognizes the Handles declarative syntax and wires the event handler into the object constructors If you wanted to try to achieve the same in C# you could manually wire up the event handlers in your own constructor, however that approach requires that the generated code does not have any constructors, which is why you can't really do this in c# with strongly typed datasets as the generated code there does provide constructors and needs to. With VB however, because the declarative syntax tells the compiler to do this wiring, the compiler gets to act as the glue between the generated code and your custom code.
The cost
The old saying there's no such thing as a free lunch tends to hold true here. the cost however is very minimal. You may for example want the NameChanging event to be public in your object model, so really there is not overhead. In other cases, the cost basically is an IntPtr slot for each declared Event, although you can minimize that via collection for all the events. should you actually choose to wire up the event then that IntPtr will point to a multicast delegate which will store a function pointer and a pointer to self. The invocation is also minimal overhead, as it is basically calling delegates in a list. So memory or preformance issues are pretty insignificant, and can actually be favorable compared to inheritance or method stub approaches.
One concern you might "one day" need to be aware of is that event invocation does not guarantee the order the listeners will be invoked in the cases where there are more than one listener to the same event. That being said, the behavior is FIFO (first in first out), and as your intra class events are wired in at the start of the constructor, they are always first in, hence are today first to be notified.
Should that ever change, or should you require further control on the order of the events invocation, you can in VB.NET use the Custom Event syntax which let's you write the Raise method as well as modify the Add and Remove methods,
Public Custom Event SomeEvent As EventHandler
AddHandler(ByVal value As EventHandler)
'TODO
End AddHandler
RemoveHandler(ByVal value As EventHandler)
'TODO
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
' ensure events are raised the way you want them to be in here
End RaiseEvent
End Event
The VB syntax shown here is as per the MSIL specification, and corresponds to the MSIL of .addon, .removeon, and .fire.
In C# however they only support the .addon and .remove on, so you have to write a separate method to try to simulate the .fire. Typically the OnXXX pattern is used for this, although great care and code analysis really needs to be run to ensure all event invocation then goes via the OnXXX method. The .fire method provides an nicer encapsulation of this.
Conclusion
Hopefully you can now see, or will after a bit of experimentation with the above concepts, that intra class events provide a flexible and powerful way of wiring up generated code with manually written code. And here once again we have VB leading the way with modern concepts such as declarative programming, and also with full specification implementation of things such as custom Events. Clearly C# has much catching up to do in these areas.
So next time you start to build your business object layers, or any code that may center around code generation, then think about your choice of language. It obviously makes a lot of sense to use VB for these kinds of applications as only VB today provides such great coupling via intra class event handling.