Now that I have your attention, you are probably asking yourself, "what possibly could these subjects have in common?” Obviously, WF and transparency make since, but what about Interop and baby. This posting is the product of being hit with way to much within the past four weeks. In starting the month off right, my wife gave birth to our new son, Nathan! And to brag about my wife here a little, she was able to give birth at home with zero drugs...Strong woman, huh? So now I am in charge of cleaning after and explaining to our two year old daughter where he came from and that he will not be stealing all of her attention.
The past couple of weeks my latest project led me down a dark dark road that I have not been down in years. No it was not something out of a horror movie but close... VB6! Ya feel me? Now you know when I say years, I mean years, 7-8 to be exact. There was a client who needed some enhancements built on top of a current application built in VB6. I can still read VB6, but it is kind of like that friend that everyone has who is from a different country, and who mentions that they can still understand when they hear their native language spoken, but really cannot remember how to communicate back or even write it on paper...Same boat. Because of this and the customer’s requirements, they both led me down the track of interop. To learn more about my findings on .net to VB6 interop read on. If you don’t, I totally understand, and possibly can’t blame you because I do not ever plan on having to use or talk to VB6 again.
In this case, the client was a wood mill that weighed the wood on trucks when they entered the mill. There are different "offload points" for the different categories of wood, pine pulp chip, etc. What the client needed was a traffic light manager that could start queuing the trucks in the mill based on the different types of wood they were carrying. The current VB6 app weighed the wood, so I figured that I could embed a queuing manager inside of it. More importantly, I could use WF!
After it was all said and done, I had built the following workflow. It was relatively simple to build and I also showed it to the client so he could verify the business flow at each step.
- The first step was to change the traffic light to red, so that trucks would not enter the mill if there were any issue later. A CallExternalMethod activity was used here.
- Next step is to start polling the mill to see what category of wood trucks already in the mill were carrying. A while activity solved the solution. It kept polling until a property was set to false.
- Now it was time to start controlling the lights based on the categories of wood in the mill. A sequence activity was used so I could sequence the core of the business logic within the while activity. To check what was in the mill, another CallExternalMethod was used.
- After checking the mill, the workflow needs to determine if it will set the light to red or green. The IfElse Activity was used. If the light that needed to be set was already on, nothing was done. Again another IfElse activity was nested with CallExternalMethod activities embedded, so that they could call the host to change the lights. I forgot to mention that the lights were hooked up, via comm. Ports and certain character codes were sent to the lights to control them.
- Finally, a Delay activity was needed to control how often the mill should be polled for categories.
After I had created my WF host and everything ran correctly in .Net it was time to build the interop wrapper. By right clicking in Visual Studio, on my WF Project, selecting Properties, clicking the Application Tab and then clicking the “Assembly Information” button, I checked the “Make assemply COM-Visible”. While still in the properties, I clicked the Build tab and checked “Register for COM Interop”. After rebuilding the project, it was ready to be deployed. After copying the compiled assembly and .tlb file to the server running the VB6 app, I ran the REGASM.exe command… c:\windows\microsoft.net\Framework\v2.0.50727>Regasm C:\folder\Queue.dll /codebase /tlb:Queue.tlb. This allowed me to reference the COM wrapped WF code within VB6. I will stop here because even though the workflow worked, meaning some of the activities executed and even raised events back to the VB6 app, which was running the WF host, I did have some issues with the While activity, but not a WF or even .Net issue. The only thing I could think of was VB6 is single threaded. I guess I could have used a VB6 timer object, but at this point it was time to move on.
The good news about moving on is that I was told later that a separate process was needed to actually control the lights, but VB6 still needed to know what categories were in the mill. This meant that no interop was needed and my workflow could run exactly the way it was supposed to run. I still needed logic to poll the mill and check for wood categories, inside VB6, but because I used HandleExternalMethod Activites, I was able to reuse that functionality for interop. Because I had all the trouble before when trying to do this with WF, I was able to implement the functionality through .Net to VB6 with little to know problem. And if the functionality changed, because it was implemented within the same service, controlling the lights within WF and checking the mill within interop, the code was totally reuseable.
Something that I wanted to share about WF transparency is this. I friend of mine who is somewhat technical, stopped by while I was working on this project. I wanted to test WF transparency again to him. I took the services that WF was using and wired them up within a console app. I then asked him to view the console app running and I showed him how and why the lights were changing. I then showed him my service and asked him if he could follow the code. When I saw we were not getting anywhere to fast, I showed him the workflow I had built. He then started telling me exactly what the workflow was doing correctly. Event though this is a simple example, it shows the power of WF and how it makes software development multi-dimensional.