in

MSMVPS.COM

The Ultimate Destination for Blogs by Current and Former Microsoft Most Valuable Professionals.

Cluebat-man to the rescue

A weblog dedicated to Visual C++, interoperability and other stuff.
  • Regex bug in VC2008 SP1 TR1 library

    Yesterday I tracked down a bug in the TR1 regex library that is shipped with VS2008 SP1.

    If you use regexes, then the regex a| will cause an exception to be thrown because of supposedly illegal syntax. For example you could use (a|) in a regular expression to indicate that a string contains at a certain point either a or nothing.

    There are better ways to do this of course, and I've changed the problematic regex already, but it should have worked.

    I checked the .NET regexes, and they accept this syntax. .NET regex follows the ECMAScript syntax, which specifies pretty unambiguously in section 15.10.1 (Thanks Igor for helping me identify the correct section) that the alternative operator should accept empty sections.
    The TR1 proposal also specifies that ECMAScript is used, so it should accept this syntax.

    If you use TR1 regexes, take a minute of your time to vote for this bugreport on connect so that they fix it in the next SP / release.

    Posted Sep 04 2008, 04:46 AM by vanDooren with no comments
    Filed under:
  • Extending a native C++ project with managed code

    One question that comes up from time to time in the newsgroups is ‘I have a native C++ project and I want to extend it with Managed code (e.g. Windows Forms). What do I do?’

    The answer is not so complex. It is fairly easy to extend native projects with managed code. In this article I’ll explain how.

    What NOT to do

    To quote Kate Gregory ‘In the name of all that is good and right: Do not set /CLR for the entire project’.

    /CLR tells the compiler that it should compile a source file as C++/CLI code in which it finds both native and managed C++ code. Theoretically you could specify this for the whole project, but this has some serious consequences.

    Apart from the fact that it is possible for the compiled output size to explode, there can be significant problems with COM and CRT initialization. I am no interop expert in the matter like Marcus Heege or Kate, but I am willing to take their word for it.

    Furthermore, your existing project is possibly validated by QA en unit tested 7 days from Sunday. You don’t want to travel that road again if you can prevent it.

    What to do

    You want to add managed stuff to your project while impacting the rest of the code as little as humanly possible. To achieve this you have to compartmentalize the managed stuff and give it a native interface that you can use in the native parts of you projects without any hassle.

    I think I can best explain this with a practical example.

    For the sake of this example I have a native DLL project that exports a function that returns an integer value. Perhaps this function got that integer value previously through an MFC interface, and now that value has to come from a Windows Forms interface.

    Add the windows form to your project

    This is the first and also the easiest step of the process. Rightclick your project and select ‘Add…->New Item’ and select ‘UI->Windows Form’ in the Visual C++ dialog.

    You will then get a message box, telling you that your project will be converted to a managed project. Here you click ‘yes’. Even though you don’t want to compile your project with /clr, Visual Studio itself needs to know that you are doing managed stuff in your project. This is not necessary for compiling your project, but if you want to have the benefit of working with the forms designer and other .NET related things, then it would be a good idea. And you cannot add the form if you choose ‘No’ so it’s not like you have much choice anyway.

    Now you have a .NET Windows Form in your code. You can verify the file specific settings if you want, but the cpp file will be compiled with the /clr flag set, and without the use of precompiled headers. Not using precompiled headers is important, because the default precompiled header is compiled without /clr set, and this would lead to conflicts.

    Of course, if you need to, you can create a copy of StdAfx.h/cpp cpp files called ‘StdAfxClr.h/cpp’ add them to your project, and configure them to create a managed precompiled header, which you could then use for all files that are compiled with /clr. This is not necessary for small projects, but it could be a useful optimization in large projects.

     The interface layer

    At this point you can compile and link the entire project, but your native code isn’t yet using the new managed functionality. And because the native code will not be compiled with /clr, it will never do so. In order to make that happen, you will need a thin layer between the native and managed code. This layer will have a native C or C++ interface which can be called by the native code, and a managed implementation that will do all the .NET stuff.

    In our example, the interface is 1 simple C style function in Interface.h:

    int __stdcall DoManagedStuff(void);

    And this function has a simple implementation in Interface.cpp:

    int __stdcall DoManagedStuff(void)
    {
          DemoForm ^df = gcnew DemoForm();
          df->ShowDialog();
          return df->Value;
    }

    Interface.h and Interface.cpp are 2 new files that you have to add to your project. You have to manually configure the cpp file to be compiled with /clr, and to not use precompiled headers.

    As you can see, the interface layer provides a clean native interface for the managed stuff that you want your code to perform. Of course, you are not limited to C style interfaces. You can also work with classes and make classes with a native interface and a managed implementation. But there are a couple of issues that you need to be aware of. If you want to go there, then it would be a good idea to read the paper written by Herb Sutter which explains the rationale behind C++/CLI, as well as some of the limitations and pitfalls.

    Actually, reading that paper is a good idea for anyone working with C++/CLI who also cares about understanding what is actually going on behind the scenes.

    Using the interface layer

    All the hard work is done. Now you can simply include Interface.h in your native code files, and call ‘DoManagedStuff’ where appropriate.

    #include "stdafx.h"
    #include
    "InterfaceLayer.h"
    int __stdcall DoFoo(void)
    {
          return DoManagedStuff();
    }

    Conclusion

    As you can see, extending native code with managed code is not so hard. At least, it isn’t if you maintain a clean break between managed and native code. If you cannot do this, things might become more difficult. For example, using .NET controls on an MFC dialog, or using .NET remoting in a native COM project are things that can be much more tricky.

    Another thing you should be aware of is that not all compiler switches can be used in conjunction with the /clr  switch. The compiler will inform you if it detects this. The combinations which are not allowed are documented, and can be found in the documentation of the /clr switch itself.

    This post was not meant to be an exhaustive how-to to those complex scenarios, but instead an explanation behind the basic ideas.

    The demo project for this article can be downloaded under the MIT license as usual.

  • Fun with templates: parsing command line arguments

    One of the things that everyone has to do sooner or later is parsing command line arguments into program variables. Even the most trivial command line application needs some input variables to tell it what to do.

    One of the things in which C and C++ are lacking is a unified approach to command line arguments. This allows anyone to do what he wants, but unfortunately it also forces everybody to figure it out for himself.

    I have done this several times, and tried several approaches. My last projects all needed moderately complex command line configurations, so I finally solved this problem in a reusable way. Originally I used the boost template library for this (www.boost.org). Specifically, I used regular expressions. But now that VS2008 SP1 is out, I can use the TR1 library to do this for me.

    What does a command line argument look like

    The exact syntax doesn’t matter because we are using regular expressions. What is important is that the identifier and the value are recognized by the shell to belong together.

    The only way to do this is of course to make sure that they are in the same string. For example, such command line arguments can look like this:

    -val:12.5
    /text=blabla
    -file=”C:\Documents and Settings\me\desktop\article.doc”


    It really doesn’t matter. As long as all the information is recognized as 1 argument, it’s fine. If the value contains spaces, you need to use quotes so that the shell will not treat

    -file=”C:\Documents and Settings\me\desktop\article.doc”

    as 3 arguments.

    Requirements

    The requirements for my solution are as follows:

    • 1 function which can take a command parameter and a regular expression, and which can parse any given type (bool, int, string, …) from the parameter, according to the specified regex.
    • The function should be able to handle string and wstring parameters.
    • It should be able to put values into regular data types, as well as into TriStateValue template types (see here http://msmvps.com/blogs/vandooren/archive/2007/10/11/fun-with-templates-implementing-a-tri-state-value.aspx for more info).
    • The function should return a bool to notify the user if the argument was parsed.
    • The part of the regex that identifies the actual value has to be captured. I.e. it has to be enclosed between ( ) symbols.

    First attempt

    The first version of such a function was ready pretty rapidly.

      template <typename T>
      bool ParseArg(
        std::tr1::regex const& pattern,
        std::string const& arg,
        T& value)
      {
        std::tr1::smatch matches;
        if( !std::tr1::regex_search(arg, matches, pattern))
          return false;

        std::istringstream iss((string) matches[1]);
        return ! (iss >> std::dec >> value).fail();
      }

    The function takes a regex and an argument. The value type is a template type which allows the user to use it for any type. The type itself can be inferred at compile time. I.e. the user does not have to explicitly specify the template type using brackets.

    A string stream is used for getting the value out of the stream. This is very handy because this way, the text to value conversion has no dependency on the value type. By using the string stream, the function remains generic.

    This function has an overload that uses a TriStateVal type for the resulting value.

    template <typename T>
      bool ParseArg(
        std::tr1::regex const& pattern,
        std::string const& arg,
        TriStateVal<T>& value)
      {
        std::tr1::smatch matches;
        if( !std::tr1::regex_search(arg, matches, pattern))
          return false;

        std::istringstream iss((string) matches[1]);
        T val;
        if((iss >> std::dec >> val).fail())
          return false;

        value = val;
        return true;
      }

    The TriStateVal type allows the user of that value to know whether it had been assigned or not. Unfortunately, there is no support yet for streaming directly into a TriStateVal type, so I have to use a temporary value first.

    Of course, these 2 functions work for strings. What about wstring? Well, for wstring we need another 2 overloads.

      template <typename T>
      bool ParseArg(
        std::tr1::wregex const& pattern,
        std::wstring const& arg,
        T& value)
      {
        //
      }

      template <typename T>
      bool ParseArg(
        std::tr1::wregex const& pattern,
        std::wstring const& arg,
        TriStateVal<T>& value)
      {
        //
      }

    These are almost identical, except that they use wregex, wstring and wistringstream instead of regex, string and istringstream.

    The overload mechanism

    By now you may have wondered about the function overloading, if you are into template laws.

    There are 4 overloads (removed template specifier template <typename T>

     for clarity):

    bool ParseArg(regex const&, string const&, T&);
    bool ParseArg(regex const&, string const&, TriStateVal<T>&);
    bool ParseArg(wregex const&, wstring const&, T&);
    bool ParseArg(wregex const&, wstring const&, TriStateVal<T>&);

    It is simple enough to see how the compiler chooses based on the types of the pattern and the argument. That is via normal overloading rules.

    But how does it know when to pick the generic T template function or the more specific TriStateVal<T> template? Both can be valid.

    As it turns out, the compiler can follow the rules laid out in the C++ ISO standard section 14.5.5.2, which states that if multiple template functions are valid for the supplied template types, the most specific one will be selected.

    The wording is of course more complex and formal than the previous paragraph, but that is what it boils down to. Section 14.5.5.2.5 contains a number of helpful examples, and one of them is equivalent with the ParseArg function.

    TriStateVal<T> is more specific than T, so the function with that parameter type will be used whenever possible.

    Evaluation of the first attempt

    The first implementation works very well. You use the ParseArg function like this:

    wregex reFile(L"^[-/]file[:=]\"{0,1}([^\\?\\*/<>\\\"]*)\"{0,1}$");
    wregex reRows(L"^[-/]rows[:=]([0-9]*)$");
    wregex reCols(L"^[-/]cols[:=]([0-9]*)$");

    int _tmain(int argc, _TCHAR* argv[])
    {
      int numRows = 0;
      TriStateVal<int> numCols;
      wstring file;
     
      for(int i=0; i< argc; i++)
      {
        wstring arg(argv);
        if(ParseArg(reRows, arg, numRows))
          continue;
        if(ParseArg(reCols, arg, numCols))
          continue;
        if(ParseArg(reFile, arg, file))
          continue;
      }

      wcout << "numRows : " << numRows << endl;;
      wcout << "numCols : " << numRows << endl;;
      wcout << "file : " << file << endl;;

      return 0;
    }

    As you can see, no matter how many command parameters there are and how complex their formatting is, parsing them remains trivial if you can correctly specify the regular expressions.

    The regular expressions in my example also take care of the fact that users can use either the – or the / to precede identifiers, and that the value delimiter can be a = or : sign.

    The great benefit of the TriStateVal is that you don’t have to keep track of Boolean variables, indicating the status of a variable. I.e. you don’t have to manually keep track of which variables were assigned.

    If your application can do several things, based on a ‘command’ parameter for example, then you can check the TriStateVal variables for that command to see if those have been assigned to. If will make your whole program easier to understand.

    Problems with the first attempt

    One  issue is that it sadly doesn’t work if T is of type ‘char’ or ‘wchar_t’. The reason is that these types are the character types which make up ‘string’ and ‘wstring’, and streaming from a string stream into a char is not supported.

    Another possible issue is that in the case that T is of type bool, the text value has to be 1 or 0. Perhaps we would also like to be able to use ‘on’ and ‘off’ as valid value texts, or ‘high’ and ‘low’.

    Both problems can be solved by providing more specific template functions, like (removed template specifier

     for clarity):

    template <> bool ParseArg(regex const&, string const&, bool &);
    template <> bool ParseArg(regex const&, string const&, char &);

    But if we want to implement those functions, we not only have to implement the string-regex function, but also the wstring-wregex function, and the functions that use TriStateVal parameters.

    So instead of having to write 2 additional functions, we would have to implement 8 functions.

    We could partially fix that by making the regex and string parameters templates instead of qualified types, but that does not fix the problem of the types that are used internally (smatch and istringstream).

    Of course, we could make those template arguments as well, but that would break automatic type inference, and force the programmer to specialize the template function explicitly, which would be ugly and confusing.

    So instead we use a trick that is also used in the STL itself: we use a helper class that deduces those internal types for us.

    Second attempt

    The key to the second attempt is to use a helper class that –through specialization- will specify the dependent types.

    The coat hanger for this mechanism is the empty class

      template <typename strType>
      struct __pca_typehelper{};

    which has 2 specializations:

      template <>
      struct __pca_typehelper<std::string>
      {
        typedef std::tr1::smatch MatchType;
        typedef std::istringstream SStreamType;
        typedef std::tr1::regex RegexType;
      };

      template <>
      struct __pca_typehelper<std::wstring>
      {
        typedef std::tr1::wsmatch MatchType;
        typedef std::wistringstream SStreamType;
        typedef std::tr1::wregex RegexType;
      };

    Depending on which specialization is picked, MatchType, SStreamType and RegexType are typedef’ed to the correct STL and TR1 types.

    And the nice thing is that is the user supplies something other than string or wstring, compilation will fail at this stage already, because those typedefs don’t exist.

    Using that helper class, the ParseArg function can be written like this:

      template <typename Targ, typename Tresult>
      bool ParseArg(
        typename __pca_typehelper<Targ>::RegexType const& pattern,
        Targ const& arg,
        Tresult& value)
      {
        typename __pca_typehelper<Targ>::MatchType matches;
        if( !std::tr1::regex_search(arg, matches, pattern))
          return false;

        typename __pca_typehelper<Targ>::SStreamType
          iss((Targ) matches[1]);
        return ! (iss >> std::dec >> value).fail();
      }

    As you can see, there are now 2 template arguments: Targ and Tresult.

    The meaning of Tresult is still the same as in the previous implementation.

    Targ is new, and is the type of the argument that needs to be parsed. In our example it is either string or wstring. This type is then used to specialize __pca_typehelper so that the type of the regular expression can be deduced:

    typename __pca_typehelper<Targ>::RegexType

    The same goes for the internal variables ‘matches’ and ‘iss’

    The implementation for the TriStateVal<Tresult> specialization is very similar to the one for Tresult so I am not going to repeat that here.

    Evaluation of the second attempt

    We got rid of the code duplication (which is good) and managed to have some fun in the process of doing so. At least I did. J

    The code still behaves as it did previously, so using the ParseArg function hasn’t changed at all.

    We still have the issues about bool and char, but at least we can now solve this problem with a lesser number of specializations (4 instead of 8).

    Conclusion

    My implementation of ParseArg works good, and is easy to use. I’ve been using it for some time, but used boost for the regexes.

    I would like to try and get the TriStateVal<T> and T scenarios to be handled by the same function. That would require providing a >> stream operator for TriStateVal<T> and I don’t know how much work that is.

    I feel like giving this a try, but I am not going to wait with publishing this article. For one thing, it is already lengthy enough, but it also won’t matter from the user’s point of view. The usage of ParseArg will not change, so I feel it is perfectly acceptable to leave this optimization for another article.

    The code of this article is available for download as always.

    And as always, if you have any comments or feedback, please leave a comment at the bottom of the page.

     

    Posted Aug 14 2008, 05:17 AM by vanDooren with no comments
    Filed under:
  • Access != database

    While working on a data application for the finance guys, I already discovered that Excel sucks when used with OleDb. It seems as if Excel was specifically designed to make your life as a programmer miserable.

    Fair’s fair: Excel is not a database, so perhaps it is acceptable if the data link layer feels as if it has been thrown together by a vba hacker without a clear grasp of data types and interfaces. Probably they needed another handful of buzzwords on the Excel box, and decided to hire a high-school summer intern who installed basic once.

    But I digress.

    While I am willing to let Excel off the hook for not being something it was not supposed to be, I have a problem with extending the same courtesy to Access; an application specifically designed to be a database.

    For the last couple of hours I have been debugging the finance app because some of the allocated items showed up as having cost nothing. This would have enjoyed the CFO immensely if it had been true, but since that wasn’t the case, they were wondering why my app insisted it. For some systems the totals and the details were correct. For others they were zero, or something far less that what they had cost in reality.

    I examined a correct example, compared it with one of the problem cases, and found that all required data was there, in the correct tables. Then I debugged through the code, and the algorithm seemed to work just fine. Only for some systems it didn’t return any values. And since this was done via LINQ, debugging the actual SQL was difficult.

    Then I decided to go spelunking in the raw data tables themselves. Again and again I checked, and nothing seemed to be wrong. But then it suddenly jumped at me:

    tbl_keymstr -> row 1234 -> Alloc_key == ‘all’

    tbl_alloc -> row 123456 -> Alloc_key == ‘All’

    How could this be possible? I double checked, and verified that the links were all defined with the ‘Enforce referential integrity’ flag set.

    After some testing, it seems that Access is pretty loose in its judgments. When it comes to comparing strings, ‘equals’ really means ‘kinda looks like’, so ‘All’, ‘all’ and ‘alL’ are all the same for access.

    The LINQ queries in my app all use the C# ‘==’ to define joinings and equality operations, so if the rows in 1 table say ‘All’ and those in the other say ‘all’ the result of the joined set is empty of course.

    Key definitions and cost allocations get uploaded separately, and my app doesn’t check whether the key fields are spelled the same. Everything gets uploaded, and the integrity is insured by the database itself, as it should be. If there is an upload error it gets reported and everything is rolled back. Unfortunately, key value comparison does not work that well.

    The fix was very simple: I implemented a case insensitive comparison in my queries, and the problem was solved. Too bad Access is allowed by the Office team to let sloppy input through.

    EDIT: I just checked, and by default, SQL server has the same behavior. But you can change it to case sensitive if you want, which is important in scenarios like these. Granted, I should have checked first before slagging off Access, but I still think that this should be an option in Access. The fact that it isn't is a severe shortcoming in my eyes, since lots of smaller databases use strings as keys. In case sensitive clients (like e.g. C# apps by default) this causes a lot of work to get correct results. And if you forget to case insensitivize (is that even a word?) your queries even once, you will get incorrect data.

    Posted Jul 14 2008, 01:27 AM by vanDooren with 3 comment(s)
    Filed under: , ,
  • Another year

    3 days ago I got 'the email' again. I can call myself MVP for another year.

    While I am glad I made it, I have to admit, the suspense and excitement are getting less and less. The first time I knew I was nominated, and the wait was like being a kid, waiting for Santa. And when I got the mail, I spent hours reading all the info, browsing the MVP site, reading private newsgroups...

    The first time I was up for renewal, I was anxious to see if I made it again, and the wait was very uncertain.

    This year I was a lot more relaxed, and when I got the mail I registered again, clicked 'next' a couple of times, and decided to call it a day when I was done.

    Don't get me wrong, I still like being an MVP, doing MVP things as much as I did in the beginning, but this is a marathon, not a sprint. When you hear the starting signal, there is a lot of activity and excitement, but after that initial phase, you settle into your rythm and follow your own pace. A marathon runner doesn't accelerate every time he comes across a landmark. He just maintains his pace because that is the way to endure.

    Anyway, YAAY me.

    Posted Jul 04 2008, 01:25 AM by vanDooren with 1 comment(s)
    Filed under:
  • Scheduling tasks via a batch file: where am I?

    One of the things that comes with configuring software for a controlled environment is that every single thing involved has to be documented. Some people fail to realize what this means.

    It means that my installation cannot contain a trivial phrase like 'Add xyz.exe to the scheduled tasks, and have it run every night with these credentials'. Instead, I have to write something fit for 'Deployment for dummies', mentioning every single click, selection and user entry.

    This may seem ridiculous, but otoh the purpose of these procedures is that someone without knowledge of this specific deployment can simply follow the procedure, and end up with a system that is identical to the previous / other one. And it also has the advantage that the procedure documents which files / user accounts / other resources are required for the system.

    It also means that it can be a daunting task to create and test app deployment. In my case I often choose to build a script file that is part of an XCOPY deployment, and have the administrator (me) run a script.

    I usually opt for the script, because it is human readable (with a definition of human = administrator) and you can read them later in case you need to check how something was done. And the major advantage of scripting things is that I don't need human interaction -> I don't need to write an installation manual that is as verbose and comprehensible as the Silmarillion.

    Anyway...

    One of the issues with scripts is that a script has to know where the other stuff is which it is supposed to install. Sometimes you can get away with assuming it is in the present working directory %CD%, but oftentime you can't. And hard coding path names is not a safe option.

    It took some googling, but it turns out that the environment variable %~dp0 does what I want (thank you Wes Haggard) . It expands to the physical location of the script file that is currently being executed. From that point you only need to know the location of the other files relative to the installation script, and Bjorn Stronginthearm's your uncle.

    Some of the software I develop runs on systems where it gets scheduled to execute at specific times, and I use schtasks.exe to configure those tasks in my installation script. Interesting tidbit: if you want to use schtasks to schedule a command which contains spaces, you have to enclose the command path inside the /TR argument with \" quotations so that the task scheduler doesn't get confused. It cannot handle spaces in paths.

  • Ntbackup.exe and the task scheduler

    Last week we discovered that our weekly backup had failed. The only clue we had was the return code 0x1f. There were no log files, or messages in any of the event logs.

    It was already the second time this had happened, but the first time the return code was 0.

    After some googling I discovered that the return code can sometimes be 0, even if there was an error. So that might explain why I got that the first time. Then I also discovered that 0x1f seems to be a very generic error.

    I read a lot of articles, but finally found the reason buried deep in this Microsoft KB article:

    If you use the /um option, it is recommended that you not use the /n option to label the media. Instead, permit Ntbackup to use the default date/time as the label name and description. This eliminates the problem of multiple tapes' having the same label name, which can cause RSM to ask for a manual tape mount and prevent Ntbackup from continuing to completion unattended.

    The tape names and description were all unique, but the tape label was simlpy 'Weekly DCS Backup'.

    The reason we didn't notice this earlier is that I remove the tapes in time. Only last week I was importing some older tapes to retrieve old data, and the tapes were still in the loader, thus causing a label name conflict.

    Posted May 13 2008, 02:40 AM by vanDooren with no comments
    Filed under:
  • My daughter the running champion

     This weekend my daughter participated in the 'Kriebelcross' which is a running competition organized between different schools.

    If is all very informal, and it is intended to be a fun day out for the family, with drinks and hotdog, and a fun fair for the kids.

    Running competitions are arranged by year of birth, with separate runs for boys and girls. My daughter Kato is a very active young girl who likes to run, climb, and do all sorts of stuff that will turn my already greying hair white soon enough.

    Before the starting whistle sounded I explained several times what the point was of the whole event: run to the teacher on the other side of the field as fast as you can, and try to run faster than the other kids.

    So at the sound of the whistle they all took off. She hesitated at first because of all the sudden activity around her, but as soon as she saw the other kids running she took off and started to run as fast as she can.

    As we have experienced several times, usually at bad times, that can be very fast. Ever since she could walk, she wanted to run. And most kids her age can't really run, but even her day care parents used to say that Kato runs like an adult.

    Halfway across the field she was head to head with another kid, but then she really started to pump her legs and she zoomed across the finish line with a distance of 10 meters separating her from the second kid.

    Here she is in the middle. At that point I noticed that we had forgotten to dress her in something suitable for running, as opposed to all the other kids around us, but luckily that didn't matter too much. This was definitely a day to be proud of.

     

    Posted Apr 28 2008, 12:46 AM by vanDooren with no comments
    Filed under:
  • VC2008 feature pack released

    http://blogs.msdn.com/vcblog/archive/2008/04/07/visual-c-2008-feature-pack-released.aspx

    Finally we get TR1 with VC2008. Get it while it's hot. This allows me to move a codebase to VC2008 and removing the dependency on boost.

    Posted Apr 08 2008, 03:50 PM by vanDooren with no comments
    Filed under:
  • License server doesn't serve license

    Did you know that a Windows2003 Licensing server does not manage Terminal Server 'Per User' CALs?

    It is really stupid, but from a licensing point of view, a terminal server that is configured to use 'Per User' licenses only checks if it can find a license server. As soon as it does, the license server does the Jedi mind trick (These are not the licenses you are looking for...) and the terminal server becomes a free for all, limited only by the maximum number of connections configured by the administrator.

    At first I thought this could not possibly be true (noone would design anything that stupid, right?) but this and this quickly convinced me otherwise.
    What makes it double stupid is that the license server allows me to add 'per user' licenses, and then forces me to go through the whole activation obstacle course, only to ignore whatever licenses were added.

    The only way to make sure that our licensing is in order, is to run a nightly script to determine how many TS users we have, and then check if we have enough licenses.
    This also means that no matter how many per user licenses you install, they will always show 'N licenses installed, N available, 0 used'

    Posted Mar 19 2008, 06:41 AM by vanDooren with no comments
    Filed under:
  • It has to make business sense

    I had just downloaded FreeBSD 7.0 and I wondered if I could use it as a VMWare host. A quick visit to www.vmware.com taught me it is not supported. However, a lot of stuff can run on BSD in linux compat mode.

    Google pointed me to a VMWare forum where someone had started a thread to ask VMWare to add support for FreeBSD. That thread had received about 100+ replies, in 3 years time. Someone complained that 100 posts over 3 years time should be enough to convince VWMare to do this.

    Yeah right.

    Let's look at the math: 100 possible customers for FreeBSD. But a lot of VMWare customers don't need more than the free version of VMWare server. I use it in our poduction envirnoment as well. I have no need for the 'for pay' features. So VMWare doesn't make money from those people.

    Then there are a lot of unix sysadmins which posted that they would like to use BSD, but were using linux because they couldn't. Supporting BSD would add no value for VMWare, since those admins are already using it, but on another platform. Again VMWare doesn't make money.

    But what does it cost to support BSD?

    A lot. Each version of the VMWare product would need to get the same amount of QA testing and analysis. This is horribly expensive for shrink wrapped software which is used in business critical environments. And there is also the cost of maintaining the different code versions.

    It will cost VMWare a ton of money to support BSD hosts, at the risk of damaging their name if problems arise, all for maybe a couple of licenses that they would probably have sold anyway, but for a different host.

    As much as I would like this, ultimately businesses exist to make money, not to be nice. Being nice is only done when it adds measurable value. IBM does not support linux on their servers because they are nice people. They do it because they sell hardware and servers, and if a large number of important customers demands linux, that is what they will get.

    Posted Mar 15 2008, 04:42 AM by vanDooren with 2 comment(s)
    Filed under:
  • Getting rid of the duplicate SPN in Active Directory

    Last week I noticed an error in the domain controller event log with Event ID 11:

    Event Type:   Error
    Event Source: KDC
    Event Category:    None
    Event ID: 11
    Date:         2/29/2008
    Time:         1:43:18 PM
    User:         N/A
    Computer: SE-DOMAINCONTROLLER01
    Description:
    There are multiple accounts with name MSSQLSvc/ComputerName.DomainName.SysName.Company.Local:1433 of type DS_SERVICE_PRINCIPAL_NAME.
    For more information, see Help and Support Center at
    http://go.microsoft.com/fwlink/events.asp.
     

     

    The name of the computer in the SPN was one of the process control databases I had replaced earlier. Our process control servers each have a specific role, and their computer names are tied to that role. This is a side effect from the process control system software that we use, and I cannot change this.

    This means that the old server and the new server will have the same name.

    The process software also doesn’t allow me to change domain membership while the software is installed, and if anything goes wrong with installing and configuring the new server, I should be able to bring the old system back online as soon as possible.

    So I simply disconnected it, made the new server with the same name a domain member, installed the application, synchronized everything and the system worked fine. I checked the event log of the new server, but couldn’t see anything suspect. However, looking back through the DC system log, I discovered that the problem started at that exact time.

    I did a little bit of research, and I found out that the servicePrincipalName attribute basically tells anyone who wants to know that a service with a certain principal name (duh) is running with the credentials of the Active Directory account with which it is registered.

    Since a service with a specific ID can only run with 1 account, having duplicates on the network is bad.

    Using ldifde, I found out that the service principal name MSSQLSvc/ComputerName.DomainName.SysName.Company.Local:1433 was linked to the user account ‘XyzAdmin’ and the computer account ‘SE-XYZ01’

    Using adsiedit.msc, I had to delete one of the SPNs from its containing account. I checked the service on the SE-XYZ01 server, and the SQL server was configured to run as local service. This means that the correct SPN link is to the server account, and not the XyzAdmin account.

    Unfortunately I couldn’t check anymore because the old server was already ‘recycled’ but I seemed to remember that the SQL service was configured to run with the XyzAdmin account instead. When I deleted the link, I wrote an entry in the server logbook, writing down exactly what I removed where, and I also saved the deleted info in a text file ‘just in case’.

    From the moment I did this the error did not occur anymore, so I deleted the right SPN. Even if it would have been the wrong one, I could have put it back easily with either setspn, or adsiedit.msc.

    I think I will make it part of the server replacement procedure to make an ldifde dump before and after, so that I can more easily diagnose possible problems. I also added a line in my daily backup scripts to make a backup of this dump every night for solving problems like this.

    Another thing I thought of later was to make a disk image of the old server that needs to be replaced. That way I can uninstall the application, take the computer out of the domain correctly, and install the new server and still know for certain that if anything goes wrong, I can restore the old system to the exact same state from which I started without having to waste any time with the backup and recovery procedures, which can take a long time for certain servers.

    As an afterthought I asked my fellow MVPs what the point was of having SPNs in AD in the first place. After all, if a service runs with certain credentials, it will be authenticated when it starts, so what is the added value of registering that information persistent in AD?

    This is what MVP Joe Kaplan had to say:

    Kerberos uses SPNs extensively.

    When a Kerberos client uses its TGT to request a service ticket for a specific
    service, the service is actually identified by its SPN.  The KDC will grant
    the client a service ticket that is encrypted in part with a shared secret
    that the service account as identified by the AD account that matches the
    SPN has (basically the account password).

    In the case of a duplicate SPN, what can happen is that the KDC will
    generate a service ticket that may be created based on the shared secret of
    the wrong account.  Then, when the client provides that ticket to the service
    during authentication, the service itself cannot decrypt it and the auth
    fails.  The server will typically log an "AP Modified" error and the client
    will see a "wrong principal" error code.  I forget the exact error code and
    description, but hopefully that's close enough.  :)

    So, duplicate SPNs are very bad, much in the same way that duplicate UPNs
    are bad.  Both can cause Kerb auth to break and Windows uses Kerb for auth
    everywhere it can.

     

    Posted Mar 11 2008, 05:04 AM by vanDooren with no comments
    Filed under:
  • Excel and OleDb stupidity

    This afternoon I was working on a Windows Forms app for the finance guys, to help them allocate costs to systems, proportional to predefined allocation keys.

    The app has to import Excel spreadsheet files and perform all the database actions.

    The key columns to uniquely identify a cost are text values. Unfortunately, some of those key values do not contain letters, but only numeric characters. And this is where it sucks to have to work with Excel.

    This is because Excel knows no datatypes. You can specify formatting for cells, but Excel ignores that when someone asks for cell data. Instead, it scans the first couple of rows to guess the datatype. By default it checks the first 8 rows. If those contains mixed values, it uses a specified default type for those values that are not numeric.

    This means that if you use OleDb to retrieve values, the column type can vary per row.

    What can you do about it? Well nothing really. You can tweak some values, and hope that you will never encounter the corner cases that you cannot do anything about. There is plenty of information to be found. One good explanation was this.

    However, one of the finance guys gave me an incredibly useful tip, which you can use as a workaround. You have to manually make a couple of easy modifications to the excel file, and Excel will always use the text data type.

    1. Assume that the offending data is in column 1, and that the first row is the header row. 
    2. You insert 2 empty columns to the right of the offending column.
    3. Put an ' in the first cell of the first empty column (B2).
    4. Then enter =B2&B1in the cell B3.
    5. Select B2 and B3, and double-click the bottom right corner of the selection box. This will copy the data from there to the last row.
    6. B3 will now hold the data as text, because the ' tells Excel that no matter what is in the cell, it is text.
    7. Then you copy column 3, paste it as 'values only' over column 1.
    8. Delete columns 2 and 3 again.

    Now you can read the column in OleDb and always get text values for that column.

  • Differences between C++ and C#, part 3

    One of the things that C# (and VB.NET) programmers have to live with is non-deterministic destruction of their objects.

    The garbage collector was introduced in .NET to take care of memory leaks and remove the need for manual memory management. It does this by keeping track of references, and as soon as an object is no longer referenced, it ‘can’ be collected by the garbage collector.

    The ‘can’ is important here, because cleanup happens only when the GC thinks is should happen. On systems with lots of memory, and few memory allocations and releases, it is possible that this takes minutes or hours, or even doesn’t happen at all.

    This can be a real problem, because now you don’t have memory leaks anymore, but resource leaks.

    Suppose your app opens a file for writing, and does not explicitly dispose of the stream reference.

    FileStream stream =
      new FileStream(Path.GetTempFileName(), FileMode.Open);
    StreamWriter writer = new StreamWriter(stream);writer.WriteLine("Hello, world.");

    writer.Close();

    The file is written and flushed to disk, but as long as the garbage collector does not collect the ‘stream’ object, it will hold an open file handle that will prevent you or anyone else from accessing that file. To overcome this you have to make sure that the file is released. On way of doing that would be like this:

    FileStream stream = new FileStream(Path.GetTempFileName(), FileMode.Open);
    try
    {
      StreamWriter writer = new StreamWriter(stream);
      writer.WriteLine("Hello, world.");
      writer.Close();
    }
    finally
    {
      stream.Dispose();

    }

    You could also use the ‘using’ keyword, but the same holds true. It is easy to make mistakes, and if you have several of such objects in the same scope, then your code will become a convoluted mess of nested try/finally or using constructs.

    In C++/CLI, this problem can be solved differently.

    In native C++, they way you create an object determines whether it will live on the stack or in the heap. The location implies the way the object will be cleaned up. If it is on the stack, it will be released automatically when it goes out of scope.

    C++/CLI does not have the ability to create managed objects on the stack, but it supports stack like semantics. I.e. even if you use the declaration that would put the object in the stack, it is still created in the managed heap. But the syntax and the semantics are stack based.

    This means that in the following example, the stream object will automatically be released when it goes out of scope.

    FileStream stream(Path::GetTempFileName(), FileMode::Open);
    StreamWriter writer(%stream);
    writer.WriteLine("Hello, world.");

    writer.Close();

    And regardless of how many such objects we need to create or use locally, they will all be cleaned up automatically without needing ugly nested structures, and without needing extra lines of code.

    Of course, you still have to determine if this is something you want, because sometimes you need objects to live beyond the scope in which they were created. In that case you can use the gcnew operator to use heap semantics.

    FileStream^ stream = gcnew FileStream(Path::GetTempFileName(), FileMode::Open);

    C++ gives you the ability to choose the best approach, which is nice if you want to write correct code without wanting to increase the number of lines of code, and structural complexity.

    Posted Feb 27 2008, 05:52 AM by vanDooren with no comments
    Filed under: ,
  • gpupdate and psexec, and a moment of D'oh

    I had to do a security change today which required each XP machine to first update its policies, and then reboot to make sure that the required changes went into effect immediately.

    To do the update I used psexec in conjunction with gpupdate /force to tell each machine to update its policies remotely, and I discovered something funny: if no user is logged on to the remote machine, you'll get an error that the user settings could not be updated. Which is fair enough I suppose, except that it took me a while to figure out.

    To do the reboot I used psshutdown. Mental note to self: 'If I want to use psshutdown again to reboot all client machines on the network, I should not forget to specify -r' The maintenance people entered the server room just as I thought 'Hm, why is it taking so long for the computers to come back online...?' Hmm

    Of course when manufacturing noticed that they went down and didn't come back up, they were 'worried'. Luckily all our client machines are located in the server room, with kvm cables running through the plant so booting all of them back on was done in a minute.

    It was really cool to have the diagnostics window open and then 'BAM' drop every client node from the network at the same time.

     

    Posted Feb 23 2008, 07:46 AM by vanDooren with no comments
    Filed under:
  • Active Directory disjointed namespace problems

    Last week I was redlining SOPs (Standard Operating Procedures) on a test network for some of the Windows Domain specific situations we sometimes encounter on our process control network.

    This specific SOP handled Domain Controller promotion and demotion for our process network. It should be noted that in our process control network, Domain Controllers are also DNS servers.

    I made a mistake and completely screwed up the Active Directory. Instead of reloading the network, I decided to figure out what was wrong and solve it properly, since there was no rush.

    How I screwed up the domain controllers

    Just before I promoted the 2nd DC, I went to the system properties tab, where I made a crucial mistake. My procedure said to clear the DNS suffix, and I cleared the checkbox that said ‘change DNS suffix when domain membership changes’ instead.

    With 20/20 hindsight this was a pretty stupid thing to do. What this does is it prevents the new DC from getting the name ‘DC2.networkname.companyname.local’ and instead let it keep its old name ‘DC2’

    This problem is known as a disjointed namespace, where the FQDN of a server does not match the domain of which it is a member. Active Directory looks for FQDNs when it needs to replicate or do other things, so without a FQDN you get all sorts of helpful errors like ‘The RPC server is unavailable, this might be a DNS problem

    Again looking with hindsight, the error details and the requested names should have made it obvious that DNS was working just fine, but that the specified name was indeed not available in DNS.

    I tried various things to solve this problem, but the most stupid one was probably renaming DC2. I still don’t know why I thought this was a good idea. Perhaps to force a new name registration in AD?

    Of course this failed because Active Directory didn’t replicate, so the name change never propagated either. I had only made the problem worse. DC1 still thought that DC2 had its original name, and it wouldn’t even try to find DC2 at its new name.

    What I did to make it right again

    Making things right when you hose Active Directory is not easy (or sometimes downright impossible perhaps) but there is a way out of the aforementioned mess.

    Google turned up this page which explains what a disjointed namespace is, and it links to a Microsoft KB that has a script for making the DNS suffix of a server equal to the domain name.

    When that was done, I renamed the DC2 computer object on DC1 (which still had its old name) to the new name of DC2. I changed the TCPIP settings of both DCs so that DC1 became the preferred DNS server for DC2, and vice versa. This was to insure that they could resolve each other.

    I fixed the records in the DNS so that DC2s original name was not mentioned anymore, and I verified that the GUID associated with the DC2 alias record was indeed correct.

    At this point I could already synchronize from DC1 to DC2, but not the other way around. Running netdiag on DC1 I was informed that LDAP still had a reference to the original name of DC2, and that some DNS records of this DC were not registered correctly on the DNS running on DC2. It told me to wait 30 minutes in order for DNS server replication to succeed.

    I used adsiedit.msc on