not quite minimalistic enough  

2020-04-26

See hugo go.

… and to think it only took me three months to notice that the front page was empty, and only another three to fix that.

2019-10-30

In excess of requirements

Well, Jabra, of course your “Jabra Direct” headset setup application is Chromium based, or whatever enormous rendering engine is en vogue today. After all, the application has at least five pages to show, and ten buttons or so, so clearly you need a full-blown web browser to show this surfeit of UI.

And of course this means that the two-bit application comes in at five processes. Efficiency is for the wimps!

And yes, of course closing the windows only does exactly that, but leaves the five processes running forever, doing God knows what, and with no sign whatsoever of their presence (such as a tray icon or so).

Another entry on the list of sometimes useful applications that nonetheless get installed only when needed and then removed immediately afterwards.

2019-10-22

Oh no, not again ...

The Python-on-Windows people are at it again. This time they have deliberately broken os.path.expanduser() in 3.8.

Until 3.7, expanduser() treated a tilde at the front of the path given to it the same as a *ix shell, i.e. ‘~/’ was replaced by the current user’s home directory, and ‘~user/’ with that of user user. More specifically, it used the value of the HOME environment variable, or USERPROFILE if the former did not exist, or HOMEDRIVE\HOMEPATH as a final fallback (on NT 3.51, perhaps?).

Then someone complained about that, Python bug #36264, and for some reason unknown to the world, it was decided not to consider HOME anymore.

This (and I’m speaking out of a deep personal animus) was the most misguided decision since splitting the Windows distribution into 22 MSI packages per architecture.

Why?

Because the supposed rationale for the change is that HOME is not a “special” variable on Windows, i.e. it is not something the system/shell cares more about than any other environment variable.

So what? It was documented that it was used by expanduser(), and that is what matters. Explicitly mentioning some behavior in the documentation, without a note that it is an implementation detail subject to change, is what interface contracts are made of.

The documentation does not make any claims that HOME is used because it is of any particularly exalted rank, it simply says it is used. The relevant paragraph could even be read simply as “the user’s home directory, unless overridden with HOME”.

In a particularly cruel twist, the original complainant even pointed out that their problem was actually caused by a bug in MSYS, but the Python-on-Windows maintainer apparently felt that this localized problem with a single tool merited breaking part of the Python standard library for everyone. (The tool was Git, but still …)

2019-08-22

Goodbye Mercurial; it was nice knowing you.

Atlassian have made the extremely regrettable decision to stop supporting Mercurial on Bitbucket, suggesting that everyone migrate their repositories to Git. (They say they “considered” developing an automated migrator, but ultimately they decided to wash their hands of the whole affair and just abandon their customers.)

There does not appear to be a viable alternative hosting solution (by which I mean, none of the dozen or so I looked at are any good), and I’m not going to run my own server; I have better things to do with my time.

Unfortunately, this means that a lot of that time I have the aforementioned better things to do with will be spent converting quite a few Mercurial repos to Git, and learning how to use that crime against sanity and humanity, Git.

I have been a user of the excellent TortoiseHg for many years now, but apparently this is now going to change. I hope the project will keep going.

Thanks for nothing, Atlassian.

2019-07-06

You missed some.

Microsoft left some things in the Windows 10 1903 release that crept in during development and should have been removed.

There is certainly a lot more I have not yet encountered.

2019-07-02

If it just _has_ to be the command line.

Intel’s track record with Windows 10 drivers for their network chips is … well, “spotty” might be the word. For some as yet unexplained reason, after a new “functional update” comes out, it always takes Intel months to get a driver release out that will support ANS (Teaming and VLANs) on that Windows version.

Recently they also have removed the GUI for configuring the more advanced features, such as creating VLAN interfaces (it was called “PROset for Device Manager” or something), so now that has to be done in PowerShell. That wouldn’t be so bad, if there was not also another bug somewhere: As long as any ANS VLAN interfaces exist, the basic “*-NetAdapter” cmdlets do not work anymore; they complain about an “invalid parameter” in some WMI operation. Remove all the VLANs, and it works again as if nothing had happened.

In the early announcement for the latest driver release 24.1, Intel said that “[t]he Team and VLAN configuration issues are expected to be resolved in the next SW Release available in early Q2 (April/May)". At least I assume that refers to 24.1, because that is also the first release to support VLANs on 1903 at all, and the above is part of Intel’s standard response to forum questions about VLANs on 1903.

No such luck (or it was not meant to refer to the WMI issue). Still the exact same error.

This is a problem for those who want to rename their interfaces from “Ethernet 1” etc. because Rename-NetAdapter is also affected.

However, there is a workaround using an older (I think) version of the WMI classes. The more recent root\StandardCIMv2\MSFT_NetAdapter class is used by the *-NetAdapter* cmdlets and transitively breaks them all, but the good old Win32_NetworkAdapter class is still around and still works.

To change the interface alias (=name) of a network connection, you can still use both PowerShell

Get-CimInstance -Namespace root\cimv2 `
                -ClassName Win32_NetworkAdapter `
                -Filter "DeviceID=6" `
    | Set-CimInstance -Property @{NetConnectionID="MIRRORING"}

and WMIC

/interactive:off NIC where DeviceID=6 set NetConnectionID="MIRRORING"

. Without the switch in front there will be a confirmation prompt.

You can get the DeviceID from either

nic get DeviceID,Name,NetConnectionID

or

Get-CimInstance -Namespace root\cimv2 -ClassName Win32_NetworkAdapter `
    | Select-Object DeviceID,Name,NetConnectionID

The output is identical, except that wmic does not underline column headers.

Or you can use netsh, if you don’t care about the deprecation warnings.

netsh interface set interface name="Ethernet 1" newname="MIRRORING"

2019-06-29

Saving some typing.

One item on my C++ wishlist is a syntax for inlining typedefs into the base class list on a class declaration:

class CMyClass
    : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>
    , public ATL::CComCoClass<CMyClass, &__uuidof(MyClass)>
    , public ATL::IConnectionPointContainerImpl<CMyClass>
    , public ATL::IConnectionPointImpl<CMyClass,
                 &__uuidof(IMyClassEvents)>
    , public ATL::IConnectionPointImpl<CMyClass,
                 &__uuidof(IMyClassOtherEvents)>
    , public IMyClass

The two connection points result in a duplicated name, m_vec. To get the list of listeners to deliver any given event to, contortions like ATL::IConnectionPointImpl<CMyClass, &__uuidof(IMyClassOtherEvents)>::m_vec are necessary. These usually become typedefs:

private:
    typedef ATL::IConnectionPointImpl<CMyClass, &__uuidof(IMyClassEvents)> events_cp;
    typedef ATL::IConnectionPointImpl<CMyClass, &__uuidof(IMyClassOtherEvents)> otherevents_cp;

Then a relatively simple otherevents_cp::m_vec leads to the right container, but it requires regurgitating the entire base class type in the typedef.

Something like this would be really nice to have instead:

class CMyClass
    : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>
    , public ATL::CComCoClass<CMyClass, &__uuidof(MyClass)>
    , public ATL::IConnectionPointContainerImpl<CMyClass>
    , public ATL::IConnectionPointImpl<CMyClass,
                 &__uuidof(IMyClassEvents)> [private: events_cp]
    , public ATL::IConnectionPointImpl<CMyClass,
                 &__uuidof(IMyClassOtherEvents)> [private: otherevents_cp]
    , public IMyClass

Wouldn’t it?

Why stick that there?

I know it’s because the class is from waaay back when the SBCS APIs were still actually being used, but …

// Extract a const wchar_t*
//
inline _bstr_t::operator const wchar_t*() const throw()
{
    return (m_Data != NULL) ? m_Data->GetWString() : NULL;
}

// Extract a const char_t*
//
inline _bstr_t::operator const char*() const
{
    return (m_Data != NULL) ? m_Data->GetString() : NULL;
}

BSTR is a Unicode string, and the second extractor above converts it to ANSI. This, unfortunately, results in ambiguous-overload errors whenever a _bstr_t is passed to anything that can accept both forms.

There should really be a way to, say, #define _BSTR_T_NO_ANSI_SUPPORT.

2019-06-28

Library Science!

Huh? I thought type libraries could only represent the Automation compatible types?

Good to know. #import is much easier than writing all the wrappers myself, particularly because I’ve been rather generous with the property attributes this time.

Templates. It's always the templates that get you.

Problem

You are developing a COM object that supports outgoing events (source interfaces). You get a compiler error similar to

C2440: ‘static_cast’ cannot convert from ‘CMyClass::_atl_conn_classtype *’ to ‘ATL::_ICPLocator<IID_IMyClassEvents> *'. Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast.

on a CONNECTION_POINT_ENTRY() line:

class CMyClass
   : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>
   , public ATL::CComCoClass<CMyClass, &CLSID_MyClass>
   , public ATL::IConnectionPointContainerImpl<CMyClass>
   , public ATL::IConnectionPointImpl<CMyClass, &__uuidof(IMyClassEvents)>
   , public IMyClass
{
public:
   CMyClass();

   DECLARE_PROTECT_FINAL_CONSTRUCT()

   BEGIN_COM_MAP(CMyClass)
      COM_INTERFACE_ENTRY(IMyClass)
      COM_INTERFACE_ENTRY(IConnectionPointContainer)
   END_COM_MAP()

   BEGIN_CONNECTION_POINT_MAP(CMyClass)
      CONNECTION_POINT_ENTRY(IID_IMyClassEvents)    // <-- C2440
   END_CONNECTION_POINT_MAP()
...

Analysis

The IIDs in the IConnectionPointImpl base class and the CONNECTION_POINT_ENTRY are not the same symbol. The cast fails because it attempts to convert to a base-class pointer that is not a base class, but a separate specialization of the same template.

Solution

Use either the predefined constants (IID_IMyClassEvents) or the MIDL metadata based constants (__uuidof(IMyClassEvents)) in both places; do not mix them.