Wednesday, October 11, 2017

Fixing VS 2015 "buggy 'make console/win32 app' dialogs"

For some reason, this week, I wasn't able to make a Win32 pure or console application in VS2015. When I tried to type in a Project Name and a Solution Name (I was making a new solution at the time, with "Create directory for solution" checked.), I clicked ok, the dialog would disappear, but then reappear again (the same one).

I googled online. The only thing I found was this reddit post. There was no accepted solution. I found on my own that going to the "Programs and Features" window in the Control Panel, clicking my VS 2015 installation, clicking "Change", and clicking "Repair" in the VS installation dialog. VS apparently did a fresh reinstall, and it worked again.

=====
That worked for me in the first go, but the problem was that I was getting warnings that VS 2015 Redistributable (both x86 and x64 versions) were already installed. At face value, that's logically okay. As long as they existed, VS 2015 would run, but for some reason they weren't listed in my "Programs and Features" window, which was really mysterious to me.

I did a lot of searching about this. I found this forum post with an accepted answer saying that VS 2017 (which I had on my computer at the time, probably because of Unity) installs VS 2017 Redistributables with it that is sort of a "in-place upgrade" (I'm interpreting it as "minor upgrade") over the VS 2015 ones. It seems that registry keys may contribute to some installation programs interpreting the VS 2017 Redistributables as 2015 ones, causing the warnings in my VS 2015 re-installation. It'd also explain why no VS 2015 Redistributables were found in my "Programs and Features"; they were listed as the 2017 ones I'm guessing.

I uninstalled VS 2015 again. Unity and VS 2017 (probably didn't have to uninstall Unity, just wanted to be safe here). I uninstalled the 2017 Redistributables. I didn't manually install the 2015 redistributables here. I just ran the VS 2015 installer and let it install them for me. Everything was successful, and the 2015 redistributables were showing again for me.

Interestingly, I got Unity installed again on my laptop too. I don't remember clicking an option for that. Maybe it's automatic for VS 2015 installs since there is VS integration in Unity.

=====
The last thing I wanted to note here is getting Visual Studio installation logs. When I originally got the redistributable warnings, I didn't save a screen shot. I wanted to look at them again. I found this microsoft site about something called the "Microsoft Visual Studio and .NET Framework Log Collection Tool", which searches for VS installation logs and other installation logs, and puts it in a .zip folder.

I ran the too, got a zip, extracted it, and used the "Agent Ransack" search program to look for keywords I remembered from the redistributable warnings. One of the files was called:

dd_patch_KB3165756_20171006121844.log

The text of interest I found was:
[1608:0BB8][2017-10-06T12:24:55]i000: MUX:  Sending package issue to the caller: Type=2 Package Name=Microsoft Visual C++ 2015 Redistributable (x86) - 14.0.24215 Message=Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel. Error Code=-2147023258 (0x80070666)

[1608:0BB8][2017-10-06T12:24:55]i000: MUX:  Sending package issue to the caller: Type=2 Package Name=Microsoft Visual C++ 2015 Redistributable (x64) - 14.0.24215 Message=Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel. Error Code=-2147023258 (0x80070666)

(I added a newline between the two messages for easier reading.)

I think I got other hits, but this is the one I saved.

Thursday, October 5, 2017

Developing Winapi apps from a USB flash drive

Back at university, I'd like to continue to study Windows API, but I don't want to bring my entire laptop there, with campus being a little far from my dorm and especially with computers available there. I was thinking about moving some tools over to my USB flash drive to do so.

I was thinking the most important tools were a compiler and linker. In my C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin, there was a cl.exe compiler that represents the VC++14.0 compiler and a link.exe for linker. I saw they were command line tools, so I was assuming there was a way to do port tools like these to a USB, but I didn't know if those were the only ones I had to move. I was wondering if there was a download somewhere that could help me out with this.

So I asked on msdn about it, and got a lot of feedback/ideas. To get straight to the main idea, user Simple Samples recommended I try Eclipse for C/C++ for ease of use, and after a lot of research, I was able to get something portable working! I'd like to share my method here. Pretty sure it's working, I'll be doing the process again on a USB 3.0 external hard drive as I write this, to double check. If there are any more nuances/mistakes I find, I'll make sure to update it here.

Here's the main tools I used at the time I wrote this:
  -MinGW (g++ version says 6.3.0)
  -Eclipse Neon.3 IDE for C/C++ Developers, 64-bit (not the newest IDE at this time, I've just used that version before with Python)
  -JDK version 8u144 64-bit

Here's the general process:
  1. Download/unzip Eclipse to a folder on the USB.
  2. Download/install MinGW to a folder on the USB.
  3. Download/install the JDK to a folder on the USB.
  4. Setup the eclipse.ini file -vm option to point to the directory where the the Java Virtual Machine (javaw.exe) is intalled.
  5. Use setlocal and set to temporarily append the MinGW and MinGW\bin paths to PATH before running eclipse.
  6. Configure and run a Windows API project that uses the MinGW compiler toolchain.

Here's the process in detail:
1. Download the Eclipse Neon.3 IDE from the Eclipse website. Here's a link to the Neon.3 package listing. I chose to download using the Windows 64-bit option for my convenience. 32-bit is okay, but that means you must download either the 32-bit version of JDK (containing JRE) or just JRE by itself. Just to list it here, for the 64-bit download, I got a "eclipse-cpp-neon-3-win32-x86_64.zip".

2. When you open the zip file, you'll see a folder called "eclipse". Move/extract that folder to your root USB drive directory. At the time I'm doing this with my USB external drive, I moved it to F:\. (The directory where you place eclipse [and JDK and MinGW too] isn't important, but it's pretty convenient in my opinion to place it as the root usb directory.)

3. Download the MinGW GUI installer to install the MinGW compiler toolchain to your USB. You can go to the MinGW home page, and click the "Download Installer" button in the top right corner, which will redirect you to a SourceForge page to get the .exe. I got a "mingw-get-setup.exe" file.

4. Run the mingw .exe you got. In the license dialog, click Install. In the "Specify Installation Preferences" dialog, in the Installation Directory entry, click Change, and select a folder to install MinGW in. In my drive, I made a folder called F:\MinGW, just to be consistent with the default C:\MinGW installation path. From the MinGW Getting Started site, it's highly recommended to avoid paths w/ spaces.

5. Still in the "Specify Installation Preferences" dialog, check "... also install support for the graphical user interface.". Select the "... just for me (the current user)" radiobutton. (The Getting Started page recommends not to select the "all users" option. It was even disabled when I was doing this.) Uncheck the "... in the start menu" and "... on the desktop"  options.

Overall, I think these options are for the GUI tool called "MinGW Installation Manager" (in <mingw path>\bin) you can use for easy MinGW package management (including downloading, installing, and removing packages). I use that later on. It would make sense to just have it set for the current user since this is a portable install. And it wouldn't make sense to somehow link it to all the users of one computer, when you want to use the tools in multiple different computers. I deselect the start menu/desktop shortcut options also because it wouldn't make sense to have it since you're putting tools on a USB.

Here's a screenshot below of the options:



6. Click Continue. After the download of the MinGW Installation Manager is complete, click Continue. The manager will open up.

7. Click on the checkboxes for the following and click "Mark for Installation":
  -mingw-developer-toolkit
  -mingw-32-base (C compiler)
  -mingw-32-gcc-g++ (C++ compiler)
  -msys-base

I don't actually think you need the mingw-developer-toolkit and msys-base packages since the descriptions for those in the manager say they're for MSYS, which according to the MinGW homepage is a Unix-based command-line IDE. I'm just totally guessing here, so just to be safe, I include them.



8. Click Installation -> Apply Changes. Click Apply. Downloading and installing(copying) the files will take while. When it's done with everything, it'll display a dialog like below. Click Close. You'll see in the Installation Manager green check boxes next to successfully installed packages. You can close the Manager too.


9. The next thing is to install the right Java tools to get the Eclipse GUI running. From what I know so far, you need something called the Java Runtime Environment (JRE) in order to run GUI apps based on Java, like Eclipse. Some computers already have Java installed, and if a computer's PATH is set up right (especially to the right -bit version, like 32- or 64-bit), Eclipse will run. But it's handier to have a local one installed, especially for consistency.

Having the JRE by itself is good for end-users, but I'm going to use the JDK instead, which contains developer tools in addition to an end-user copy of the JRE in a folder called "jre". (There's no special purpose when talking about this installation, it's just my choice. I don't even know Java at this time haha.)

To emphasize, you must download the bit version of JDK that matches your Eclipse bit version. 64-bit Eclipse requires 64-bit JDK, which I'll be using.

So, to install the JDK, download the installation exe from the Java site. (The one for the 8u144 version I'm using is here). In the "Java SE Development Kit 8u144" section, I accepted with license agreement and downloaded the Windows x64 version, "jdk-8u144-windows-x64.exe". (You need to accept it before downloading.)

10. Run the java install .exe. When you get to the "Choose the Java features to install" dialog, click Change, and select/make a folder on your USB to install Java in. Like the MinGW install, I chose F:\Java\jdk1.8.0_144\ just for consistency. I think having a Java folder is a good idea since JDK (and standalone JRE) installations are just copying files, like the MinGW install, and you can have different versions in different folders without worrying about registry entries and whatnot. Click Next after you've set that up.

(After the download/install, the JDK folder will be set up, with "developer binaries" in the bin folder apparently containing more tools than a standalone JRE like "javac.exe". There'll also be an end user JRE in a "jre" folder, which itself contains another "bin" binaries folder. The installation dialog is still up at this point, I just wanted to point it out. You can see for yourself with Explorer).

 Now the installation dialog will ask you where you want to install a standalone JRE. Click Change, and select another, empty folder. I chose F:\Java\jre1.8.0_144. Continue/finish the install.

Looking at it now, it sounds a little confusing, having multiple JRE's available, each with the same javaw.exe Java Virtual Machine, aka JVM (not sure why it's called "javaw" though):
  1. <JDK path>\bin
  2. <JDK path>\jre\bin
  3. <JRE path>\bin

Any of those should work when setting up eclipse to use a given JVM.

11. To setup Eclipse to run its Java GUI based on the JRE you installed, open the eclipse.ini file that's in the same directory as eclipse.exe (mine is F:\eclipse\eclipse.ini). I prefer to open it in Notepad++ instead of Notepad because at least for me, the tabs/newlines don't display correctly in Notepad. Before the -vmargs listing (before the line that says -vmargs), Add the following options as two lines:

-vm
<directory containing JRE, javaw.exe [JVM] specifically>

You can use relative or absolute directories. This is what I put:

-vm
..\Java\jdk1.8.0_144\jre\bin
-vmargs
...

My file directory is like below:

F:\
  |
  -Java
  |
  -eclipse
    |
    -eclipse.ini

Don't use quotations marks, even if the directory you choose has spaces in it. The .ini can already process the line as is. If you put quotation marks, the .ini will literally try to look for a path containing a quotation mark. And since that never happens, running Eclipse (eclipse.exe) won't work.

If Eclipse can't find the JRE and therefore a JVM in that JRE, it'll display an error message box about it. Here's what it looks like


11. Before running eclipse.exe, temporarily edit your PATH variable in cmd to point to <MinGW install location> and <MinGW install location>\bin. I don't know batch scripting, but I'm familiar with cmd, so I opened it up and used these commands before running eclipse.exe.

setlocal
set PATH=%PATH%;F:\MinGW;F:\MinGW\bin

12. Run eclipse.exe from the cmd. Choose a workspace to place your projects in. I chose F:\workspace.

13. Now to setup and run a Winapi project. When the GUI comes up, click the Restore button on the top left. It's the button that looks like two cascading windows. This'll setup the Eclipse GUI so that you can see your C/C++ IDE tools.


14. Click File->New->C++ Project. Type a project name. Choose "Empty Project" for Project Type. Choose "Use default location", which will place your project folder in your workspace. Choose "MinGW GCC" as your compiler toolchain. My dialog's like below:


15. Click Finish. Click File->New->Source File. In the Source File edit box, type a name. I chose main.cpp. Click Finish.



16. (NOTE: I forgot to set up my PATH in cmd when I wrote this, and I edited in what's not Step 11. The dialog below may look different for the MINGW_HOME and MSYS_HOME variables, but the process is still the same.)

Before typing in Winapi source, set up the Project Properties. I'll start with the Environment variables. Go to Project -> Properties -> C/C++ Build -> Environment. The MINGW_HOME and MSYS_HOME are of interest. (MSYS_HOME has no effect in the overall build, but there's no harm in properly setting it, so I'll mention it here).  Set the Configuration dropdown to [All Configurations] so you can edit the Debug and Release settings at the same time.

To edit the environment variables to use the right drive letter, I added my own for my convenience called USB_ROOT for convenience. To add one, click Add, type in the environment variable name you want. Type in the root. (I prefer not adding the backslash here, so that I explicitly type it in the Properties dialog later). Click OK. Here's what my dialog looks like now:


17. Edit the MINGW_HOME and MSYS_HOME path variables to use the root variable you use. Select a variable, click Edit, and change as needed. Use the dollar sign and bracket notation to do so. Here's my new dialog:


18. Next is to edit the C++ include search path so that Eclipse can correctly find/parse header files, especially windows.h. Still in the Properties dialog, go to C/C++ General -> Paths and Symbols. Select GNU C++ in the Languages section. For the Include directories section, click Add. Click File System to search for your <mingw install path>\include folder. (Mine was F:\MinGW\Include). Click ok. This is what my dialog looks like now:


When you click ok, you may see a warning about "Duplicate paths". Here's the complete info. dump when I right-clicked to Copy the warning (the first line is more about just copying section headers):

Description Resource Path Location Type
Invalid project path: Duplicate path entries found (/TestWin [Include path] isSystemInclude:true includePath:F:/MinGW/include), path: [/TestWin]. TestWin pathentry Path Entry Problem



I googled this, and saw it may be actually a bug. Here's the bug report I found. It says Rebuilding the project is a possible fix, but it still appears for me. It may be possible to fix, from what I've seen from google so far, but now, for this blog, I'll ignore it.

19. Type in your Winapi source. Here's a dropbox link to my main.cpp. All credits go to Brook Miles site "theForger's Win32 API Programming Tutorial" (my first Winapi tutorial too : )   ) .

20. Build and Run. And that's it! Here's my final result:



I think what would be important is what's below as you move to different computers, as the drive name can change:
  -setting up your PATH variable
  -making sure right drive is specified when choosing workspace
  -updating Project -> Properties -> C/C++ Build -> Environment
  -updating Project -> Properties -> Paths and Symbols, and the GNU C++ and Include Directories entries
  -updating your eclipse.ini file, if you chose to make it absolute instead of relative

I feel like this can be automated with batch scripting, a Powershell script, or python if you can make it portable. I don't know batch or Powershell at this point. For Python, I'm sure it can be done. Overall, for the Project Properties, you'd have to find the right file to edit though, which I don't know at this point.

Post Notes:
-When you install MinGW with MSYS, I think you need to set up MSYS in some way to use the MinGW you installed. I haven't tried this yet. One of the blogs I researched mentioned this, if you're interested. But oveall though, you don't need to set up MSYS to use MinGW. MSYS is a set of coding tools in UNIX, completely separate from MinGW when you initially install them.

-You can set up the Project Properties before adding a source file.

-Editing the PATH variable to the right MinGW location is important. If you look in the screenshot for Step 16, you'll the default MINGW_HOME and MSYS_HOME variables point to a mingw install I did on my laptop's C drive. Without editing PATH, you may not get the MinGW GCC toolchain option when you first make a new project (if a computer doesn't have MinGW installed locally). (Check?)

-This is a YouTube tutorial that helped me to install MinGW. It's pretty funny too.

-It's good to install eclipse, MinGW, and JDK/JRE to new/empty folders. Since they don't depend on environment variables or the Registry, if you wanted to "uninstall" them, you just delete the folders. As a side note, I think that's how install/uninstall were done back then, just copy/paste files. The environment variables and the registry, combined with installation dialogs, just make it easier for the end-user. At least I'm guessing that's how it works.

-Your drive file system shouldn't matter. I initially did this on a USB flash drive with a FAT32 file system. I wrote this blog doing this on a USB 3.0 external hard drive, formatted to NTFS (I checked by right clicking on them in Explorer and clicked on Properties). They both worked.

-Having a USB w/ fast read/write is good. From a quick search, looks like they don't really give that info. You'd have to manually test it yourself with some program. SanDisk is a good brand, from my experience. USB 3.0 is of course the way to go here.

-With developing with a USB, you'll be wearing it out faster. It's good to make backups and not store critical files here permanently.

-Looks like by default, MinGW links Windows API libraries for you without you having to specify them in the compiler options (the ones that came with the mingw32-base package, according to the Installation Manager). That's pretty handy, especially if you're just starting out doing this.

-In your MinGW installation folder, in the bin folder, you'll find mingw-get.exe that's the MinGW GUI Installation Manager. I'm guessing you only get this if you choose the "install support for GUI" option during the install process

-In the overall process, I've realized that developing Winapi apps isn't exclusive to the VC++ compiler. That's pretty cool.

-Using the --version option in a mingw compiler like g++.exe or mingw32-g++.exe will give you the version number. At this time, my MinGW version was listed as "(MinGW.org GCC-6.3.0-1) 6.3.0".

-Eclipse versions are sort of confusing at first, in my opinion. What you see most directly is the version name and not number. Seems like Eclipse likes to name its versions based on outer space. What I've found was that different named Eclipse versions represent different major releases of Eclipse. Then, minor version releases are named using letters and numbers, with newer versions coming in later numbers or letters. You can see the complete listing here

-User Pavel A from that msdn post I linked mentioned CDT. I think that's more of a plugin. I got an IDE. I don't think they're the same. The CDT sounds harder to install. That's what I did, for ease-of-use purposes.

Sites:

I researched a lot of sites while doing this. I tried to keep as much as them as I could while doing the research, thought it'd be nice to share it on this blog post.

Eclipse on a USB Flashdrive
How to compile and run C++ with MinGW using Eclipse and CDT? - Stack Overflow
Installing Eclipse for C/C++ and MinGW | Another day at the office...
c++ - Configuring Eclipse for MinGW - Stack Overflow
Portable MinGW and MSYS
MinGW Site, Getting Started
MinGW Site, HOWTO Install the MinGW (GCC) Compiler Suite
omtlab - Configure your eclipse for C++
Stack Overflow - How to find out if an installed Eclipse is 32 or 64 bit version?
Stack Overflow - What is the difference between JVM, JDK, JRE & OpenJDK?

Some sites I ended up putting on my txt list don't seem relevant to this post now that I look at it, but I still thought it'd be nice to share them:

Stack Overflow - Eclipse CDT Debug not in executable format: File format not recognized after strawberry installation
Eclipse Forums - "Failure to execute MI command during Debug - Helios"