I guess Robin and I inspired her on Monday when we had dinner together. Yes folks, Deborah Kurata (VB MVP) is finally spilling her technical heart out on her new blog! Time to update your RSS readers….
Neat-o title too.
Enjoy!
by Alex Feldstein (noreply@blogger.com) at July 02, 2009 12:51 PM
Visual Studio 2010 Beta1 provides a great feature called “Navigate To”. You can find this feature under the “Edit” menu or use the keyboard shortcut “Ctrl + COMMA” to bring up the “Navigate To” dialog. This feature provides search-as-you-type support for files, types, and members to match the input string. Following is a snapshot of the “Navigate To” dialog:
Here are some summaries for this feature:
1. If the search string contains uppercase characters, the search is case-sensitive; otherwise not.
2. The white space between characters will be treated as an 'and' relationship.
3. The search does not support wildcard.
This feature becomes extremely handy when your solution/project is complex. The search result comes very quickly even for large solutions.
You can find more information about this feature at the following link: How to: Search for Objects, Definitions, and References (Symbols).
Also, a walkthrough is provided: Walkthrough: Quick Search for Files and Symbols in Visual Studio 2010.
Enjoy!
I just released 3 new videos onto the VB Dev Center starting a new series on how to do WPF data binding with Entity Framework using Visual Studio 2008 Service Pack 1. This is a “no frills” WPF series that focuses on data so you won’t see any other tools used besides Visual Studio 2008 SP1 and no flashy animations.
#1 | How Do I: Get Started with Entity Framework in WPF Applications?
#2 | How Do I: Build a WPF Data Entry Form Using Entity Framework?
#3 | How Do I: Create a WPF Lookup Combobox using Entity Framework?
The videos are a bit longer than your normal 5-minute “How Do I” videos but I tried to keep them short by re-using the data access layer I build in the first one. I hope this doesn’t confuse people. Believe me when I say this will get a lot better, especially tooling-wise, in Visual Studio 2010. But this is a good introduction to building WPF data apps against Entity Framework with the version of Visual Studio that is available now! :-)
Enjoy!
by Alex Feldstein (noreply@blogger.com) at July 01, 2009 11:31 PM
I’m happy to announce that my WPF Localization paper went live a couple of days ago on CodePlex. You can find it here:
http://wpflocalization.codeplex.com/ (click on Downloads – it’s published only as PDF <shrug>)
I’ve been working on this document for quite some time and those that follow this blog and twitter probably already know that it’s been an interesting journey. It’s a very long document as it covers a whole range of topics from some localization overview, the basic .NET localization infrastructure to the actual localization approaches using LocBaml and Resx resources as well as couple of custom approaches using custom markup extensions and attached properties. There are a lot of topics covered, and for once though it was actually supposed to be this long based on the article specs on the contract.
The reason for the length is primarily that WPF localiztion doesn’t just take a single path. Unlike previous Windows desktop technologies that preceded it, WPF does not have one clear path to localization and no direct tool support in Visual Studio or Blend. This means the choices for localization are left up to the developer to explore and figure out.
The two major choices available are using LocBaml for localizing XAML resources or using the more traditional Resx approach. LocBaml focuses on using the XAML document itself as a resource store and allows for exporting of these XAML resources for localizations after development is complete. The rigid LocBaml approach lends itself to applications that are completed and won’t change much (yeah right – is there really such a thing?) but is not a good choice for applications that need to be incrementally localized. Resx provides better tool integration in Visual Studio with support for resource editing right in Visual Studio as well as the ability to create strongly typed resource classes from Resx resources. However, there’s no direct designer support for the locailzation content which means you manually have to hook up resource keys to properties of elements or at the very least assign some sort of marker property so a custom extension can map resources to properties. For WPF accessing Resx resources involves the manual process of mapping resource ids to XAML elements for binding which is more work up front compared to LocBaml but allows for more flexibility when updating applications at a later point. The Resx approach also has number of options available. The simple x:Static binding markup extension makes for easy bindings of strongly typed resources to properties using simple, built-in binding syntax. For more control custom markup extensions or attached properties can be used to provide custom binding to Resx resources.
The LocBaml approach is interesting in that it defers localization until the end of a project, but in its current form with the limited tool support in LocBaml itself and lack of integration the process of localization is very fragile – it’s very easy to break the CSV localization files and have to start over or roll back to a previously saved version. Using LocBaml it’s definitely worthwhile to back up constantly! Resx offers a more traditional approach and while it’s definitely more work during development I feel that this is the more stable and consistent approach to localization at this time. There are lots of choices available for Resx localization as well beyond what has been discussed in this white paper, many of them interesting and innovative. Lots of innovation around Resx extensions, but nobody seems to be extending LocBaml.
The bottom line is that as a WPF developer you need to spend a little time with each of these approaches to get a feel for what works for you and what works for your localization staff. Choices are good, but arriving at the right one unfortunately can take a little extra time. I’m hoping that the white paper provides a good background on some of the tools available and a better understanding what to look for in any solution you use for WPF localization. I doubt that this is the final word in WPF localization – I suspect at some point there will be some proper tooling provided, but as of the current version of .NET (3.5SP1) and as far as I can see of .NET 4.0 Localization for WPF hasn’t seen a lot of love from Microsoft. <shrug>
I’ve also had the pleasure of working with Michele Leroux Bustamante on this project who did a bang up job on final editing and providing feedback in the course of writing. Michele of course is one of the THE experts in Localization in WPF and I felt honored being asked to help out by writing this white paper and take on the WPF Localization topic.
Anyway, I hope this article will prove useful to developers if for nothing else than putting a lot of the information that is out on the Web for WPF Localization into one comprehensive document that can act as a starter before going off looking at the wide variety of custom solutions available. It’ll be a good place to start and hopefully give you a good idea on what approach is closest to the way you like to work.
Check it out.
Dear Maurice de Beijer,
Congratulations! We are pleased to present you with the 2009 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in Connected System Developer technical communities during the past year.
O yes, I am happy again ![]()
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
The samples below use the Graphics.SetClip function to draw shaped borders in your pictures.
The trick here is to use the CombineMode.XOR enumeration, that forces the drawing to the external part of the shape, like in the samples below.
Playing with the source image below:
Prerequisites
Visual FoxPro 9 and the GdiPlusX library from VFPX
Please make sure that you have the latest version, because this sample may be using some functions that were added or fixed recently.
http://www.codeplex.com/VFPX/Wiki/View.aspx?title=GDIPlusX&referringTitle=Home
Sample 1: Ellipse shape
DO LOCFILE("System.app")
WITH _Screen.System.Drawing
* Get an image file
LOCAL loBmp as xfcBitmap
loBmp = .Bitmap.FromFile(GETPICT())
* Create a Gfx object that will allow us to make the transformation
LOCAL loGfx as xfcGraphics
loGfx = .Graphics.FromImage(loBmp)
LOCAL lnWidth, lnHeight
lnWidth = loBmp.Width
lnHeight = loBmp.Height
* Create GraphicsPath object.
LOCAL loClipPath as xfcGraphicsPath
loClipPath = .Drawing2D.GraphicsPath.New()
* An Ellipse shape
loClipPath.AddEllipse(0, 0, lnWidth, lnHeight)
* Set clipping region to path.
* CombineMode enumeration
* http://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.combinemode.aspx
* CombineMode.Xor - Two clipping regions are combined by taking only the areas
* enclosed by one or the other region, but not both.
loGfx.SetClip(loClipPath, ;
_Screen.System.Drawing.Drawing2D.CombineMode.Xor)
* Fill rectangle to demonstrate clipping region.
loGfx.FillRectangle( .Brushes.White, 0, 0, loBmp.Width, loBmp.Height)
* Save the image to the disk and show
loBmp.Save("Clipped.Jpg", "image/jpeg")
RUN /n Explorer.Exe Clipped.Jpg
ENDWITH
Sample 2: Doughnut shape
DO LOCFILE("System.app")
WITH _Screen.System.Drawing
* Get an image file
LOCAL loBmp as xfcBitmap
loBmp = .Bitmap.FromFile(GETPICT())
* Create a Gfx object that will allow us to make the transformation
LOCAL loGfx as xfcGraphics
loGfx = .Graphics.FromImage(loBmp)
LOCAL lnWidth, lnHeight
lnWidth = loBmp.Width
lnHeight = loBmp.Height
* Create GraphicsPath object.
LOCAL loClipPath as xfcGraphicsPath
loClipPath = .Drawing2D.GraphicsPath.New()
* A Doughnut slice shape
loClipPath.AddEllipse(0, 0, lnWidth, lnHeight * 2)
loClipPath.AddEllipse(lnWidth / 4, lnHeight / 2, lnWidth/2, lnHeight * 4)
* Set clipping region to path.
* CombineMode enumeration
* http://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.combinemode.aspx
* CombineMode.Xor - Two clipping regions are combined by taking only the areas
* enclosed by one or the other region, but not both.
loGfx.SetClip(loClipPath, ;
_Screen.System.Drawing.Drawing2D.CombineMode.Xor)
* Fill rectangle to demonstrate clipping region.
loGfx.FillRectangle( .Brushes.White, 0, 0, loBmp.Width, loBmp.Height)
* Save the image to the disk and show
loBmp.Save("Clipped.Jpg", "image/jpeg")
RUN /n Explorer.Exe Clipped.Jpg
ENDWITH
Sample 3: Star shape
DO LOCFILE("System.app")
WITH _Screen.System.Drawing
* Get an image file
LOCAL loBmp as xfcBitmap
loBmp = .Bitmap.FromFile(GETPICT())
* Create a Gfx object that will allow us to make the transformation
LOCAL loGfx as xfcGraphics
loGfx = .Graphics.FromImage(loBmp)
LOCAL lnWidth, lnHeight
lnWidth = loBmp.Width
lnHeight = loBmp.Height
* Create GraphicsPath object.
LOCAL loClipPath as xfcGraphicsPath
loClipPath = .Drawing2D.GraphicsPath.New()
* Source for the star drawing
* http://www.java2s.com/Code/VB/2D/GraphicsPathDrawwithFillModeWinding.htm
LOCAL lnRadius, lnPi, lnRadian72, n, lnEdges
lnRadius = lnHeight / 2
lnPi = 3.141592
lnEdges = 5
lnRadian72 = (lnPi * 4.0 ) / lnEdges
LOCAL laPoints(lnEdges)
FOR n = 1 TO lnEdges
laPoints(n) = .Point.New(;
+ lnRadius * SIN( n * lnRadian72 ) + lnRadius , ;
- lnRadius * COS( n * lnRadian72 ) + lnRadius )
ENDFOR
loClipPath.AddPolygon(@laPoints)
* Set the Clip Mode to Winding
* ClipMode enumeration
*http://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.fillmode.aspx
loClipPath.FillMode = _Screen.System.Drawing.Drawing2D.FillMode.Winding
* Set clipping region to path.
* CombineMode enumeration
* http://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.combinemode.aspx
* CombineMode.Xor - Two clipping regions are combined by taking only the areas
* enclosed by one or the other region, but not both.
loGfx.SetClip(loClipPath, ;
_Screen.System.Drawing.Drawing2D.CombineMode.Xor)
* Fill rectangle to demonstrate clipping region.
loGfx.FillRectangle( .Brushes.White, 0, 0, loBmp.Width, loBmp.Height)
* Save the image to the disk and show
loBmp.Save("Clipped.Jpg", "image/jpeg")
RUN /n Explorer.Exe Clipped.Jpg
ENDWITH
Notice that the only difference between the code samples is the shape definition !
We just published another community article onto the Visual Basic Developer Center by Maurice de Beijer, Visual Basic MVP, on .NET RIA Services. Maurice explains what they are and how they help you build Silverlight line-of-business applications. Sample source code is included here.
Read Getting Started with .NET RIA Services.
Many thanks to Maurice for donating this article. I’m looking forward to part 2 myself ;-)
Enjoy!
Seven online merchants operating more than 40 Web sites have agreed to pay a $765,000 settlement following an investigation by the New York State Attorney General's office, the AG's office said.
by Alex Feldstein (noreply@blogger.com) at June 30, 2009 06:33 PM
Creating a COM server in VFP is easy, maybe too easy. Check the OLEPUBLIC checkbox or add the OLEPUBLIC keyword to the class definition and you are done. Building a DLL creates a COM server that you can pass to anyone who needs to interface with your application. Using a COM server in VFP is similar uneventful. Instantiate the COM server using the ProgId and call methods on the object, that's it.
The ease of creating a COM server comes at a high price. We VFP developer tend to not think about how our COM server is consumed. Unlike Visual FoxPro, which due too its use of late binding is very forgiving when consuming COM servers, this isn't true for most other environments, especially .NET.
A COM interface consists of a list of method pointers. Each method is accessed by its index number. When .NET imports a COM server, it internally creates a mapping which forwards any call of a named method to the corresponding index in the interface. As long as the interface doesn't change, life is good. Have an updated version of the COM server? Just copy it over the existing DLL or EXE.
Any interface change, however, requires a lot of work for the .NET developer. The COM server needs to be imported again. The InterOp library must be generated anew. Depending on how the COM server is used by the application, the entire application might need to be recompiled. The old COM server has to be unregistered; the new one to be distributed and registered.
That's quite a bit of work, but manageable if you tell your clients about the modified interface. Unfortunately VFP makes it way too easy to introduce interface changes accidentally.
How does VFP generate the interface for a COM server?
For every COM class, VFP loops through all public properties and methods and assigns id values. The first method or property in the PRG file is id 0, the second PEM becomes id 1, and so forth. In other words, the physical order determines the id value. This index is the same one that early binding languages use to call methods and access properties.
It's probably obvious now that there're at least two ways to alter the COM interface in a way which wouldn't have any impact on Visual FoxPro, at all: If you rearrange methods in your source code, the index numbers change. Secondly, any new property or method that you don't mark protected or hidden, is added to the interface, as well.
At least for me the second one is a major source for headache. Visual FoxPro uses an object based approach to protected members where almost any other OOP language uses a class based approach. This renders protected PEMs in Visual FoxPro basically useless, which is why I often don't bother making procedures protected. I do even less so with properties as protected properties in Visual FoxPro make it hard to debug code properly and therefore affect code quality negatively. But that's food for another controversy discussion..
After refactoring code and accidentally changing the interface, I took a defensive approach to make sure this won't happen again. I added a unit test similar to the following one for every COM class in my project. It doesn't detect changes to the order of PEMs, but it's sufficient to make sure I'm aware of interface changes to the COM server:
Procedure Test_CheckInterface
Local loBO
loBO = CreateObject("MyCOM.Server")
This.AssertTrue( "Error loading MyCOM.Server", ;
Vartype(m.loBO)=="O" )
Local laPem[1]
This.AssertEquals( "Wrong number of PEMs", 4, ;
AMembers(laPem, m.loBO, 3) )
This.AssertEquals( "#1", "Method1", laPem[1,1] )
This.AssertEquals( "#2", "Method2", laPem[2,1] )
This.AssertEquals( "#3", "PEM1", laPem[3,1] )
This.AssertEquals( "#4", "PEM1", laPem[4,1] )
EndProc
For every method there's one item in the array created by AMembers. Properties have two entries, one for the getter, and one for the setter. Since I added this unit tests, I made the same mistake several times. But I always spotted the problem before I even prepared the distribution set.
When you download a file with Internet Explorer, the file is tagged as being downloaded from the internet. This has impact on a number of file types. When the file is an EXE and you execute it, you (or more specifically, your users) get a warning:
The publisher could not be verified. Are you sure you want to run this software?
If the file is a CHM help file, the content is never shown. Instead you only see a "Navigation cancelled" error page. For archives the tag is often mysteriously inherited when you extract files. In other words, while this warning might be helpful to prevent malicious code to execute, the system causes a lot of unnecessary support effort for smaller application makers.
Technically, the tag is just an NTFS stream named "Zone.Identifier". This file is actually an INI file specifying the network zone from which the file originates:
[ZoneTransfer] ZoneId=3
Since NTFS streams are only supported on NTFS drives, copying the file to a FAT32 formatted USB stick and pack to the disk effectively removes the security tag. This is neither an obvious, nor a very understandable solution. To an average user this approach sounds much like the famous "if your car stops working get our and back in to fix it" approach.
It would be better to handle this within the application. Providing you have write access to the files, the following program removes the security warnings for all files that match the patter you pass to it:
*============================================================
* Removes the security warning for all files in a directory
* that match the pattern
*============================================================
LParameter tcPattern
Local laDir[1], lnFile
Declare Long DeleteFile in Win32Api String
For lnFile=1 to ADir(laDir,m.tcPattern)
DeleteFile( ;
Addbs(FullPath(JustPath(m.tcPattern)))+;
laDir[m.lnFile,1]+":Zone.Identifier" ;
)
EndFor
To fix your updated EXE and CHM files, you would use:
RemSecurityWarning("*.CHM")
RemSecurityWarning("*.EXE")
You can specify a directory if the current directory is not the right choice.
Passing parameters into a workflow is similar in WF4 as it was in WF3.
In both case a Dictionary<string, object> is passed in when creating the workflow instance object. Alternatively when using the WF4 WorkflowInvoker you can pass it into the Invoke() method.
This is quite simple but I have never been a fan of the very loose coupling here. basically on the outside you have to create a dictionary with as key something inside of the workflow. No compile time checking. No improvement where, unless you consider the somewhat easier unit testing with the WorkflowInvoker.
The actual behavior between WF3 and WF4 is quite different however.
In Wf3 if you pass in a key that doesn’t match up you get a System.Reflection.TargetInvocationException with a System.InvalidOperationException inner exception with the text: “This operation can not be performed at runtime.”. Great help in debugging ![]()
In WF4 on the other hand you get no error at all. The value is just ignored so it is even harder to detect typos. Well I guess not every change can be an improvement. And just in case you where thinking “But a unit test will take care of that right?” keep in mind that workflows tend to be complex and long running things not very well suited to unit testing.
Starting a workflow with a parameter:
Shared Sub Main()
Dim inArgs As New Dictionary(Of String, Object)
inArgs("Name") = "Maurice"
Dim myInstance As WorkflowInstance = New WorkflowInstance(New Sequence1(), inArgs)
myInstance.OnCompleted = AddressOf OnWorkflowCompleted
myInstance.OnAborted = AddressOf OnWorkflowAborted
myInstance.OnUnhandledException = AddressOf OnWorkflowUnhandledException
myInstance.Run()
syncEvent.WaitOne()
End Sub
So where is this Name value actually stored?
Well in WF3 that would have been stored in a property, possibly a dependency property, or a field. The types must match, exactly.
In WF4 the notion of properties and fields is gone. No more dependency properties to tie everything together. So instead we have Variables and Arguments. Basically a variable is just like a variable in a function, only here it holds some value for an activity. Big difference is that a Variable is in scope, i.e. visible, to all nested activities as well. So basically it is a way of sharing state between different activities.
To allows us to pass data into a workflow, or get something out, we need to use an Argument.
In this case I have defined two arguments, the Name to pass into the workflow and the Greeting that will be the result of the workflow.
Getting the result out is done in the OnCompleted delegate. This delegate is passed a WorkflowCompletedEventArgs which in turn contains another dictionary with all out argument.
Shared Sub OnWorkflowCompleted(ByVal e As WorkflowCompletedEventArgs)
Dim greeting As String = e.Outputs("Greeting")
Console.WriteLine(greeting)
syncEvent.Set()
End Sub
Again not very different from WF3 where we used the WorkflowCompleted event and the OutputParameters dictionary from the WorkflowRuntime.
Conclusion
While there are quite a few differences in the details the basic approach remains the same. And as the old approach with dictionaries was rather error prone I consider this a missed chance ![]()
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
by Andrew MacNeill (noreply@blogger.com) at June 30, 2009 09:44 AM
For the last two decades, human cognitive superiority had a distinctive sound: the soft click of stones placed on a wooden Go board. But once again, artificial intelligence is asserting its domination over gray matter.
Just a few years ago, the best Go programs were routinely beaten by skilled children, even when given a head start. Artificial intelligence researchers routinely said that computers capable of beating our best were literally unthinkable. And so it was. Until now.
by Alex Feldstein (noreply@blogger.com) at June 30, 2009 07:34 AM
May 11 – 15, 2009. Los Angeles.
It is always exciting to attend conferences like TechEd and talk to the users like you! I attended Teched 2009 North America, which took place in Los Angeles last month, as a Visual Studio staff, and spent 20+ hours standing at Visual Studio booth. I really enjoyed experiencing TechEd once again and enjoyed the moments when you told us the products are helping to do your daily work more efficiently. Hearing your feedback is also very important to us, and it is exactly the reason why we are there at the conference! For those who were also at TechEd this year, I hope you enjoyed the sunshine in LA and liked hundreds of sessions there!
This year, Windows 7 and Windows Server 2008 R2 drew a lot of attentions. Mark Russinovich, who is a Technical Fellow at Microsoft, demoed quite some new Windows 7 features at keynote on the first day.
- One of my favorite features in Windows 7 is the Problem Steps Recorder which helps customers (or friends, or family) to easily record what they did and what happened on their machine instead describing the repro steps, therefore it’ll largely help the ITPros to understand and troubleshoot the problems.
- Another highlight in Windows 7 is AppLocker feature, which helps IT Admins to easily specify what is allowed to run on user desktops and creates a secure environment.
Windows 7 demo is followed by Windows Server 2008 R2 demos by Iain McDonald, including the File Classification Infrastructure which helps ITPros to establish policies for classifying files and then performing common administrative tasks based on the classification.
Another hot topic at TechEd was Silverlight 3. (download Silverlight 3 Beta 1) If you are still wondering if you should choose Silverlight to build line of business applications, you should definitely try out Silverlight 3! Silverlight 3 has made Silverlight ready for building data-driven applications than ever before! A few Silverlight 3 controls that you might be interested in your business applications:
These controls are available for download at Silverlight Toolkit Sample.
Besides Silverlight 3 new controls, .NET RIA Services (download ".NET Ria Services" March 2009 preview) is the other essential piece that makes build Silverlight business applications much easier. In short -
Microsoft .NET RIA Services simplifies the traditional n-tier application pattern by bringing together the ASP.NET and Silverlight platforms. The RIA Services provides a pattern to write application logic that runs on the mid-tier and controls access to data for queries, changes and custom operations. It also provides end-to-end support for common tasks such as data validation, authentication and roles by integrating with Silverlight components on the client and ASP.NET on the mid-tier.
".NET Ria Services" March 2009 preview provides a great overview document that introduces .NET RIA Services in details, and it also described an end to end walkthrough for you to get started. Start building your Silverlight business applications today!
It is great to see .NET RIA Services generated huge interests at TechEd, as our team is also working on some of the features in there. :) Please let us know if you have any comments and suggestions once you have tried it out. You are more than welcome to leave comments here or post at .NET RIA Services forum.
Next year, TechEd will be back in New Orleans, June 7-11, 2010.
See you there!
by Alex Feldstein (noreply@blogger.com) at June 30, 2009 12:14 AM
Man, I hate it when I can’t find old code to reuse. Maybe if I post it here I’ll at least be able to find it next time it’s wanted. *Heavy, theatrical, sigh*
Edited to add a bit more info.
I’ve gotten far too use to the casual, sloppy, chatty style of Facebook, I guess.
I’m writing code, in VFP, that will iterate through directories, collect all PDFs, and merge them using GhostScript. I want the full path and file names for one purpose, but Ghostscript seems to require short file names. At least so far as I can tell it stumbles with file names delimited with quotes. So, in short, I need both short and long paths, and I can iterate using native VFP functions with either long or short paths, but not both. Hence, my desire to collect long filenames, but convert to short paths to pass to GhostScript.
* Example ?GetShortPathName_VFP( GetFile() ) Function GetShortPathName_VFP (tcLongName) Assert Vartype( tcLongName ) = "C" ; Message "Did you mean to pass a bad parameter to " + ; Program( Program(-1) -1 ) + "?" Local lcFName, lnFName DeclareDlls_gspn() lcFName = Space(255) lnFName = GetShortPathName( tcLongName, @lcFName, 255) ClearDlls_gspn() Assert lnFName > 0 Message Program() + " failed." Return Left( lcFName, lnFName ) Endfunc Function DeclareDlls_gspn Declare Integer GetShortPathName In Win32API As ; GetShortPathName String, String, Integer Return Endfunc Function ClearDlls_gspn Clear Dlls "GetShortPathName" Return EndfuncTagged: api, FoxPro, getshortpathname, VFP

A quick follow-up on the weekend posting about the Ruby group: there was mention of another package, LESS, that generates CSS as well. This might be worth checking out as well. I appreciate the feature that the CSS is static on the server and only generated when the plugin notes that the source file (with .less extension, of course) has changed. This speeds up serving the file, and speeds the responsiveness on the client, since nothing needs to be parsed, interpreted and applied.
In “It’s the Headings, Stupid!” Jon Udell points out that pretty visually-structured HTML still shouldn’t lose the structural power built into HTML: seven levels of headings, paragraphs, ordered and unordered list, definition lists, anchor tags, captions, titles and alt attributes. A sober reminder that not all the readers of our web sites are “ooh!” and “aah!” over our choice of colors or silly javascript animations, but are searching for content!
In a follow-up on Twitter, Pat Allen points to a SlideShare presentation with excellent audio of the Melbourne Ruby User Group and a presentation by Ben Schwarz “Why HAML Sucks or Why You Should Think Before Choosing HAML for Your Next Project” The long-winded title, Ben explains, is from an initially controversial title that got the conversation going, but was a bit too extreme. He makes some very good points in the presentation. I like the idea of audio synched with the slideshow; that works well. Obviously, hards-on presentations would have other challenges, but for a slide-heavy presentation, this works well.
Got a question in response to a Localization article today that asked how to store requested culture settings. In the article I recommend that easiest and most reliable way to switch cultures is to assign the culture when the application runs and allow the user to change cultures somewhere in the UI. When the culture is changed it’s up to the application to decide how to handle the actual culture change. One of the easiest things to do is write the change to a configuration setting and then exit and immediately restart the application.
.NET 2.0 gained the ability to write configuration settings in addition to easily reading them. Although this isn’t something you need frequently it’s quite handy to be able to update values easily and then write the changes back out into the configuration store. Here’s an example of a sample application that allows changing the active culture writing a new culture selection into a configuration file (in WPF):
private void lstLanguageSelections_SelectionChanged(object sender, SelectionChangedEventArgs e) { string origCulture = CultureInfo.CurrentUICulture.IetfLanguageTag; string culture = ((ComboBoxItem)this.lstLanguageSelections.SelectedValue).Tag as string; // static app method that acutally sets the culture App.SetCulture(culture, true); // force windows to close if (this.IsInitialized && culture != origCulture) { System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); // Add an Application Setting. config.AppSettings.Settings.Remove("Culture"); config.AppSettings.Settings.Add("Culture", culture); // Save the configuration file. config.Save(ConfigurationSaveMode.Modified); // Force a reload of a changed section. ConfigurationManager.RefreshSection("appSettings"); Process.Start( new ProcessStartInfo(Environment.CommandLine) { UseShellExecute = false, WindowStyle = ProcessWindowStyle.Normal }); Application.Current.Shutdown(); } }
Notice that you have to remove the setting before adding it back in when updating the value. The code checks to see if the culture has indeed changed (a little odd since this IS a SelectionChanged event handler after all but this has to do with how WPF initially assigns values) and removes the key and adds it back in. Finally the whole file is written back out and the configuration values are refreshed so the next time you read the changed configuration key(s) they will reflect the new values.
All of this assumes the that you have appropriate permissions – you need to have read/write access in the folder where your .config file is located – most likely the applications’s startup folder, which by no means is guaranteed. Under restricted profiles (or with UAC enabled in Vista) writing into the installation folder is not allowed. So use this approach with some awareness of the security environment it runs in.
ADEL() is now available, as well.
RowSource and RowSourceType are now available for comboboxes and listboxes on mobile devices. Right now the only supported value for RowSourceType is 1 = Values.
Twelve people attended the June meeting of the New Hampshire Ruby / Rails User Group , held on the 4th Thursday of the month ( we usually meet on the 3rd Thursday) at RMC Research in Portsmouth (Thanks to RMC and to John for hosting the meeting!)
Nick Plante was our master of ceremonies. As is the custom, we made a round of introductions to find out the most of the folks were “from away.”
Pat Allen put on the first presentation, on Thinking Sphinx. Thinking Sphinx is a Ruby library (not just for Rails) that allows Ruby applications to work with the Sphinx full-text search engine. Pat presented a slightly shortened version of the presentation he gave at RailsConf, and the presentation was clear, engaging and interesting. Participants had lots of questions to ask on search technology, word stemming, project status, what it’s like to be a Freelancing God, what being the lead on a popular Open Source project is like, what’s a kilometer, and more, and Pat’s answers were insightful. Check out (pun intended) the source on github, the support on Google Groups and Pat’s guide to using Thinking Sphinx on Peepcode.
Pat also took a moment out to plug his upcoming Rails Camp, a not-going-to-make-a-profit weekend get-together in BarCamp/Unconference format for 30-ish people at Bryant Pond, Maine. It sounds like a great event and a nice location and a price that can’t be beat: $120 for 3-nights, 3-days food, lodging and conference. Get details and consider signing up at http://railscamps.com/#ne_july_2009
Casey Rosenthal asked us, “What are style sheets for?” a number of times during his presentation, for good reason. Casey talked about SASS, Syntactically Awesome Style Sheets, a part of HAML and his reimplementation of SASS in Javascript, SASSiJS, sounds like “sausages” leading to all kinds of predictable jokes. But the topic was thoughtful, intriguing, interesting, and controversial. SASSiJS actually allows a .sass file to be downloaded as part of the HTML file, with similar syntax to a stylesheet link, and a JavaScript file that interprets the .sass file into CSS and applies it to the HTML document. Discussion was far-ranging and insightful: “What’s this good for?” “Would designers use this to make their CSS DRY?” View the source on GitHub at http://github.com/clr/sassijs/tree/master.
Thanks to Pat and Casey for their great presentations, to Nick for organizing, and to John and RMC for the facilities.
by Andrew MacNeill (noreply@blogger.com) at June 27, 2009 11:36 AM
At the MVP summit this year Kathleen and I asked MVPs using Visual Basic what kinds of applications they’re building, what other technologies they’re using, what their favorite features are, and more. Many thanks to all of you who humored me! The result? A great series of videos on Channel 9. (I told you I’d get back at you Jim Duffy!) ;-)
But Lisa decided to take this a step further to give more people, not just MVPs, a chance to tell their story. Check out www.imavb.net (which redirects to a page on the VB Dev Center) that also has links to written interviews submitted by MVPs. Here’s your chance to submit your own story and have your interview appear on the VB Dev Center!
Okay I just threw a lot of links at you up there. Just visit www.imavb.net!
Enjoy!
June 30 is the deadline to save $125 and get a free half-day pre-conference session for Southwest Fox 2009. Registrations are already at last year’s numbers, so be sure to join us in sunny Arizona in October to hear the brightest VFP developers on the planet speak about our favorite development environment. See you there!
by Doug Hennig (noreply@blogger.com) at June 26, 2009 09:44 PM
This past Saturday, the Regina YMCA once again held the event I look forward to all year: Echo Challenge. Our team, Thunder, competed in 2007 and 2008, and with three original members and three new ones, we were up to the challenge.
For the second year in a row, my Wednesday evening ride before Echo Challenge was marred by a bike crash. This time, it was on the cool-down part of my ride around beautiful Wascana Lake. As I came around a corner, a woman on another bike going the opposite direction was in my lane, coming right for me (she wanted to turn left but didn’t check for traffic first). We both tried to veer out of the way, but ended up side-swiping each other and down we went. My left wrist hit her bike, smashing my watch, spraining my wrist, and leaving a watch-shaped bruise. We both made sure the other was OK, and I continued on my way home. A couple of hours later, my right knee tightened up. By morning, I could barely walk because I could neither bend nor straighten my leg. Stretching and ice helped, but I figured Echo was no go this year, which really bummed me out. Fortunately, with lots of stretching, the knee loosened up a fair bit over the next couple of days, so I was able to ride after all.
Saturday started out cool and a little rainy, but by mid-morning, it was beautiful: about 24C (75F), cloudy, and some wind. I had a chance to meet our new team members, including our swimmer who’s only 12 (but a member of a local swim team).
The swim event was first: 750 m in the cold lake waters. That has to be the toughest leg, but Jamie did great, finishing in 13:34, good enough for 11th of 18 teams and almost nine minutes faster than last year’s swimmer. He tagged Lisa, our hill runner, who finished in 5:15 (placing her 10th) despite struggling with a sudden flare-up of asthma.
Here’s a photo of Nick and I waiting for the cycling leg to start. You can see the lake and the hills where the cycling route goes in the background.
Lisa tagged me and off I went. Although my knee was a little stiff, I managed a speed of about 45 kph (28 mph) for the 1.5 km to the start of the hills. I passed seven other cyclists, all in their twenties, and went down the final hill at over 50 kph (31 mph). However, I was significantly slower than last year: this year’s cycling leg was longer, but my time over the hill part of the race was 21:11 vs. 16:29 last year. Part of it was the knee, part was a head-wind we didn’t have last year, but the major part was I wasn’t in as good shape as I was last year. Here’s a shot of me at a relatively flat part of the hill section:
I ended up finishing 8th, which was pretty disappointing. However, there were a lot of new faces in the race this year, many of whom are serious athletes, and I was the second oldest cyclist, so I guess I shouldn’t feel too bad.
Here’s a shot of Nick and I at the end of the race:
I tagged Bob, who finished the 7 km run in 34:30, 1:30 faster than last year, 16th of the 18. Finally, Mike and Adrian finished with the 1.6 km canoe event. Their time of 32:33 was two minutes faster than last year, putting them in 17th.
Overall, we finished 17th out of 18 teams, not as good as last year, but it’s for a good cause. Unfortunately, donations were down this year, but hopefully we can get more teams out next year and get donations back up again.
Congratulations to the YMCA staff and volunteers for putting on a well-organized and fun event once again. I’m already dreaming of next year’s event!
by Doug Hennig (noreply@blogger.com) at June 26, 2009 04:49 PM
If you haven’t seen it yet, we’ve got a new article from Robert Green (VSTO MVP) up on the Visual Basic and VSTO Dev Centers. In this article, learn how you can use Visual Basic to build application-level add-ins that automate common Microsoft Office tasks. It’s a good introduction to Office development with Visual Studio so check it out!
Create an Application-Level Add-In to Automate Common Office Tasks
Enjoy!
After last nights dinner I went to bed but hardly could sleep.
Up at 5 for the last day.
Yesterday I had a session on software protection. Not all things went as good as I wished. So this morning I did work on the loose ends because I had the same session today again.
Now everything went smooth, actually so smooth that I had to invent some last minute things as otherwise my session would end too early.
Good thing that Venelina Jordanova was in that same session together with Uwe Habermann.
They came up with some question that really took me some time to answer.
Yet, the session was over in 65 minutes. 10 minutes earlier than expected.
The session on the first day, on VFP.Net was a very good one. It took me not too long to prepare for that and there was an enormos amount of information to share, so filling that session was more like leaving out things.
I spend the rest of the afternoon in Prague and go back tomorrow early afternoon.
This was a nice experience, the Prague DevCon is a very intimate one with nice folks around and a loose atmosphere. I was honored to be here.
I had fun last night presenting to the Sydney Business and Technology User Group. We chatted about the productivity improvements that we get as developers and managers from the professional version of Visual Studio and the great enhancements to the platform provided by the new version of the .NET Framework.
I've posted my slides on skydrive, but as I said last night the slides and demos were shamelessly stolen from the Visual Studio 2010 and .NET Framework 4 Training Kit. That's what you really want to download.
Thanks to Craig and Nick for inviting me to present.

Hey, all (if anyone’s actually still reading this). Sorry I haven’t been updating lately: when I’ve had something to say, it’s typically been easier to comment on Twitter than to come up with a full post here. Also, I made the mistake of trying to keep things sane in a discussion about naming of Ireland-related articles over at Wikipedia — big mistake. :-)
Incidentally, I just upgraded to 2.8 final and re-enabled Redirection. Hope I didn’t break anything…
WINE may or may not stand for “WINE Is Not an Emulator;” you might consider coming to the meeting to find out.
The July meeting of the Central New Hampshire Linux User Group, CentraLUG, will happen on the usual first Monday of the month, starting at 7 PM at the Hopkinton Public Library’s Community Room. Gather for Q&A and informal chat at 6:30.
Philip Sbrogna, an activist with the Monadnock Linux User Group, MonadLUG, will be presenting WINE. Philip got his start in the field of computers programming games for early microcomputers in ‘79 after which he spent some time on mini’s at DEC. After an intermission on submarines he returned to the world of corporate computing where his daily fare at a small southern NH company provides him some opportunity to do the DB & Web dev thing. Personal interests include optimizing algorithms & innovative datastructures; particularly NXDs. He’s been a Linux enthusiast since switching from Coherent to Slackware in ‘94.
Learn more about running Windows programs under Linux natively (Ubuntu Jaunty for presentation). Talk will include architectural overview & practical demonstration of what works and what doesn’t. Bring your favorite Window program along to see how it fares.
Note this meeting is at the Hopkinton Public Library 61 Houston Drive, Hopkinton/Contoocook, NH. Google map here. (Also, if you are coming from the southwest on route 202/9, the route 127 road over the Hopkinton Dam is once again open after a long repair closure.)
Day 2 in Praha.
Day 1 of the DevCon.
I had two session today, one on the VFPCompiler and one on the NetExtender
The Compiler session was visited by 60 people, the extnder session was visited by 30 people. All in all it was quite an experience to speak for 75 minutes.
I can suggest to anybody to prepare a session and speak even for a smaller group.
That will most definetely raise your awareness of the enormous task to prepare and perform such a session.
This experience made me more aware of what welll known speakers like Doug Hennig, Andy and Marcia, Cathy Pountney, Tamar Granor and all those other big names are or were doing year after year. (Please don't be offended if I did not mention your name, that was no on purpose!)
But at the same time I have to warn for the addition level of this experience. If you don't watch out you'll be hooked before you know. Just like creating applications this is most addictive.
Tomorrow I do a session on Protecting your software. Mind you, today I was telling about the NetExtender and showed the encryption/decryption possibilities. The combination with writing data in an absolute unreadable way came up and I will use this in my tomorrow's session as well.
Some new ideas for sessions came up.
Keeping you updated. See you.
With WF3 there was a central workflow runtime environment called the WorkflowRuntime and used to manage the lifetime of workflow instances. In WF4 this central class no longer exists and we manage individual workflows.
To compare the two, this is what a minimal console application looks like in WF3. It basically runs a workflow and prints a message when done:
static void Main(string[] args)
{
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
{
Console.WriteLine("The workflow has completed.");
};
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowConsoleApplication1.Workflow1));
instance.Start();
Console.WriteLine("Waiting for the workflow to complete.");
Console.ReadLine();
}
}
The same functionality in WF4 looks very different:
static void Main(string[] args)
{
WorkflowInstance myInstance = new WorkflowInstance(new Sequence1());
myInstance.OnCompleted += delegate(WorkflowCompletedEventArgs e)
{
Console.WriteLine("The workflow has completed.");
};
myInstance.Run();
Console.WriteLine("Waiting for the workflow to complete.");
Console.ReadLine();
}
The most important thing to note is that there is no longer a WorkflowRuntime object, instead we create a new WorkflowInstance object passing in a workflow instance (compared to a workflow type before).
The main benefit is that it makes creating and running workflows much easier. No longer do we need to keep track of a singleton and use that to do everything. Another benefit is we can register event handler per workflow instance, makes it easier to do different things for different types of workflows. In fact the OnCompleted isn’t an event but a delegate so you can add only a single handler.
The drawback is that general configuration. Like recording workflow errors, tracking execution or workflow persistence must be done for each instance while before we could just do it on the workflow runtime.
Some things haven’t changed. In both WF3 and WF4 running the workflow is done asynchronously so we need to wait, in both cases done using a Console.ReadLine().
With WF3 it was hard to have a workflow execute synchronously. Basically we had to add a different scheduler to the workflow runtime and explicitly tell the scheduler to execute the workflow. Of course this would affect every workflow created through the same WorkflowRuntime.
With WF4 there is a much easier model using the WorkflowInvoker class. All we need to do is call WorkflowInvoker.Invoke() passing in the workflow object and the workflow will execute synchronously on the same thread. Not only very useful for running the odd workflow but also for unit testing as any WorkflowElement, the base class for all activities, can be executed this way.
static void Main(string[] args)
{
WorkflowInvoker.Invoke(new Sequence1());
Console.WriteLine("The workflow has completed.");
Console.ReadLine();
}
Nice right!
Enjoy.
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu
While there have been only few posts here on the release blog, I've been constantly posting new versions of Guineu over the past few months. I've made many, many bug fixes in this time, but haven't added a lot of new features. Constantly reading blog posts that merely state "There's a new bug fix" doesn't seem very appealing to me, so I rather not posted those.
There've been a few new features in the meantime. DELETE FILE and SAVE TO are now working. SYS(8010) allows FTP transfer albeit for now only in the desktop version. SYS(8011) is a debugging function that produces extensive log information.
SYS(8012) is a brand new function that gives you access to the Software Input Panel (SIP) on mobile devices. That's the writing area you use with the stylus when there's no keyboard attached to the device. I'll update the documentation soon.
Tomorrow morning I'll be presenting in Prague at the conference. Topic of the session is Mobile development with VFP and Guineu.
Joe Stagner’s second podcast is up and this time he’s interviewing the one and only Lisa Feigenbaum from the VB team. Joe pins her down on what the future of VB really is and discusses perceptions, parity and co-evolution. It’s a great interview so check it out:
Misfit Geek Podcast - Episode #2 Does VB have a Future?
I got a little nervous at about 31 minutes into it when Joe calls me the “Princess of Visual Basic” (better than an old queen I guess ;-)) and mentions that there should be a crew of Beth Massi’s out there to crank out VB content. I can think of more than a few people besides my family that would be scared to have more copies of me running around and screaming out there. LOL. But many many thanks, Joe! I’ll keep it coming.
Enjoy!
For several years I’ve been following the Business-IT alignment movement. Alignment is necessary for fostering innovation and realizing greater profits as IT resources are used to their fullest to satisfy business goals and objectives.
But many organizations still struggle to make the connection.
Some suggest varying 3-, 5-, and 7-step approaches for better alignment. They typically consist of diving into new organizational structures, or implementing new frameworks and service models. Other sources say that the business is to blame, that IT is misunderstood and underutilized. While finally, some say it is a dead issue altogether.
I’m not convinced this is a dead issue, nor am I convinced that the business is to blame (especially nowadays). I’m also not convinced that 3-, 5-, and 7- step plans will magically work.
A few basic actions, initiated by IT, must happen first.
Business has long ago recognized that better alignment with IT is essential. We can argue about how well they’ve understood IT and how it can best be utilized, but across the board, the recognition is there. IT, after many years of making the case for alignment, seems to be coming up short during this crucial period. I hope that the following actions, from an IT-perspective, can help:
If IT can take action, better alignment can be achieved. This isn’t to say that the business can’t do more, but before the business can make IT a full partner, understanding, participation, and contributions from IT are a must.
As you may have heard Windows Workflow Foundation 4 is not an upgrade from Windows Workflow Foundation 3 (or 3.5). The version numbers might suggest that the previous version was quite mature but in fact it refers to the version of the .NET framework. In fact Windows Workflow Foundation 3 was the first version and 3.5 added only very few features and some bug fixes. And as WF 4 is a complete rewrite we should approach it as a new product and forget just about everything we already know about WF 3.
That might be a bit surprising, after all we still have activities and a workflow runtime right?
Well wrong actually!
There no longer is a class named WorkflowRuntime. Creating workflows is done by creating a WorkflowInstance object. This object is raises events for that workflow and only for that specific workflow.
But surely there is still an Activity base class?
Yes there is. But this is a completely new class that has nothing to do with the class Activity that was used with WF 3. In fact the new Activity class is in a new assembly and namespace, the full name is System.Activities.Activity in the assembly System.Activities.dll. The “old” activity class was System.Workflow.ComponentModel.Activity in the System.Workflow.ComponentModel.dll assembly. The old class still exists in .NET 4 so old workflows will still run but the new classes have no relation with the old classes.
So basically forget all you knew about the behavior of WF 3 ![]()
So lets take a brief look at creating a new workflow 4 style workflow.
When we start Visual Studio 2010 and select File/New/Project we get the new project tab. Select the Workflow node and you will see the four new project types
More about the different types in another blog post. For now just select the “Sequential Workflow Console Application”.
What we end up with is a simple project with just 2 files, the program.cs and the Sequence1.xaml. The latter contains the workflow. Note there is no choice between code or xaml workflows, the designer only works with xaml based workflows. Also note that the extension is no longer XOML but has changed to XAML.
The Sequence1.xaml workflow is still empty and looks like this:
When we open the Toolbox we see the new collection of basic activities. These are also completely new. For now just drag a WriteLine activity onto the Sequence in the designer. The goal of the WriteLine activity is just what the name suggest: write a line of text to some form of output stream. When we open the property sheet with the WriteLine activity selected we see there are just three properties: the DisplayName, the Text and the TextWriter.
The DisplayName is actually the name used on the design surface and used during the design of the workflow.
The Text property contains the text we want to print. In the property sheet we see a textbox with the text “<Enter an expression>”. This really is an expression editor where you can type in code. So if you want to enter a simple fixed text you must use quotation marks around it. This must always be a valid Visual Basic statement. yes that isn’t a typo Visual Basic, not C#, even if you are developing a C# project.
So in this case just add “Hello Workflow 4” including the quotation marks.
The TextWriter property is the text stream to write the text to. This is also an expression, just like the Text, and is optional. When not specified the text will be written to Console.Out which will do fine for now.
These expression windows in VB are completely new and a big change from WF3. Where we previously had to bind to property binding or something similar to add custom code we can now type it directly into the designer.
With this in place we are ready to run the workflow. Press Ctrl+F5 and with a bit of luck you should see the output appear in the console window. You might need a bit of luck because it appears the current bits are still a bit unstable and on my laptop running Windows 7 the designer tends to lock up quite a bit ![]()
In the next post more about how the workflow is created and started at runtime.
Up at 3 in the morning to catch a plane at 7 is beyond human efforts for me, but I did it.
Right now I am in my hotelroom, looking out over a street and a small park playground.
Plane took off at 7:05 exact and landed 1h 10mins later at Ruzyne (the name of the Praha airport)
I will keep you all updated about my days here. Looking forward to the events.