If you work on a Apache Cordova project in Visual Studio 2013 using Visual Studio Tools for Apache Cordova CTP 3 or 3.1 you should know there are important breaking changes in migrating the project from Visual Studio 2013 to Visual Studio 2015. The project can be migrated, but you have to do everything manually, as Visual Studio is not able to apply the changes automatically.

First of all, Visual Studio Tools for Apache Cordova CTP3.x are not longer supported in Visual Studio 2013 in the first place. If you try to install Update 5 it will prompt you to remove it before continuing.
vs2013u5
This is explained in the release notes for Update 5.

Also note: All prior releases of the Tools for Apache Cordova are incompatible with Update 5. If you have previously installed a Tools for Apache Cordova CTP extension, you must uninstall that extension before installing Visual Studio 2013 Update 5. If you require Apache Cordova support, we encourage you to try Visual Studio 2015.

The options for those developing with the VS tools for Apache Cordova in VS2013 are either to switch to Visual Studio 2015 or not install the last update and continue to work with CTP 3.x in VS2013.

In this article I will show you how to migrate a Cordova application from VS2013 to VS2015 and I will exemplify with a test application.

I have this app called TestApp. It’s built with Ionic and AngularJS. It is a JavaScript app, not a TypeScript app, but this works just the same regardless what language you use. It has the following project structure, with the Javascript source code in a folder called app, the libraries in libs and the templates in views. There are other folders apart from the ones VS has created, mainly css and images.

vs2013proj1 vs2013proj2

The application is just a test, it doesn’t do anything but it works for both Android and iOS.

ripple1 ripple2

When you open this project in Visual Studio 2015 it is not loaded. Visual Studio complains that “This project is incompatible with the current edition of Visual Studio.”
vs2015proj1
You have to covert it manually in order to make it available for Visual Studio 2015. Fortunately, the steps to do this are documented, but not in MSDN as one might expect, but on GitHub. There is a document called Known Issues – Visual Studio 2015 that explains what has to be done.

  • Create a new empty Apache Cordova app. The only purpose of this app is to copy from files to your actually project.
    vs2015proj2
  • Copy the .jsproj and taco.json files into the project folder of the application you migrate. Make sure you overwrite the existing .jsproj with this new project file.
  • Delete the existing bin and bld folders
  • Create a folder called www
  • Move everything except for config.xml and folders merges, res and plugins to the www folder.

If you open the project again in Visual Studio 2015 it will work and you can build and run it. For my test application the new project looks like this.
vs2015proj3

You can see that the all the folders and files under the www folder appear automatically in the solution explorer. They are not added with a Content or Folder element in the .jsproj file. You can make a comparison of the old and new .jsproj and see how simplified the new file is.
jsprojcompare1

Another thing to notice here is that the NodeJS module used for building the project is no longer called vs-mda (i.e. Visual Studio Multi-Device Application) but vs-tac (i.e. Visual Studio Tools for Apache Cordova).
jsprojcompare2

However, when I tried to build I got the following error:

MSBUILD : cordova-build error BLD401: Error : BLD00401 : Could not find module ‘delayed-stream’] code: ‘MODULE_NOT_FOUND’. Please Go to Tools –> Options –> Tools for Apache Cordova –> Cordova Tools –> Clear Cordova Cache and try building again.

This might have been related to the version of Apache Cordova I had globally installed, i.e. 5.1.1. If you get the same install it via npm.

However, you may still get problems when you try to build for Android.

MSBUILD : cordova-build error BLD10205: Please install Android target “”
You may not have the required environment or OS to build this project
MDAVSCLI : error : cmd: Command failed with exit code 2

The Android target name is empty, but if you do a Rebuild you get more information and actual required target name:

[Error: Please install Android target: “android-21″.

Hint: Open the SDK manager by running: C:\Program\ Files\ (x86)\Android\android-sdk\tools\android.BAT
You will require:
1. “SDK Platform” for android-21
2. “Android SDK Platform-tools (latest)
3. “Android SDK Build-tools” (latest)]
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\ApacheCordovaTools\vs-mda-targets\Microsoft.MDA.FileMirroring.targets(352,5): error MSB3073: The command “platforms\android\cordova\clean.bat” exited with code 2.

These can be installed using the Android SDK Manager. Make sure you select all the mentioned components.
android1
With these changes you can build successfully for Android.

One more thing here is the version of Apache Cordova used by vs-tac to build. vs-tac uses Cordova 4.3.1, but I already had Cordova 5.1.1 installed on my machine and used by vs-mda. If you have a newer Cordova version than 4.3.1 what you have to do instruct vs-tac to use this one in the taco.json file.

Replace the version 4.3.1 of the cordova command line interface with desired version (in my case 5.1.1). When you rebuilt it will install it and build with it.

Your environment has been set up for using Node.js 0.12.7 (x64) and npm.
—— Ensuring correct global installation of package from source package directory: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\ApacheCordovaTools\packages\vs-tac
—— Name from source package.json: vs-tac
—— Version from source package.json: 1.0.0
—— Package already installed globally at correct version.
—— Installing Cordova tools cordova@5.1.1 for project from npm. This could take a few minutes…

You can find the various Cordova versions installed under %APPDATA%\npm\node_modules\vs-tac\node_modules\cordova.
vstac3

For more information see:

, , , , Hits for this post: 54 .

In Visual Studio 2015 MFC comes with a new features (something that has rarely happen in recent years): support for dynamic dialog layout. That means library support for moving and resizing controls on a dialog. In this article I will show how this feature works.

Suppose we have the following dialog:
Dialog in original size

What we want is that the controls on the dialog move (the buttons) or resize (the group box, edit and the list) when the dialog is resized:

Resized dialog

Resized dialog

The resource editor provides support for this, but it can also be done programmatically. If you open the properties of a control there is a new category called Dynamic Layout that allows you to select a moving and a sizing type.
Dynamic Layout Settings
The options you have for both moving and resizing are: None, Horizontal Vertical, and Both. These options should be self explanatory. However, the important thing to notice is the value for the X and Y axes moving and resizing: these are ratios, not dialog units or pixels, having a value between 1 and 100 and defining how much a control is moved or resized when the host dialog changes size.

Now, to enable the layout shown in the the example above we need to do the following:

  • fully resize (100%) the group box and list box both horizontally and vertically
  • fully resize the edit control horizontally
  • completely (100%) move the OK button vertically
  • completely move the Add button horizontally
  • completely move the Clear and Cancel buttons both horizontally and vertically

Dynamic layout settings for the example dialog
It is pretty simple to put values into the dynamic layout settings for each control. When you build and run and resize the dialog box the controls move or resize accordingly.

These dynamic layout settings are put in the resource script (.rc file) of the application. For the example above it looks like this:

In this definition IDD_MFCDYNLAYOUTDEMO_DIALOG is the identifier of the dialog for which the settings are defined and the numbers in the BEGIN-END block represent:

  • the first line is a header containing the version number on the structure (0 in this version)
  • the consecutive lines are the dynamic layout settings (move and size ratios) for each control on the dialog, corresponding to the order the controls were defined for the dialog in the resource script file.

Dynamic layout settings in .rc file

These settings are loaded into a CMFCDynamicLayout object (see afxlayout.h/cpp). This is done in the OnInitDialog method of the CDialog class as shown below:

Note: for CPaneDialog, CDialogBar and CFormView on the other hand this is done in HandleInitDialog.

This LoadDynamicLayoutResource is actually a member of CWnd which contains other methods for working with dynamic layouts:

  • EnableDynamicLayout: enables or disables layout manager for a window
  • IsDynamicLayoutEnabled: indicates if layout management is enabled for a window
  • GetDynamicLayout: retrieves a pointer to layout manager
  • ResizeDynamicLayout: readjust the position of the controls handled by the dynamic layout manager as a response to WM_SIZE
  • InitDynamicLayout: initializes dynamic layout manager as a response to the WM_CREATE message

These methods allow you to enable or disable the dynamic layout management on the fly.

  1. Initially the dynamic layout management is set so the controls move and resize when the dialog is resized.
    dynlayout6

    dynlayout7

  2. Disable the dynamic layout management and the child controls are no longer adjusted.
    dynlayout8
  3. Re-enable the dynamic layout management and it works again.
    dynlayout9

The catch here is that just calling CWnd::EnableDynamicLayout won’t work because this method only deletes and recreates the CMFCDynamicLayout instance.

Just like CDialog::OnInitDialog you’d have to call CWnd::LoadDynamicLayoutResource. Therefore, the correct code for enabling and disabling dynamic layout management should look like this:

As mentioned earlier, setting the move and size values for dynamic layout management can be done programmatically using the CMFCDynamicLayout class. This is important when the controls are created dynamically and not in the resource template. What you have to do is:

  • create the CMFCDynamicLayout object
  • store the host window (the dialog) in that object
  • add the child controls with their move and size settings

The following code provides the same dynamic layout functionality as shown earlier except that all is set from code. Note that you must call EnableDynamicLayoutHelper from OnInitDialog.

Actually the same code as above can be expressed differently with the help of several static methods from CMFCDynamicLayout that create instances of MoveSettings and SizeSettings.

One important thing to notice here is that this code does not call CWnd::LoadDynamicLayoutResource because there are no settings in the resource script file. All these settings are only provided programmatically in this case.

When controls have to move or resize completely (100%) across one or both axes, setting the right values for the layout is straight forward. It gets complicated though when controls are not positioned sideways or need to move or resize with more complicated rules. Let’s take an example where the OK and Cancel buttons are positioned at the bottom vertically and centered horizontally. When the dialog resizes they should retain the original size, but they should always remain at the center bottom.

dynlayout10 dynlayout11

In this case the Y ratio for move is again 100. But what is the move ratio on the X axis? To determine you need a paper and pen. Basically we need to find how much do the buttons move on X when the width increases by 100 units. That is the ratio we have to set.

Initially the dialog has 251 units, that means two halves of 125 and 126 units. We want to keep the buttons apart by 10 units. What means the OK button is left aligned at 70 units and the Cancel button is left alight at 130 units.
dynlayout12
Then we increase the size of the dialog by 100 units. It’s now 351 and the haves have 175 and 176. The buttons are still 10 units apart and their with is still 50 units each. That means the OK button is now left aligned at 120 units, and the Cancel button is left aligned at 180 units.
dynlayout13
The conclusion is their both left margin has moved 50 units, and that is the value we need to set for the X ratio of their move setting. (Remember, the value is a ratio, but 50 units out of 100 units is also 50%.)

What if the OK and Cancel buttons should both be aligned at the center of their each half on the X axis and always preserve the margins? In other words they should change like this:

dynlayout14 dynlayout15

In this example, initially, the dialog has 231 units and that means two halves of 115 and 116 units. The buttons have both 60 units width, so they are aligned at 27 or 28 units to the margins.
dynlayout16
When the width of the dialog increases by 100 units to 331 units, the two halves have 165 and 166 units. The buttons preserve their margins, so their new width is 110 units.
dynlayout17
(Notice that the image above is stretched and the margins may be misleading.)

The conclusion is that:

  • The OK button did not move horizontally, but it increased its width from 60 units to 110 units, that means 50%.
  • The Cancel button moved horizontally and is now left aligned at 193 units instead of the original 143 units. That means it moved by 50% horizontally. Its sized increased from 60 units to 110 units, that also means 50%.

With those values set the buttons are resized and positioned as intended.

For more information see MFC Dynamic Dialog Layout.

Demo source code:
MFC Dynamic Layout Management - demo 1 (19)
MFC Dynamic Layout Management - demo 2 (17)
MFC Dynamic Layout Management - demo 3 (17)

, , , Hits for this post: 249 .

guidgen.exe is a small utility that comes with Visual Studio and generates GUIDs in a variety of formats. The problem with the tool is that it does not format GUIDs in plain text, which I happen to need many times (in source code, database tables, etc.) and I suppose is a feature needed by many developers. There are a couple of variants of the tool on Codeproject (GUIDGen Developer Studio AddIn and GUIDGen AddIn for Visual Studio.NET) but they lack some of the new formats supported by guidgen.

GUIDGEN.exe from Visual Studio

GUIDGEN.exe from Visual Studio does not have plain text formatting or case options.

Modified GUIDGEN has plain text formatting and case option but does not support all formats from Visual Studio’s GUIDGEN (i.e. C# and VB.NET Guid attribute format)

I have decided to create another modified version of GUIDGEN in order to support additional formats, including plain text, and also case options.

guidgen used to be available as an MFC sample, but that doesn’t seem to be the case any more. However, the sample from Visual Studio 2005 is still available on MSDN and I used that as a starting point. The result is a tool very similar to guidgen.exe from Visual Studio (2013 or 2015) but with additional features:

  • two more formats: __declspec(uuid("xxxxxxxx-xxxx...xxxx")) and plain text
  • case option: upper case (default) or lower case
guidgen2 guidgen3

The existing guidgen executable is available in the Common7\Tools folder of Visual Studio (i.e. c:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\ for Visual Studio 2013). You can replace that version with this build or put it somewhere else and keep it side by side by adding a new command from Tools > External tools. This might be more practical if you have several versions of Visual Studio installed.

guidgen-externaltools

Here are the downloads:
Guidgen-src (23) – Source code as Visual Studio 2013 solution
Guidgen-binaries (25) – Executables built with MFC as a shared library
Guidgen-mfcstaticlib-binary (29) – Executables built with MFC an a static library

, , , , , Hits for this post: 338 .

Visual Studio 2015 is out and comes with lots of new features and improvements (see details here) but it also surprised me with what I call a demoting of C++ again to a second-class citizen, after some years when it looked like it regained importance at Microsoft. I’m saying Microsoft has demoted C++ because they made it an optional component in the installer, unlike C# and VB.NET that you cannot opt out and are installed by default with all configurations.

When you run the installer you can see there are two setup options:

  • Typical installation, that includes C#, VB.NET and desktop features, and
  • Custom installation, that allows you to select what components to install.

vs2015installertypical1
The typical configuration requires about 8GB of disk space. However, it only installs .NET based components (and of course other related assets). C++ is not part of those “desktop features” mentioned in the installer description. It does however install the C++ redistributable packages.
vs2015installertypical2

However, when you run Visual Studio after installation completes, all VC++ components are missing and require explicit installation.
vs2015vcpp2
vs2015vcpp1

To install VC++ you need to perform a custom installation. This can be done after a typical installation. A custom installation allows you to select what you want to install. These includes programming languages (VC++, VF# and Python Tools for Visual Studio), Windows and Web Development components, Cross Platform Mobile Development components and common tools. In total these require an additional 13GB of free disk space. However, with a custom installation you cannot opt out C# or VB.NET.
vs2015installercustom1

A good thing though is that the MBCS version of the MFC library is no longer a separate download, but made available with the Visual Studio installation. You must select the Microsoft Foundation Classes for C++ in the Custom installation to have it installed.

The conclusion I draw from the Visual Studio installation options is that C++ is not viewed as a first-class citizen language at Microsoft. I suppose they don’t think a “typical” developer using Visual Studio develops in C++ so they didn’t put it in the typical installation. On the other hand, they don’t provide us with the possibility to opt out .NET languages we don’t use. I’ve never developed anything in VB.NET and I don’t plan to. I don’t even see the need for such a language (just for some remote resemblance with VB6).

, , , , Hits for this post: 678 .

When you create a Cordova project with Visual Studio Tools for Apache Cordova it generates a set of splash screens for all supported iOS (both iPhone and iPad) resolutions. These are found under res\screens\ios.

Visual Studio project showing the splash screen images.

Visual Studio project showing the splash screen images.

XCode project showing the splash screen images.

XCode project showing the splash screen images.

There are two things to notice here:

  • First, the names in Visual Studio are like screen-iphone-portrait.png or screen-ipad-portrait.png and in XCode are like Default~iphone.png or Default-Portrait~ipad.png.
  • Second, if you actually look at the files you’ll see they are not the same. The splash screens generated in VS are ignored and default Cordova images are used.
Default Visual Studio splash screen image for iPhone.

Default Visual Studio splash screen image for iPhone.

Default Cordova splash screen image for iPhone.

Default Cordova splash screen image for iPhone.

You can see the default Cordova splash screen image in the iOS built if you open the generated XCode project on the Mac where the iOS app is built.

Splash screen image in the XCode project generated by Cordova.

Splash screen image in the XCode project generated by Cordova.

The questions are: why are the file names different in Visual Studio and XCode, and why are the images not correctly copied from Visual Studio project to XCode project.

I’ll start with the second question. The problem here is that just because the files are in the Visual Studio project does not mean much. If you open the Cordova configuration file, config.xml, it only contains this (for a newly created blank project):

However, if you look at the Cordova documentation for images and splashes you’ll see the config.xml file should contain something like this:

The names here look like the ones that appear in the XCode project. But key is the platform element with its splash children. We have to add these to the config.xml file, but it can only be done by manually changing the configuration file, as Visual Studio Tools for Apache Cordova do not support this in the IDE yet.

Note: the Visual Studio names for the splash screens were used here, not the Cordova ones.

With this change, when you build, the right splash files are generated for the application.

XCode project with correct splash screen images.

XCode project with correct splash screen images.

This leads us to the first question: why are the file names different in Visual Studio and XCode and how are they mapped correctly? If you set the MSBuild output to Diagnostic, you’ll see something like this in the output:

1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-ipad-landscape-2x.png to res\screens\ios\screen-ipad-landscape-2x.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-ipad-landscape.png to res\screens\ios\screen-ipad-landscape.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-ipad-portrait-2x.png to res\screens\ios\screen-ipad-portrait-2x.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-ipad-portrait.png to res\screens\ios\screen-ipad-portrait.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-iphone-568h-2x.png to res\screens\ios\screen-iphone-568h-2x.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-iphone-landscape-736h.png to res\screens\ios\screen-iphone-landscape-736h.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-iphone-portrait-2x.png to res\screens\ios\screen-iphone-portrait-2x.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-iphone-portrait-667h.png to res\screens\ios\screen-iphone-portrait-667h.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-iphone-portrait-736h.png to res\screens\ios\screen-iphone-portrait-736h.png (TaskId:36)
1> —— Copied […]\BlankCordovaApp1\res\screens\ios\screen-iphone-portrait.png to res\screens\ios\screen-iphone-portrait.png (TaskId:36)

and

1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-iphone-portrait.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default~iphone.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-iphone-portrait-2x.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default@2x~iphone.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-ipad-portrait.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default-Portrait~ipad.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-ipad-portrait-2x.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default-Portrait@2x~ipad.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-ipad-landscape.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default-Landscape~ipad.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-ipad-landscape-2x.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default-Landscape@2x~ipad.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-iphone-568h-2x.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default-568h@2x~iphone.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-iphone-portrait-667h.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default-667h.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-iphone-portrait-736h.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default-736h.png (TaskId:36)
1> Copying splash from /Users/theuser/remote-builds/builds/16782/cordovaApp/res/screens/ios/screen-iphone-landscape-736h.png to /Users/theuser/remote-builds/builds/16782/cordovaApp/platforms/ios/BlankCordovaApp1/Resources/splash/Default-Landscape-736h.png (TaskId:36)

Here is a table of the iOS splash screens with the mappings between Visual Studio files and Cordova files.

Resolution Device Model VS file Cordova file
320×480 iPhone 1st Gen, 3G & 3GS screen-iphone-portrait.png Default~iphone.png
640×960 iPhone 4 & 4S screen-iphone-portrait-2x.png Default@2x~iphone.png
640×1136 iPhone 5, 5C & 5S screen-iphone-568h-2x.png Default-568h@2x~iphone.png
750×1334 iPhone 6 screen-iphone-portrait-667h.png Default-667h@2x~iphone.png
1242×2208
2208×1242
iPhone 6 Plus screen-iphone-portrait-736h.png
screen-iphone-landscape-736h.png
Default-736h@3x~iphone.png
Default-Landscape-736h.png
768×1024
1024×768
iPad 1, 2 & Mini screen-ipad-portrait.png
screen-ipad-landscape.png
Default-Portrait~ipad.png
Default-Landscape~ipad.png
1536×2048
2048×1536
iPad Air & Mini Retina screen-ipad-portrait-2x.png
screen-ipad-landscape-2x.png
Default-Portrait@2x~ipad.png
Default-Landscape@2x~ipad.png

Note: Though the actual iPhone 6 devices are down-sampled to a resolution of 1080×1920, the splash images must have the size of 1536×2048 and 2048×1536 pixels.

Note: Also take notice that for iPhone 6 Plus, unlike all the other iPhone models, you must provide both portrait and landscape splash screens (just like with iPads).

But where are the mappings handled? In the cordova-lib module there is a file called ios_parser.js where you can find the following code:

This code shows an array of (source) splash screens as defined in the config.xml file and an array of pre-defined target splash screen files and their expected resolution. The splash screens in these arrays are mapped by their size (width and height) and source files are copied into destination files. This means that the actual source file names are not important, and in fact you can name your files in any way you want, with the right size they will be correctly mapped.

Note: Be aware of a subtle issue: just copying content from the Cordova documentation for images and splashes to your config.xml file and changing file names won’t work. The path in the Cordova docs looks like res/screen/ios/ while the Visual Studio project path is res/screens/ios/. The mismatch of screen and screens can lead headaches trying to figure out why splash screen images are not correctly setup.

, , , , , , Hits for this post: 589 .

Visual Studio Tools for Apache Cordova (VSCordovaTools for short) is a great Visual Studio toolset to develop hybrid applications for multiple platforms, including Android, iOS and Windows. One of the nice things about the tool is that it installs everything you need to develop with Cordova. You don’t have to care about installing multiple components, runtimes, setting system environment variables, etc. However, one of the drawbacks is that it is not currently supporting updating those components to newer versions.

The latest release available for VS 2013 is CTP 3.1 and this build comes with Cordova 3.5.0. Should you need to use a newer version you have to do it manually. In this blog post I will list all the steps you need to do to update to the latest version Cordova (currently 5.1.1) both on Windows and on Mac (where you build the iOS version of the hybrid apps). However, in these steps I will also include how to update Node.js and npm.

Update Cordova on Windows

Note: Make sure you close all instances of Visual Studio before starting this process.

  1. Download and install the latest version of Node.js from nodejs.org.
  2. Update npm. To check your current npm version run the following command in a console:

    To update to the last version of npm run the following command in a console (elevated As Administrator):
  3. Update Cordova. To check your Cordova version run the following command in a console:

    To update to the last version of cordova run the following command in a console (elevated As Administrator):
  4. Update the vs-mda version of Cordova with the latest you just installed in the previous step. Cordova is (globally) installed at %APPDATA%\npm\node_modules\cordova. vs-mda copy of Cordova is available at %APPDATA%\npm\node_modules\vs-mda\node_modules\cordova. Replace the entire content of this folder with the one of the global Cordova installation.
  5. Install missing modules (this might depend on the latest version you install). For 5.1.1 I had to install concat-map and balanced-match. If anything else is necessary it should show up in the output log when you build your Cordova project.

Update Cordova on Mac

Note: Make sure you stop the vs-mda-remote agent before performing this upgrade.

  1. Open a Terminal session and run the following command:
  2. Update the vs-mda-remote version of Cordova with the the latest you just installed in the previous step. Cordova is (globally) installed at /usr/local/lib/node_modules/cordova. vs-mda-remove copy of Cordova is available at /usr/local/lib/node_modules/vs-mda-remote/node_modules/cordova. Replace the entire content of this folder with the one of the global Cordova installation.
  3. Restart the vs-mda-remote agent.

With all these installed you should be all set to start building with the latest version of Cordova.

, , , , , , Hits for this post: 581 .

I was working on transforming a Windows Store app into an Universal app so that it worked not just for Windows Store but also for Windows Phone. When you do this two new projects are added to the solution. One of them is a special one, called shared project that you can use to keep files shared between platforms.

universalapp1

universalapp2

In my case, one of those shared files were the App.xaml and App.xaml.cs. So what I did was moving these files from the original Windows Store app to the shared folder and then delete the copies from each platform specific project.

universalapp3

When I did this however, I run into several problems.

C:\Program Files (x86)\MSBuild\Microsoft\WindowsXaml\v12.0\8.1\Microsoft.Windows.UI.Xaml.Common.targets(327,9): Xaml Internal Error error WMC9999: Object reference not set to an instance of an object.

This was fixable by rebuilding the project. However, a new error appeared:

CSC : error CS5001: Program ‘c:\Work\Demos\DemoApp\obj\Debug\intermediatexaml\DemoApp.exe’ does not contain a static ‘Main’ method suitable for an entry point

Everything looked good, but whatever I tried the error still persisted. Eventually, I figured it out that the build action for the App.xaml file was wrong. When the files where included in the project, App.xaml was added as a simple Page.

universalapp4

However, this is not a regular page, it’s an application definition and the build action must be manually changed accordingly.

universalapp5

When you make this change and rebuild again (a simple build won’t suffice) everything works fine again.

, , , , , Hits for this post: 6286 .

I have recently upgraded my SSD disk to a newer and larger one. To avoid the hassle of re-installing everything (I have a lot of things to install) I cloned the disk. Everything worked fine. No problems with the operating system and the applications, except for Visual Studio. Though I could start, edit, build, run, etc. some things just did not work.

When I opened a solution with both C++ and .NET projects I noticed that the C++ projects took a lot to initialize. When I say a lot I mean minutes, many minutes. That didn’t seem right, but I had patience. However, after they finally passed the Initializing phase I noticed that it was no possible to select the configuration and target for the solution to build. The combos were disabled and nothing was displayed there. I could actually build, but it was the last selected configuration and target that were built. I tried deleting generated files (such as the .suo file) and after that, the last selections appeared in those combos, but they where still disabled.

vstrb3

Then I noticed that the properties window was not able to show anything, whether it was the properties of the project, a file or a reference. Everything was very slow. I could edit, but sometimes it took seconds for the text to show up. When I checked the resource monitor, it turned out that Visual Studio was using 17-18% of my CPU.

vstrb1

Finally, I noticed a warning when I closed the solution:

vstrb2

The .sdf file was not present in the specified location. So then I figured it must be a problem with Microsoft SQL Server Compact. Therefore I downloaded the kit from the download center and installed it again. That worked like a charm. Visual Studio was able to create the missing .sdf file, the Visual C++ projects loaded very fast and all other symptoms disappeared.

My conclusion was that cloning the hard-disk didn’t work well for SQL Server Compact. But the problem is that Visual Studio doesn’t react well when this component is missing. It should display the warning about it when it fails to create the file, not when you close the solution.

, , , , , Hits for this post: 5866 .

C++11 has provided support for range-based for loops. They allow iterating over the elements of a range without using an index.

However, if you try the following MFC code you get some errors because the compiler is looking for a begin() and end() function that provides access to the first and last element of the range:

1>error C3312: no callable ‘begin’ function found for type ‘CStringArray’
1>error C3312: no callable ‘end’ function found for type ‘CStringArray’

MFC does not define such functions for its containers.

Enter MFC Collection Utilities

Tom Kirby-Green and I have developed a small open-source library that enables the use of all MFC collection types in range-based for loops. The library is called MFC Collection Utilities and is available on codeplex.

The library consists of a single header, called mfciterators.h, that you include in your MFC projects.

Compiler and collections support

The library works in Visual Studio 2012 (the first version of the C++ compiler that supports range-based for loops) or a newer version.

The library enables all the MFC collections, both template and non-template, to be used in range-based for loops. This means arrays, lists and maps. For maps you get access to the content through a key-value pair that has two fields: key and value.

Supported template collections

Arrays Lists Maps
CArray CList CMap
CTypedPtrArray CTypedPtrList CTypedPtrMap

Supported non-template collections

Arrays Lists Maps
CObArray CObList CMapPtrToWord
CByteArray CPtrList CMapPtrToPtr
CDWordArray CStringList CMapStringToOb
CPtrArray CMapStringToPtr
CStringArray CMapStringToString
CWordArray CMapWordToOb
CUIntArray CMapWordToPtr

Examples

Download

Version 1.0 can be downloaded from codeplex from here.

For simpler installation you can use the available nuget package.

mfccollectionutilitiesnuget

Let us know if you encounter any issues.

, , , , , , , Hits for this post: 9974 .

Extension methods in C++

A few days ago Bjarne Stroustrup has published a proposal paper (N4174) to the C++ standard committee called Call syntax: x.f(y) vs. f(x,y). The following excerpt from the paper summarizes the proposal:

The basic suggestion is to define x.f(y) and f(x,y) to be equivalent. In addition, to increase compatibility and modularity, I suggest we explore the possibility of ignoring uncallable and inaccessible members when looking for a member function (or function object) to call.

x.f(y) means

  1. First try x.f(y) –does x’s class have a member f? If so try to use it
  2. Then try f(x,y) – is there a function f? If so, try to use it
  3. otherwise error

f(x,y) means

  1. First try x.f(y) – does x’s class have a member f? If so try to use it
  2. First try f(x,y) – is there a function f? If so, try to use it
  3. otherwise error

This may sound a bit crazy, but to me this immediately shouted EXTENSION METHODS, which is something that I’ve been wondering for a while how could be added to the language. I find this one of the most important proposals (I am aware of) for the evolution of the C++ language.

UPDATE: Recently I have discovered that a second paper on the same topic exists. The N4165 paper, called Unified Call Syntax, is authored by Herb Sutter. Unlike the first paper, Sutter’s paper proposes only making x.f(y) equivalent to f(x,y) and not the other way around. Here is a quote from the paper:

This single proposal aims to address two major issues:

  • Enable more-generic code: Today, generic code cannot invoke a function on a T object without knowing whether the function is a member or nonmember, and must commit to one. This is long-standing known issue in C++.
  • Enable “extension methods” without a separate one-off language feature: The proposed generalization enables calling nonmember functions (and function pointers, function objects, etc.) symmetrically with member functions, but without a separate and more limited “extension methods” language feature. Further, unlike “extension methods” in other languages which are a special-purpose feature that adds only the ability to add member functions to an existing class, this pro-posal would immediately work with calling existing library code without any change. (See also following points.)

Herb Sutter argues that the unified call syntax would achieve major benefits including consistency, simplicity, and teachability, improve of discoverability and usability of existing code and improve C++ tool support. However, he also explains why why making f(x) equivalent to x.f() is not possible since it would break existing code.

Extension Methods in C#

I’ll take a step back for a short paragraph on extension methods in C#.

An extension method allows you to add functionality to an existing type without modifying the original type or creating a derived type (and without needing to recompile the code containing the type that is extended.)

Let’s assume you want to write a method that counts words in a text. You could write a method called WordCount that looks like this (for simplicity we’ll only consider space as a delimiter):

You can use it like this:

Just by changing the syntax a bit and adding the this keyword in front of the type of first argument (always the type you want to extend), the compiler treats the method as part of the type.

With this change we can now write:

WordCount(text) vs. text.WordCount() is exactly what the Stroustrup’s N4174 paper is proposing.

Notice the extension methods in C# have several requirements including the following:

  • the extension method is always a public static member of a static class
  • the extension method has access only to the public interface of the extended type

Extension Methods in C++

The question that one may ask is how would this equivalence of x.f(y) and f(x,y) be beneficial to the language. My immediate answer is that it defines extension methods and enable developers to extend functionality without touching exiting code.

Let’s take a real case example. The C++ standard containers provide methods like find() to find an element in the container. There are also generic algorithms for the same purpose (that work in a generic way for various ranges defined by iterators). But this find() methods return an iterator and you have to check the value against the end() to interpret the result. Using std::map for instance, many times you just need to know whether it contains a key or not. std::map does not have a contains() method, but you can easily write a helper function:

And with that in place you can write:

However, I would very much like to be able to say (because in an object oriented world this seems much more natural to me):

If x.f(y) and f(x,y) were equivalent this later code would be perfectly legal (and beautiful).

Here is a second example. Suppose you want to define some query operators like the ones available in LINQ in .NET. Below is a dummy implementation of several such operators for std::vector.

(Many thanks to Piotr S. and Yakk for helping with the implementation of select.)

Those functions enable us to write code that “sums the square of the even numbers from a range” as shown below:

I don’t particularly like how the code looks. You have to catch the return value from each function even though it’s an intermediary value that you discard later.

One can improve that by using the return value from the previous call as a direct argument to the next call:

However, I like this even less. First, because it gets hard to follow what are the arguments for each call (and even if you try to format it differently it’s not going to help much) and second because it inverses the natural reading order or the operations. You first see sum, then select and last where. Even though this is how we described it earlier (“sums the square of the even numbers from a range”), it is misleading with regard to the order of the operations.

However, if x.f(y) and f(x,y) were equivalent it would be very easy to write the above code like this:

Isn’t that beautiful? I think it is.

Conclusion

The N4174 paper is rather an exploration of possibilities for uniform calling syntax than a very formal proposal. There are various aspects that have to be carefully considered especially when considering how to treat f(x, y). The N4165 paper makes a good case of the uniform calling syntax, explains the benefits better and argues against treating f(x) equivalent to x.f(). You should go ahead and read the two papers for detailed information. However, I sincerely hope that one day this will be accepted and become a core feature of the C++ language.

, , , , Hits for this post: 8461 .