I haven’t been paying too much attention to the VS 2013 launch, but I did read a few blog posts about it yesterday, including this one. Honestly, I haven’t really done much with VS 2012 yet, other than using it to work on some Project Euler problems at home, and using it as a front-end to TFS 2012 at work. (My day-to-day programming work is mostly done in the AX IDE environment right now.) Some of the stuff they’re doing sounds interesting, but it doesn’t really apply to me right now. One of these days, I’d like to get back into some serious .NET work, possibly including some Azure stuff, and ASP.NET MVC, and maybe get a chance to mess around with stuff like Unity. I do have one new interesting side project going on right now, though, which I want to write up in more detail later.
Category: programming
Project Euler
I haven’t mentioned Project Euler on here in a while. Earlier this year, I got on a roll and solved the first 20 or so problems. Then, I got too busy with other stuff, and didn’t make any more progress. Well, I got interested in it again and finished through to problem 25. I’m hoping I can find time to get a few more done before the end of the year. I’m finding that Project Euler is a pretty good way to keep up some basic skills. The kind of programming I do at work is interesting, but it doesn’t really exercise certain “muscles”.
silliness in the Dynamics AX compare tool
I had a small issue crop up in AX a couple of weeks ago. It wasn’t big enough to spend any time on, but it was a bit of an annoyance. Well, I had some spare time yesterday, so I decided to see if I could fix it. The end result was that I did indeed fix it, but the journey to that point was kind of ridiculous, so I thought I’d write it up.
AX has a built-in compare tool, for comparing different versions of code in different AX layers, or in source control. It’s not a terribly great tool, and I’d rather have WinMerge or Beyond Compare, but it’s good enough. The initial form shows the names of the two files being compared, with a red box next to one, and a blue box next to the other, to indicate the colors that will be used to highlight the differences between the two files.
Well, the color in those little boxes mysteriously disappeared a couple of weeks ago. The tool still works, and the text is highlighted in red & blue, but there’s no visual indication of which text is from which file. Not a really big deal, but inconvenient.
Most of the tools built into AX are written in X++, and we have full source, so I went ahead and dug up the source for the form named “SysCompareForm.” I don’t think I should post any of the source here, but what I found is that those little red and blue boxes were actually HTML controls, each one displaying a web page, constructed in the code! I’d never really noticed before, but the boxes were not actually displaying solid red & blue, but rather were displaying red-to-white and blue-to-white gradients. And, of course, this being Microsoft, they were doing so in a way that only worked in older versions of IE. And, yeah, I’d recently upgraded IE on my VM from 8 to 10. So that was the problem: each of those little squares was actually rendering a web page with IE, just to get little red & blue swatches!
The cross-browser gradient situation has been a bit of a mess for a long time now, and you generally need to add about 10 lines to your CSS file just to do one gradient that works well across all browsers. So, I tried to update the code so it would render out OK in IE 10. Well, I messed around for a while, and couldn’t quite get it right. Then, I did some searching, and found this thread from a Russian web site, from someone else who had the problem and solved it. So, I just copied his code and went on with my life.
Apparently, this problem was fixed by Microsoft in a recent CU, but I guess it’s one that we haven’t applied yet. I wonder how much other stuff in AX is being done like this, and relying on HTML/CSS that only works in IE 8. Geez.
Visual Studio 2013 and Build
I watched a little bit of today’s keynote from the Build conference on my iPhone at lunch today. I have to say that Scott Hanselman’s bit was pretty cool. I don’t know if I’ll actually have any reason to use VS 2013 for an ASP.NET project any time soon though. I’m not really doing that kind of work right now, and I’m not sure when I’m likely to get back to it. But I’ll at least have to install the thing and mess around with it on a little sample project, just to keep up with what’s going on in ASP.NET.
On a related subject, I’m somewhat embarrassed to admit that I’ve never really learned much about ASP.NET MVC. I did learn the basics at one point, quite some time ago, but I’ve never used it on a real project, and I haven’t kept up with the most recent releases. Well, I started reading a book on MVC 4 recently. I haven’t gotten very far with it, but hopefully I can get far enough to at least say that I have a clue how it works.
vs 2012 express for web
I thought I was done blogging about VS 2012 for now, but I decided to start messing around with MVC 4 this week, so now I’ve gone ahead and installed VS 2012 Express for Web. I was kind of hoping that the install wouldn’t take that long, since one would assume that most of the components would already be on my machine, from VS Express for Desktop. But no. It took more than an hour to download and install everything. And I had to update NuGet in Express for Web, even though it was already up to date in Express for Desktop. And I had to apply the RemoveAllCaps fix again too. So I’m guessing that there’s less overlap between the Desktop and Web products than I would have hoped. But that’s OK — I’ve got plenty of hard drive space on my ThinkPad!
Meanwhile, Visual Studio 2013 has been announced. That was a bit of a surprise, since I’d assumed that the next major version would be VS 2014. There’s some pretty neat stuff in VS 2013, though a lot of it likely won’t be applicable to anything I’m doing at work or at home right now.
a bit more on Visual Studio 2012
I feel a little bad about yesterday’s screed on the VS 2012 UI. (But not bad enough to delete it or anything. I still wish they hadn’t mucked with the UI so much.) So today I thought I’d try to write a more positive post about VS 2012.
First, I’d like to link to this blog post on how cool it is that Microsoft has kept so much of the functionality of the full VS product in the Express editions. I do agree with him on this, and I am glad that Microsoft is willing to release such a full-featured product for free. Having said that, though, I’d also love to see a $99 “standard” version that comes a bit closer to the $499 “pro” version. I think my biggest issue with the Express product will be lack of support for extensions. I’ve gotten quite used to DPack, for instance, so it’ll be hard to do without that.
Here’s a good article on “Simple but Interesting Features of VS2012“. Some of these features should be pretty useful. I’m glad that Microsoft is still adding little things like this to Visual Studio. It’s easy to let small, useful, features get lost in favor of grand initiatives, and I’m happy to see that someone at MS still thinks about stuff like this.
Finally, here’s a post about some really great new features in VS2012. I was pretty stoked about a few of these, until I realized that it was an April Fool’s post. (Actually, a couple of these *would* be useful, and not that hard to implement…)
Visual Studio 2012, take two
So I managed to get VS 2012 installed. (See previous post for details on my first failed attempt.) I’d love to write up a blog post detailing some weird issue and how I worked around it, but I don’t really have anything useful to offer along those lines. I basically just installed some pending Windows Updates, had a cup of coffee, then tried again.
After the install, I was prompted to install a patch that apparently fixes some compatibility issue. Then, I was prompted to install VS 2012 update 2. I did both of those things, and now have a usable VS 2012 install. I’m still not sure why Microsoft can’t post updated installers for their products when they release patches and updates, but I’m used to the silliness now, so I just grin and bear it.
I had read a good bit of negative feedback about the UI changes in VS 2012, and I have to say that I agree with most of it, now that I’ve seem the product up close. It’s much less pleasant to look at, compared to VS 2010. First, the upper-case menus are ridiculous. Whoever thought that was a good idea has hopefully been fired by now. (Who am I kidding, he probably got promoted!) You can fix that pretty easily with this NuGet package. And the guy who put it together gets extra points for the instructions: “YOU NO LIKE NO SHOUTING?! Run Disable-AllCaps”.
The next easily-fixed interface blunder is the color scheme. The default is called “light”, and it’s kind of an all-grey mess, with a little bit of white, black, and blue. If you switch to the “blue” theme, you get something a little like VS 2010, and much more usable.
The general flatness of the interface, though, is still pretty blah. There was really nothing wrong with the VS 2010 interface, and no reason to arbitrarily change stuff for the worse like this, and it’s so hard to believe that anybody really thought they were making things better here.
There’s a blog entry on the VS team blog that discusses the all-caps thing in specific. If you read it, you’ll get a good picture of how a very large company can make really poor decisions about specific products, based on big-picture corporate strategies and directions, and how they can be (apparently) clueless about what they’re doing. They talk about how the use of uppercase text is a “strong signature element” of MS user interfaces, including Zune and Bing. Now, really, how much thought does it take to figure out that the menu bar for a complex programming IDE has nothing to do with the user interface on a failed MP3 player or a web search engine? They end the blog post by saying that “we will enable you to customize the casing, and we are exploring options for how to expose that choice.” Well, the blog post is about a year old, VS 2012 has had two update releases, and still no option in the product itself to change the menu casing.
Alright, so that was way too much grumbling about fairly trivial user interface stuff. I guess I’m just in a bit of a cranky mood today! I still look forward to trying out VS 2012, and seeing what useful new features have been added to the product, and to C#!
Visual Studio 2012
I haven’t bothered with VS2012 yet, but today I decided to try to install VS Express 2012 for Windows Desktop on my laptop. I really only want it, at this point, for developing console apps. I wanted to take a shot at using it for the Project Euler stuff that I’ve been playing around with, and I was also interested in trying out some of the async stuff in C# 5. So nothing fancy; I just wanted to get familiar with it.
Well, no luck. The install got about halfway through (judging by the progress bars), then got no further. I know some of the VS installs in the past have been notoriously slow. (I’m looking at *you* VS 2005 SP 1! Or was it VS 2008 SP1…?) But this one just stalled at the same spot for 2 or 3 hours, with no change, so I gave up on it.
I’m starting to wonder if I need to do a fresh install of Windows 8 on that laptop, just to clear up the cruft from previous VS installs. I really wish Microsoft could make an IDE that didn’t cause so much grief just to install…
Project Euler
I started messing with Project Euler this week. It’s actually a lot of fun. I’ve only solved three problems so far, but I’ve been enjoying it, so I think I’ll keep going and see how far I get before I get tired of it, or I get pulled into something else, or the problems get too hard.
I’d been thinking that maybe I’d try a new language for this, but I decided to stick with C#, as I’m not really doing much C# at work, and I want to keep in practice with it.
I’ll also admit that I haven’t had any reason to do the kind of math problems that are found at Project Euler in a very long time, so my skills there are a bit rusty. But I’m managing to remember what Fibonacci numbers are and all that fun stuff!
Here’s my badge:
Opening multiple projects in MorphX at startup
The MorphX IDE used for X++ programming in Microsoft Dynamics AX is a fairly decent environment to work in, but it definitely has some shortcomings and oddities. There is a “project” abstraction in MorphX that allows you to create a named group of objects that all relate to a project that you are working on. There’s little meaning to these projects, other than that. You can export all objects in a project into a single XPO file, but other than that, it’s basically just a structure to help a programmer keep track of a list of related objects. You can set a single project as your “startup project”, and that project will then open automatically when you open MorphX. Since I’m usually juggling three or four projects at a time, I’ve been thinking that it would be great if you could open a group of projects instead of just one, so I decided to try and write some code to do that.
My realization that this could be done at all mostly came from the book Microsoft Dynamics AX 2012 Development Cookbook. The section “Modifying the right-click context menu” described a method of setting and clearing the startup project via the context menu. Prior to reading this, I hadn’t realized that the development environment was as customizable as the AX front-end, though (in retrospect) it makes sense that it is.
The project I’m going to describe here will do a few, fairly simple, things:
- Maintain a list of startup projects in a simple text file, stored in my personal “documents” folder.
- Allow for adding and removing projects from this list, via the right-click context menu.
- Allow the user to open all projects in this list, via the MorphX “tools” menu.
I could probably do a lot more with this project, such as actually open the projects at MorphX startup, rather than just through the tools menu, but I’m fine with the project as-is, for now.
This blog post is going to walk through the steps necessary to implement this functionality.
First, we’re going to create a class called “AjhDevLaunchStartupProjects”. Our class will have methods to add and remove projects from the list, and to open all projects specified in the list. We’re not going to go overboard with efficiency here. I’m assuming that the list will, at most, have three or four projects on it at a time, so we’re simply going to read them from disk into an array, and write them back out from the array.
We’ll start with an entirely standard static constructor:
// https://gist.github.com/andyhuey/5315492
public static AjhDevLaunchStartupProjects construct()
{
return new AjhDevLaunchStartupProjects();
}
Now let’s add a method to get the file name for the text file:
// https://gist.github.com/andyhuey/5315509
private str getStartProjFileName()
{
str myDocsPath;
#WinAPI
myDocsPath = WinAPI::getFolderPath(#CSIDL_PERSONAL);
return myDocsPath + @"\axStartProjects.txt";
}
Now, methods to read and write the file:
// https://gist.github.com/andyhuey/5315524
private Array getProjectList()
{
// get the project list from a file.
str startProjFileName;
TextBuffer tbProjList;
Array projects = new Array(Types::String);
int nProjects;
startProjFileName = this.getStartProjFileName();
tbProjList = new TextBuffer();
// if it doesn't exist, create an empty file & return.
if (!WinAPI::fileExists(startProjFileName))
{
WinAPI::createFile(startProjFileName);
return projects;
}
// should probably assert permission...
tbProjList.fromFile(startProjFileName);
nProjects = 0;
while (tbProjList.nextToken(true))
{
nProjects++;
projects.value(nProjects, tbProjList.token());
}
return projects;
}
private boolean writeProjectList(Array projects)
{
// write out a project list to file, overwriting existing list.
str startProjFileName;
TextBuffer tbProjList;
int i;
startProjFileName = this.getStartProjFileName();
tbProjList = new TextBuffer();
for (i=1; i <= projects.lastIndex(); i++)
{
tbProjList.appendText(projects.value(i));
tbProjList.appendText("\n");
}
return tbProjList.toFile(startProjFileName);
}
And the methods to add and remove projects from the list:
// https://gist.github.com/andyhuey/5315547
private void addProject(str newProject)
{
// add a new project to the list.
Array projects;
int i;
projects = this.getProjectList();
// make sure it's not already there...
for (i=1; i <= projects.lastIndex(); i++)
{
if (projects.value(i) == newProject)
return;
}
// add it and save.
projects.value(projects.lastIndex()+1, newProject);
this.writeProjectList(projects);
}
private void removeProject(str projectToRemove)
{
// remove a project from the list.
Array projectsIn, projectsOut;
int i, j;
projectsIn = this.getProjectList();
projectsOut = new Array(Types::String);
j=1;
for (i=1; i <= projectsIn.lastIndex(); i++)
{
if (projectsIn.value(i) != projectToRemove)
{
projectsOut.value(j, projectsIn.value(i));
j++;
}
}
this.writeProjectList(projectsOut);
}
And here’s the code to open all active projects:
// https://gist.github.com/andyhuey/5315552
public void openAllProjects()
{
// get the project list, and open all projects.
Array projects;
int i;
ProjectNode sharedProjects, privateProjects, projectNode;
projects = this.getProjectList();
sharedProjects = Infolog.projectRootNode().AOTfindChild('Shared');
if (!sharedProjects)
throw error("Error: cannot locate shared project node!");
privateProjects = Infolog.projectRootNode().AOTfindChild('Private');
if (!privateProjects)
throw error("Error: cannot locate private project node!");
for (i=1; i <= projects.lastIndex(); i++)
{
projectNode = sharedProjects.AOTfindChild(projects.value(i));
if (!ProjectNode)
projectNode = privateProjects.AOTfindChild(projects.value(i));
if (projectNode)
projectNode.getRunNode();
else
warning(strFmt("Project %1 cannot be found.", projects.value(i)));
}
}
(I probably found the code to open a project from this blog post, or a similar one.)
Now, we will create three new “action” menu items:
- AjhDevStartupProjectAdd – to add a project.
- AjhDevStartupProjectRemove – to remove a project.
- AjhDevStartupProjectOpenAll – to open all projects.
Each one will have ObjectType set to “Class”, and the object will be our class, “AjhDevLaunchStartupProjects”. The static main() method in our class will use args.menuItemName() to determine which action to take.
Here’s that method:
// https://gist.github.com/andyhuey/5315559
public static void main(Args args)
{
AjhDevLaunchStartupProjects obj = AjhDevLaunchStartupProjects::construct();
SysContextMenu contextMenu;
str projectName, x;
;
// should always be called from a menu item.
if (!args.menuItemName())
{
return;
}
// if called from the add-ins context menu...
if (SysContextMenu::startedFrom(args))
{
contextMenu = args.parmObject();
projectName = contextMenu.getFirstNode().treeNodeName();
}
switch (args.menuItemName())
{
case menuitemActionStr(AjhDevStartupProjectAdd):
obj.addProject(projectName);
break;
case menuitemActionStr(AjhDevStartupProjectRemove):
obj.removeProject(projectName);
break;
case menuitemActionStr(AjhDevStartupProjectOpenAll):
obj.openAllProjects();
default:
return;
}
}
The add and remove menu items will be added to the SysContextMenu. This way, they will show in the context menu under “add-ins”. The “open all” menu item will be added to the DevelopmentTools menu. This way, it will show under the “Tools” menu in MorphX.
We will also change the “verifyItem” method of the “SysContextMenu” class, so that the add & remove items will only show in the context menu for projects (and not for other objects). (If we wanted to go further with this, we would also add logic here to show only one or the other option, depending on whether or not the project is already on the startup list.)
Here’s the code that we will add to “verifyItem”, at the end of the large case statement there:
// https://gist.github.com/andyhuey/5315566
// ajh 2013-04-03: my own startup project thing...
case menuitemActionStr(AjhDevStartupProjectAdd):
case menuitemActionStr(AjhDevStartupProjectRemove):
if (firstNode.handle() != classNum(ProjectNode) || !match(#pathProjects, firstNode.treeNodePath()))
{
return 0;
}
return 1;
So I think this is all pretty straightforward. My purpose in writing this up in such detail was largely so that I could get a bit of X++ code on this blog, and in the hope that someone else might find this useful. I haven’t had the chance to write much general-purpose code at my current job, so there isn’t much I’m working on that would be appropriate to post here, but this seemed like a worthwhile little project to work on, and hopefully it may prove helpful to someone else.
