Andrew Coates ::: MSFT

It's all about community!

February, 2009

  • Andrew Coates ::: MSFT

    VB6 Runtime Supported in Windows 7

    • 2 Comments

    Just got this note from Paul Yuknewicz. There’s an update to the VB6 support page on MSDN. In summary:

    Since the initial release of this support statement, the Windows 7 operating system has been announced.  This document has been updated to clarify Microsoft’s support for VB6 on Windows 7.

    VB6 runtime will ship and will be supported in Windows 7 for the lifetime of the OS.  Developers can think of the support story for Vista being the same as it is for Windows 7.  However there are no plans to include VB6 runtime in future versions of Windows.

  • Andrew Coates ::: MSFT

    Windows 7 on my Mac Mini

    • 5 Comments

    Back in the day, Dave and I bought (intel) Mac Minis (there was a retail outlet which had apparently decided to stop selling them and they were going pretty cheap). It’s been my main Vista machine at home for 18 months or so now (running bootcamp), I never boot into OSX, the machine was a member of my SBS domain and all was well with the world. Of course, I just can’t leave well enough alone (in addition to the fact that I’d “wasted” 40 of the 80GB HD on an OSX partition that I never use). I decided to take the plunge and see what the Win7 experience was like.

    First I tried an upgrade – running setup.exe from the DVD and choosing the upgrade option. Initial results were poor because of a lack of drive space on the Win partition,  but even after getting the available space up to 10GB (lose VS, Office and some games), the setup would get most of the way through and then just roll back. By the way, the rollback experience is great – there’s nothing left of the install afterwards except a note on the desktop as to what’s gone wrong – Vista is as it’s always been.

    Today I took the plunge and started a clean install.

    I inserted a Win7 x86 beta DVD, shutdown Vista, held down the alt key and turned the Mini on. After some time (after I released the alt key), the mac boot screen came up offering to boot from either of the partitions on the hard drive or the DVD. I chose the DVD and the rest was exactly like any other Win7 install experience I’ve had to date, that is to say seamless. Within 30 min I was at a Win7 desktop starring the Beta fish and was informed that Windows was already 65% of the way through downloading 4 updates. One more restart and I was in business.

    There are three devices showing up as problems in Device Manager, one USB device, the TPM and “Performance Counters” in the Other Devices node.

    No mucking around with bootcamp drivers, none of the insidious Apple updates.

    Next, I downloaded and installed Windows Live Essentials, and then I’ll do the rest of my standard install stuff – Office2007, VS2008, Acrobat Reader etc.

    Win7 Beta on Mac Mini – Big Thumbs-Up from me.

  • Andrew Coates ::: MSFT

    Un-Mapping Mapped Network Drives in VFP5

    • 1 Comments

    Back in the day, I wrote a bunch of articles for what was, then, pretty much the leading Visual FoxPro magazine. I used to have these published elsewhere on the web, but that site's pretty much dormant now and so I thought I'd pop them up here as well.

    This one was first published in FoxTalk December 1998, so the content is not necessarily relevant to today's versions of OSs and App Dev environments. Remember, This was the days of VFP 5.0, Windows NT 4 and Win 95/98

    Update – Thanks to Ken Levy for pointing out to me that you can do this exact thing with the My.Computer.FileSystem namespace in Sedna – as per below:

    my = NEWOBJECT("my", "my.vcx")
    loDrive = My.Computer.FileSystem.GetDriveInfo('J:')
    ? loDrive.ShareName && returns the UNC path

    One commonly stored piece of information is the location of a file or folder. If that file or folder is on the network, however, different users may refer to the location through different drive mappings. In this article Andrew shows us how to decode the mapped location using the Windows API so that any user can view or retrieve the file or folder.

    I learnt something this week that I guess I should have known. The Win32API is not consistent across operating systems. There are functions that work fine under Windows NT, but that fail miserably when called under Win95. I found one when working on the subject matter for this article.

    Mapping network drives is a common way of simplifying network storage systems from a user's point of view. Unfortunately for the cause of universal access, however, different users map network shares to different driver letters. If your application allows users to store links to files, how can you tell whether E:\COMMON DOCUMENTS\BUDGET98.XLS and W:\BUDGET98.XLS refer to the same document? Even more importantly, how can a third user who has neither E: or W: mapped retrieve the document?

    The answer is UNC. The Universal Naming Convention uses the format \\SERVER\SHARENAME\ to refer to the location of a file or folder. In the example above, the first user may have mapped drive E to \\SERVER_PDC\PUB, and the second may have mapped drive W to \\SERVER_PDC\COMMONDOC.

    Any Visual FoxPro function that accepts a path as a parameter will handle UNC paths. However, returning a UNC path from the getfile() and getdir() functions is a completely different matter. These functions are central to allowing your users to specify the location of files and folders. The getfile() function will return a UNC path, but only if the user navigates to the file through the network neighborhood – something a user used to having a network drive mapped is unlikely to do. The getdir() function is even worse. There is no way of getting it to return a UNC path to a folder (except in one specific instance – see the sidebar for details). Not only do the functions not return UNC paths, VFP does not provide any way to convert a mapped path to a UNC path.

    Win32API to the rescue!

    The windows 32 bit API provides a function that accepts a mapped path and returns the UNC path that corresponds to that mapped path. I searched through the API documentation and found a function called WnetGetUniversalName() in mpr.dll in the system directory. The function will accept the path to either a file, or to a folder with or without a trailing backslash.

    Unfortunately, this function is only available under Windows NT. I found this out the hard way, having developed and tested a routine using WnetGetUniversalName on my WinNT development box, I proudly installed it on a client's Win95 machine, only to have it not work;. Microsoft have a Knowledge Base article confirming that it doesn't work under Win95 (there's no mention in the article of Win98). So much for a single, consistent Win32API!

    What the article does mention though, is a couple of work-arounds. The first involves about 30 lines of C code that calls another couple of functions in mpr.dll. The second mentions in passing that there's yet another function in mpr.dll called WnetGetConnection(). WnetGetConnection() is not quite as versatile as WnetGetUniversalName(). It only accepts a drive letter and a colon (e.g. H:), rather than a full path. With a little string manipulation, however, it's pretty easy to split up a mapped path, pass the function what it wants and then re-assemble a complete UNC path from the pieces.

    To take the drudgery out of calling the Windows API, I wrote a wrapper function called GetUNCPath() that I include in any project in which I call either getdir() or getfile(). You could, of course, write wrappers for getfile() and getdir() which called GetUNCPath().

    For example, if the pub share on the server_pdc server were mapped as drive s:

    ? GetUNCPath('s:\documents') 
    \\server_pdc\pub\documents 
    ? GetUNCPath('c:\temp') 
    c:\temp 
    ? GetUNCPath('s:\documents\myfile.doc') 
    \\server_pdc\pub\documents\myfile.doc 

    The wrapper function itself is pretty straightforward. The complete function is shown in listing 1 and is available in the download file (2k). It accepts the mapped drive path as a compulsory parameter and optionally a length for the UNC version of the path. This second parameter is most often passed by the function itself in a recursive call if the default buffer size guess is not large enough (more on this later).

    Constants from the corresponding API header files are reproduced in the function rather than in a stand-alone header to make it more portable and a couple of local constants are also #DEFINEd for clarity later in the code.

    The mapped drive parameter is checked and if it is not a character expression, or if it's .NULL., then the function simply returns whatever was passed to it. If the tests are passed, then the API function is DECLAREd. Note the use of the WIN32API rather than the specific mpr.dll.

    Splitting up the mapped path parameter into its component pieces is simply a matter of taking the first two characters and calling them the mapped drive, and taking the rest of the expression and calling them the path. There's no problem if that's not a valid assumption because the API function will return an error value and we'll take the appropriate action.

    Next I call the API function and check the return value. The two important values I'm looking for are NO_ERROR (my personal favorite <g>) and ERROR_MORE_DATA. The NO_ERROR code means just that: the drive mapping was decoded successfully, and the result is in the lcBuffer variable.

    The value placed in lcBuffer is a null-terminated string. This means that the string is terminated by a chr(0) that needs to be stripped before we use it in VFP. I just append the path part of the original mapped path parameter to the translated drive returned by the PAI call and viola, a UNC version of the mapped path.

    The ERROR_MORE_DATA return value tells me that I didn't allocate enough space in the return buffer and I need to call the function again. Fortunately, once I get this error, I no longer need to guess how long to make the buffer. In addition to returning the error, the API function sets lnBufferSize to the value required so I can call GetUNCPath() recursively with the original mapped drive path and lnBufferSize.

    Each of the other error states indicates that the mapping could not be decoded for some reason or other. I've decided to treat them all the same way: simply return the mapped path passed to the function.

    While Visual FoxPro is a wonderful development environment it does have some limitations. Fortunately it provides enough access to the Windows API to be able to work around most of them.

    * Program....: GetUNCPath.prg
    * Version....: 1.0
    * Author.....: Andrew Coates
    * Date.......: September 28, 1998
    * Notice.....: Copyright © 1998 Civil Solutions, All 
    * Rights Reserved.
    * Compiler...: Visual FoxPro 05.00.00.0415 for Windows
    * Abstract...: Wrapper to the API call that converts a
    * mapped drive path to the UNC path
    * Changes....:
    * Originally used WNetGetUniversalName, but that 
    * doesn't work under Win95 (see KB Q131416). Now uses
    * WNetGetConnection which uses a string rather than a
    * structure so STRUCTURE_HEADER is now 0        
    
    lParameters tcMappedPath, tnBufferSize        
    
    * from winnetwk.h
    #define UNIVERSAL_NAME_INFO_LEVEL 0x00000001
    #define REMOTE_NAME_INFO_LEVEL 0x00000002
            
    * from winerror.h
    #define NO_ERROR 0
    #define ERROR_BAD_DEVICE 1200
    #define ERROR_CONNECTION_UNAVAIL 1201
    #define ERROR_EXTENDED_ERROR 1208
    #define ERROR_MORE_DATA 234
    #define ERROR_NOT_SUPPORTED 50
    #define ERROR_NO_NET_OR_BAD_PATH 1203
    #define ERROR_NO_NETWORK 1222
    #define ERROR_NOT_CONNECTED 2250
            
    * local decision - paths are not likely to be longer
    * than this - if they are, this function calls itself
    * recursively with the appropriate buffer size as the 
    * second parameter
    #DEFINE MAX_BUFFER_SIZE 500
            
    * string length at the beginning of the structure 
    * returned before the UNC path
    * ACC changed to 0 on 9/10/98 - Now using 
    * WnetGetConnection which uses a string rather than a 
    * struct
    #DEFINE STRUCTURE_HEADER 0
            
    local lcReturnValue
            
    if type('tcMappedPath') = "C" and ! isnull(tcMappedPath)
    	* split up the passed path to get just the drive
    	local lcDrive, lcPath
    	* just take the first two characters - we'll put it 
    	* all back together later. If the first two 
    	* characters are not a valid drive, that's OK. The 
    	* error value returned from the function call will 
    	* handle it.
            
    	* case statement ensures we don't get the "cannot 
    	* access beyond end of string" error
    	do case
    	case len(tcMappedPath) > 2
    		lcDrive = left(tcMappedPath, 2)
    		lcPath = substr(tcMappedPath, 3)
    	case len(tcMappedPath) <= 2
    		lcDrive = tcMappedPath
    		lcPath = ""
    	endcase
            
    	declare INTEGER WNetGetConnection IN WIN32API ;
    		STRING @lpLocalPath, ;
    		STRING @lpBuffer, ;
    		INTEGER @lpBufferSize
            
    	* set up some variables so the appropriate call can 
    	* be made
    	local lcLocalPath, lcBuffer, lnBufferSize, ;
    	lnResult, lcStructureString
            
    	* set to +1 to allow for the null terminator
    	lnBufferSize = iif(pcount() = 1 or type('tnBufferSize') # "N" or isnull(tnBufferSize), ;
    		MAX_BUFFER_SIZE, ;
    	tnBufferSize) + 1
            
    	lcLocalPath = lcDrive
    	lcBuffer = space(lnBufferSize)
            
    	* now call the dll function
    	lnResult = WNetGetConnection(@lcLocalPath, @lcBuffer, @lnBufferSize)
            
    	do case
    	* string translated sucessfully
    	case lnResult = NO_ERROR 
    		* Actually, this structure-stripping is no longer
    		* required because WnetGetConnection() returns a
    		* string rather than a struct
    		lcStructureString = alltrim(substr(lcBuffer, STRUCTURE_HEADER + 1))
    		lcReturnValue = left(lcStructureString, ;
    			at(chr(0), lcStructureString) - 1) + lcPath
            
    	* The string pointed to by lpLocalPath is invalid.
    	case lnResult = ERROR_BAD_DEVICE 
    		lcReturnValue = tcMappedPath
            
    	* There is no current connection to the remote 
    	* device, but there is a remembered (persistent) 
    	* connection to it.
    	case lnResult = ERROR_CONNECTION_UNAVAIL 
    		lcReturnValue = tcMappedPath
            
    	* A network-specific error occurred. Use the 
    	* WNetGetLastError function to obtain a description 
    	* of the error.
    	case lnResult = ERROR_EXTENDED_ERROR 
    		lcReturnValue = tcMappedPath
            
    	* The buffer pointed to by lpBuffer is too small. 
    	* The function sets the variable pointed to by 
    	* lpBufferSize to the required buffer size.
    	case lnResult = ERROR_MORE_DATA 
    		lcReturnValue = getuncpath(tcMappedPath, lnBufferSize)
            
    	* None of the providers recognized this local name 
    	* as having a connection. However, the network is 
    	* not available for at least one provider to whom 
    	* the connection may belong.
    	case lnResult = ERROR_NO_NET_OR_BAD_PATH 
    		lcReturnValue = tcMappedPath
            
    	* There is no network present.
    	case lnResult = ERROR_NO_NETWORK 
    		lcReturnValue = tcMappedPath
            
    	* The device specified by lpLocalPath is not 
    	* redirected.
    	case lnResult = ERROR_NOT_CONNECTED 
    		lcReturnValue = tcMappedPath
            
    	otherwise
    		lcReturnValue = tcMappedPath
            
    	endcase
            
    else        
    
    	lcReturnValue = tcMappedPath
            
    endif
            
    return lcReturnValue

    Sidebar - Returning a UNC Path from getdir()

    If you pass getdir() an initial folder in UNC format, then that folder will be the initially selected folder but it will not appear in the list of drives in the dialog (see Figure 1). If that folder or one of its sub folders is selected then the string returned will be in UNC. Be careful though. If you navigate to a mapped or local drive from the drives drop-down box, there's no way to get back to the UNC drive.

    getdir() screen shot (5kb)

    Figure 1. "Passing getdir() a UNC path will initially display the UNC path in the dialog, but the un-mapped drive will not appear in the drop-down list."

  • Andrew Coates ::: MSFT

    Looks like we got ourselves a convoy – Vodcast on VS2010 and .NET 4

    • 1 Comments

    10-4 - Vodcast on VS2010 and .NET 4

    I’m catching up with some blogging I’ve been meaning to do for ages and this is one of the first things I wanted to post. The team looking after getting the word out about Visual Studio 2010 and .NET 4 are doing a series of Video Podcasts they’ve called 10-4 (the code name for VS2010 was Dev 10, and the framework is v4 …). The series is hosted on Channel 9.

    There are 6 shows so far*:

    Title Time Comments Views
    10-4 Episode 6: Parallel Extensions 23:11 17 44,557
    10-4 Episode 5: Code Focused in Visual Studio 2010 19:29 20 62,086
    10-4 Episode 4: No More Parallel Development Pain 13:57 9 42,807
    10-4 Episode 3: ASP.NET WebForms 4.0 18:17 35 57,906
    10-4 Episode 2: Welcome to Visual Studio 2010 14:36 20 170,832
    10-4 Episode 1: Working with the Visual Studio 2010 CTP VPC 11:35 46 159,683

    You can also subscribe:


    * Stats correct at time of writing :)

  • Andrew Coates ::: MSFT

    Ramp yourself up with Ramp Up

    • 4 Comments

    I know, getting training budget is hard at the moment, but you really want to make yourself as employable as possible.

    Help is at hand (in fact, it’s only a mouse click away).

    There are, of course, a whole bunch of Virtual Labs you can do (for developers and for infrastructure people).

    There’s also a wonderful program called Ramp Up. From the site:

    Ramp Up is a free, online, community-based learning program, with a number of different tracks that will help you build your portfolio of professional development skills. Ramp Up has a solid foundation of premium technical content from subject-matter gurus, and provides easy-to-access content in a variety of forms that guide you in learning the important skills. Join Ramp Up (it's free!) and help advance your career

    There are currently 7 tracks to choose from (with more being added):

    • SharePoint for Developers - Part 1
    • SharePoint for Developers - Part 2
    • Visual Studio 2008
    • For the VS 2002/2003 Developer: Learn VS 2005
    • For the VB 6.0 Developer: Learn VB 2005
    • For the Java Developer: Learn .NET
    • Developer Basics

    The content is written by experts gurus like Charles Petzold, Michael Howard and David LeBlanc (as well as heaps of others) and there’s a community forum where you can ask and answer questions about the Ramp Up content.

    Completing a track gets you a bunch of Graduation Awards.

    Don’t delay! Sign up today!

  • Andrew Coates ::: MSFT

    CodeCampOz 2009 – April 4-5 - Registration now open

    • 4 Comments

    Update – Mitch has also announced a call for content. Submit your session proposals now!

    Mitch Denny has just announced that registration is now open for this year’s CodeCampOz. April 4-5 at Charles Sturt University in scenic Wagga Wagga, this not-to-be-missed event is now in its 5th year. Sign up on the Event Brite site.

    Did I mention the fact that it’s free?

    I love this community!

  • Andrew Coates ::: MSFT

    Virtual Goodness with the Linked .NET User Group this Thursday

    • 2 Comments

    As if it wasn’t enough to organise physical User Groups in Perth, Brian Madsen has been helping to organise a .NET User Group on LinkedIn. This month the irrepressible Zain Naboulsi is presenting on Deepen your Debugging: Tips and Tricks for the Visual Studio 2008 Debugger.

    This session is on at an Australian-Friendly time, this Thursday Feb 5.

    All the details are over at Brian’s Blog.

  • Andrew Coates ::: MSFT

    More Virtual .NET Goodness with the LiDNUG

    • 0 Comments

    Brian Madsen’s just pinged me to remind me about the next instalment of the Linked In .NET User Group. Following on from the last meeting, Stephen Fulcher will be talking about the ASP.Net Runtime:

    In this session, we will go through the key .NET application architectural scenarios and analyze (for each one) how to instrument and monitor for reliability, availability, operating conditions and security. We will also explore how this kind of approach will provide valuable business data to:

    • Increase application security
    • Dynamically change application behavior to help solve tough issues that are inaccessible using a debugger
    • Monitor individual and corporate user behavior
    • Contribute to decisions about version definition and application R&D
    • Discover user behavior
    • Help build the foundation for performance and scalability testing
    • Help the sales team close deals and increase customer satisfaction

     Check out Brian’s blog and sign up today.

  • Andrew Coates ::: MSFT

    Walking the Walk

    • 2 Comments
    1_IMAG0026 Stitch

    I love my job – not least because much of the time this is my office. All made possible via the magic of wireless and mobile devices.

    Speaking of walking, I was on the way back from the Gym the other day and spotted this – I didn’t know we’d branched out quite this far …

    IMAG0015
Page 1 of 1 (9 items)