February 2008 - Posts

One of the cool new features in VSTO v3 is interoperability between VSTO and VBA code in your Office document. The basic steps are pretty simple:

  1. Create a Word document with some VBA code. It doesn't really matter what it just as long as it has some code.
  2. Save the document as a macro enabled document so it has the DOCM extension.
  3. Create a new VSTO project.
  4. Instead of new blank document base it on the just created document.
  5. In the property sheet set the EnableVBaCaller property to true.
  6. Add a public function to the ThisDocument class.

Setting the EnableVBaCaller property actually adds some an extra property to the existing VBA code with the name CallVSTOAssembly. This CallVSTOAssembly property is basically a proxy to the ThisDocument object letting you call all public functions from your VBA code.

It works pretty well except for a few things.

Every time you compile and run the Word document opened is overwritten so any changes to the VBA code there are also overwritten. Now this is expected behavior but in this case a bit annoying as this is the only place you can edit the VBA code. In fact from within VS2008 there is no way to get to the VBA code at all. So this means opening the project version of the Word document outside if VS2008 using Word itself and copy and pasting all code changes made. And if you do this you need to make sure the document isn't open in VS2008 or Word will complain loudly Sad.

Another problem I had was with the CallVSTOAssembly property. With all the cut and paste actions of VBA code I actually screwed up and added the code for a CallVSTOAssembly property from another solution. The result was no complaints or warnings but a CallVSTOAssembly property looking for the wrong class, actually the wrong namespace. And the result was that all interop came to a grinding halt. As the expected CallVSTOAssembly property was there it took me a while to realize that the namespace was wrong. So if you find that the CallVSTOAssembly property doesn't seem to work and offers no IntelliSense when editing your VBA code just remove it and toggle the EnableVBaCaller to false and back to true to have VS2008 reinsert the correct code Smile.

See http://msdn2.microsoft.com/en-us/library/bb386306.aspx for more info in VSTO VBA interoperability.

Enjoy!

with no comments
Filed under: , , ,

Next week Thursday, March 6th, I will be doing two talks about VSTO for VBA developers at the Nationale Office Dag in Ede.

Check the website for more info about the event.

Hope to see you there Smile

with no comments
Filed under: , ,

Last week Mick introduced me to TeamViewer and I found it remarkably easy to use.

The client doesn't have to install any software just download the client version and you are good to go. It also includes a nice file transfer option we used to rapidly transfer some large files. TemViewer also supports a presentation mode. Haven't tried it yet but from what I read you can use it to do remote presentations. I don't know if this includes sound we just used Skype for sound and that worked just fine.

with no comments
Filed under:

On May 3rd GAMTUG, the Galway Area Microsoft Technology Users Group, is organizing the DDD Ireland and I will be there doing a session on Workflow Foundation in a SOA architecture and a seconds session about using the new VSTO version 3 features that ship with Visual Studio 2008.

 

Check out the video for a preview


with no comments
Filed under: , , , , ,

One thing I noticed right away when I installed Windows Vista is that it takes up lot of disk space. Sure I installed the Ultimate edition so I wasn't expecting a very slim install but still it used a lot more disk space than I expected. My setup is a 50 Gb C drive for Windows Vista and program files while leaving a 140 Gb D drive for data. That may seem a lot but as I develop using VMware I use up quite a bit of it with 4 virtual machines. Anyway the practice of using a virtual machine for all software development is something I can recommend!

Anyway back to the disk space usage. When I started I was surprised but everything went well. But the C drive kept on filling up even though I wasn't installing new software and I kept the temp directory in check. Yesterday the bar the Explorer indicating how full the disk was even turned red so some action was needed. I fired up WinDirStat, a great utility for finding where your disk space went and reported 14Gb as <Unkown>. That is quite a portion of a 50 Gb disk, a whoping 28%, so I decided to focus on that first. It turns out it was in use by Windows Vista System Restore.

How to check? Well you need to start an command prompt with administrator privileges and from there do "vssadmin list shadowstorage" which will tell you how much disk space is in use by System Restore and what the maximum was. Turns out my machine didn't have a maximum so it just kept on growing; no wonder that I was running low in disk space Sad.

Fixing the problem is also done using vssadmin with the "Resize ShadowStorage" option. I did and now I can keep working just fine again Smile.

More info on vssadmin can be found here although Windows Vista doesn't seem to understand all listed options.

Enjoy your disk space!

You probably heard that Visual Studio 2008 lets you select the target framework version so you can use it to compile .NET 2.0 applications. I suspect you also heard about all the new cool features VB 9 includes like stuff like LINQ etc. Just in case you didn't make sure you read up on Overview of Visual Basic 9.0 by Erik Meijer, Amanda Silver, and Paul Vick.

And you probably assumed all those cool new features would only work if you where targeting the 3.5 framework, I know I did Smile. Well guess again! Some of these features are only syntactic sugar completely handled by the VB compiler.

Some of the features you can use are implicitly typed variables, both with simple and complex types.

Dim aValue = 1

'aValue = "Demo"

Console.WriteLine(aValue)

Note that assigning a string to aValue produces a compile error!

Dim home As New Country With {.Name = "the Netherlands"}

 

Another nice thing you can use is the new short notation for nullable types.

Dim aNullableInt As Integer?

aNullableInt = Nothing

 

And best of all is Lambda expressions! All they are is syntactic sugar and the compiler can take care of them. So much nicer than before Smile

Dim countries As New List(Of Country)

countries.Add(home)

countries.Add(New Country With {.Name = "France"})

countries.Add(New Country With {.Name = "Belgium"})

Dim found = countries.Find(Function(c As Country) c.Name = "France")

 

 

And just to show what is actually happening behind the scene below is the code as decompiled using Reflector.

<StandardModule()> _

Friend NotInheritable Class Module1

' Methods

<DebuggerStepThrough, CompilerGenerated> _

Private Shared Function _Lambda$__1(ByVal c As Country) As Boolean

Return (c.Name = "France")

End Function

 

<STAThread()> _

Public Shared Sub Main()

Dim aValue As Integer = 1

Console.WriteLine(aValue)

Dim VB$t_ref$S0 As New Country

VB$t_ref$S0.Name = "the Netherlands"

Dim home As Country = VB$t_ref$S0

Dim countries As New List(Of Country)

countries.Add(home)

VB$t_ref$S0 = New Country

VB$t_ref$S0.Name = "France"

countries.Add(VB$t_ref$S0)

VB$t_ref$S0 = New Country

VB$t_ref$S0.Name = "Belgium"

countries.Add(VB$t_ref$S0)

Dim found As Country = countries.Find(New Predicate(Of Country)(AddressOf Module1._Lambda$__1))

End Sub

End Class

 

Note that the compiler generated a Lambda function in this case because I used a constant string in the search filter. If I had used a variable it would have generated the required closure as an embedded type.

Enjoy VB9!

with 2 comment(s)
Filed under: , ,

Looking for more information about VS2008 and .NET 3.5?

I suspect you might just be as there is a ton of new functionality and with the pace of everything coming out it isn't likely that you know it all Smile

To help learn the new stuff Microsoft has put a Visual Studio 2008 and .NET Framework 3.5 training kit together with lots of labs and presentations. Just go through the list and check what you would like to know more about.

You can download the trainings kit from here.

Enjoy!

 

with 2 comment(s)
Filed under: , , , , , , ,

Using a ReceiveActivity is a great way of exposing a workflow via a WCF proxy.

Get started by creating a new project based upon "Sequential Workflow Service Library". This is found in the WCF projects node instead of the Worflow projects node!

Create a service interface, mine is nice and simple and add a few ReceiveActivity to the workflow and hoop up the service interface to the activities. No big deal so far and we can test things by just pressing F5 and having the WCF Test Client. Actually you can only call functions that are hooked up to an ReceiveActivity with the CanCreateInstance set to True so the WCF Test Client might not be all that useful here if you use multiple ReceiveActivity that are part of a single workflow or conversation.

Next step is to create a simple console application as a client with the following code:

Sub SimpleDemo()

Dim proxy As New ServiceReference1.DoStuffClient

Console.WriteLine(proxy.AskQuestion("Is this cool?"))

proxy.AllDone()

End Sub

 

This code works just fine Smile until we decide to split it up and recreate the WCF proxy object for part two like this Sad:

Private Sub Part1()

Dim proxy As New ServiceReference1.DoStuffClient

proxy.GetStarted("Maurice")

Console.WriteLine(proxy.AskQuestion("To be or not to be?"))

End Sub

 

Private Sub Part2()

Dim proxy As New ServiceReference1.DoStuffClient

Console.WriteLine(proxy.AskQuestion("Is this cool?"))

proxy.AllDone()

End Sub

 

In this case the second proxy object doesn't work at all and we get a FaultException with the message "There is no context attached to incoming message for the service and the current operation is not marked with "CanCreateInstance = true". In order to communicate with this service check whether the incoming binding supports the context protocol and has a valid context initialized."

So what gives? Well the WCF service needs to know which workflow the request needs to be routed to and uses the WorkflowInstanceId to do so. When you create a proxu and do the first call this WorkflowInstanceId is automatically added and resent with the next request. So we need to retrieve this WorkflowInstanceId and, when we create the second proxy object, add it again. Doing so turns out to be pretty simple and only takes a few extra lines of code:

Private _instanceId As String

 

Private Sub Part1()

Dim proxy As New ServiceReference1.DoStuffClient

proxy.GetStarted("Maurice")

Dim contextManager As IContextManager = _

proxy.InnerChannel.GetProperty(Of IContextManager)()

Dim context As Dictionary(Of String, String) = _

contextManager.GetContext()

_instanceId = context("instanceId")

Console.WriteLine(proxy.AskQuestion("To be or not to be?"))

End Sub

 

Private Sub Part2()

Dim proxy As New ServiceReference1.DoStuffClient

Dim contextManager As IContextManager = _

proxy.InnerChannel.GetProperty(Of IContextManager)()

Dim context As New Dictionary(Of String, String)

context.Add("instanceId", _instanceId)

contextManager.SetContext(context)

Console.WriteLine(proxy.AskQuestion("Is this cool?"))

proxy.AllDone()

End Sub

 

Basically what we need to do is retrieve the workflow instanceId from the context that is returned with the first call and save that. Next time we create a new proxy object we need to store the same instanceId in the request context before we actually use it and we are good to go Smile Setting the instaceId is actually done through a ClientContextProtocol object which is returned as an IContextManager inside of the channel properties. Check the bold lines in the previous code sample.

So why is this so important?

Well one of the most powerful features of Workflow Foundation is its capability to have long running workflows. Now long running workflows would not be very useful if the client application needs to keep its proxy alive for as long as it need to communicate with the workflow. Guess that would make "long running" a very relative thing. But with this technique all the client has to do is save the workflow instanceId somewhere, perhaps a database table, and it can reconnect to the same workflow at a later point in time.

Enjoy!

with 3 comment(s)
Filed under: , , , , ,

If you are expecting a link to the download I am sorry but you are going to be disappointed Sad

Why? Because it just isn't available yet!

I can already hear you saying "But it must be coming any day now, right?"

Wrong Sad

Yes, I just heard from Hugo that there are no current plans for releasing a new service pack for the very simple reason not enough people are asking for it.

Come gain, why was that?

Because not enough people are asking for it!

So click in this link and vote for another SQL Server service pack!

Enjoy!

with 1 comment(s)
Filed under: , , , ,