Taking the application down even further than last time. Windows XP? You’re probably thinking: “Direct3D 11, Media Foundation, WIC, that’s never going to work in XP! What are you thinking?”
And you’d be right. If the codebase was entirely aimed at these technologies, then Vista was already about as far as we could stretch it. Yes, you could downgrade the framework to .NET 4.0 perhaps, but you’d still miss the support for these technologies.
However, that is not the entire story of this codebase. I joined this company a few years ago, and at the time it was already an existing product. I just took over maintenance and further development. Development originally started around 2008. At that time XP was not end-of-life yet, and .NET 4.0 would not yet have been available. So this codebase may actually have started life as .NET 3.5, and has likely targeted .NET 4.0 at some point in its lifetime.
When I started working on the codebase, it targeted .NET 4.6.2 (the code had been moved from an earlier version control system to a Git repository at some point, at which the history had been lost, so I do not know the exact details of early versions), but the main renderer was Direct3D 9. Media Foundation and WIC were not used yet either. Video was played with DirectShow, or with an outdated and somewhat buggy VLC implementation, and images were loaded via the built-in functionality of SlimDX.
One of the previous developers had already made a start with a Direct3D 10 renderer, but it was never finished. I upgraded that code to Direct3D 11 and finished it. But the code I started with, had always had support for multiple graphics APIs and video renderers that could be configured dynamically.
If it was started around 2008, then why would you target Direct3D 9 still? I was told that in the early days, the application actually ran on XP. Vista was skipped, and they moved from XP directly to Windows 7. Even on Windows 7 Direct3D 9 probably made a lot of sense given that we target embedded machines, usually with low-end Intel IGPs. And in 2008, those mainly still supported D3D9 (as you could read in the previous article, I only got the first beta driver for D3D10 for my Intel X3100 somewhere in 2008, and it was still shaky). I must say, it was ‘real’ Direct3D9 though. As in, it did not use the D3D9Ex version of the API that was introduced with Vista. I’m not sure if that was a conscious decision (given that the decision had been made to move to .NET 4.6.2, and thereby shut off XP entirely, and a start with D3D10 had been made), or if the previous developer simply did not know about the updates to D3D9 that Vista introduced. At any rate, I had added optional support for D3D9Ex as well, when I was working on the Direct3D 11 path.
So until recently, our installations certainly ran Direct3D 9. Once my Direct3D 11 renderer was done, it could be enabled in the configuration optionally. Once we were confident enough that all functionality was working, we made it the default. But I kept the Direct3D 9-path in there for compatibility. And I have kept it up-to-date with the other improvements, such as making sure it works with Media Foundation and WIC.
So the starting point here is a reasonably well-maintained D3D9-path, which has seen many years of active service in the past, and it was the ‘vanilla’ D3D9 version of the API, that has at one point worked on XP. I’ve just never actually seen it running on XP, since all development had been aimed at Windows 7 or newer machines by the time I joined. So the more recent fixes and enhancements are essentially untested on XP.
Any which way but run
Now that XP is the target, we’re stuck with .NET 4.0. This is a much bigger step backwards than .NET 4.6.2 was. Aside from that, some parts of the application *may* run, under the right circumstances, but they most likely won’t in the current state. That includes NAudio, Media Foundation, WIC and VLC (and of course CefSharp, which we had already given up on when moving to Vista).
So I figured the best strategy would be to just convert all projects down to .NET 4.0, and strip out all the parts that aren’t likely to work. I wanted to at least have some kind of baseline application that at the very least sets up Direct3D 9 and does some basic rendering. Then I would start adding code back in to see how much functionality we can get running in XP.
This will put you at a crossroads: will you make a custom build that works on XP, but is stripped from some of its functionality in order to do so? Or can you get it to a state where it runs on XP, but still retains all the other functionality when available? The .NET 4.6.2 version is the latter: it was made to run on Vista, but there was no need to compromise on any functionality. CefSharp is still there, if the OS supports it. All the other fixes were just minor sanity checks and workarounds. In this case, XP support may not be the biggest challenge. It may be the .NET 4.0 support, which might lock us out of some of the third-party libraries we are using.
Again cross-development? What about NuGet?
For Vista we were already stuck with Visual Studio 2010 at best. And I was already reluctant to use that. But for XP, we probably need to do even more investigation, debugging and trial-and-error to get things working, so let’s look at developing and debugging on the machine itself again.
Well, for starters, NuGet was never a part of Visual Studio 2010. NuGet was introduced as an extension for Visual Studio 2010. Great, so can we install it? No, we can’t, because Visual Studio 2010 is out of support. If you try to install extensions, you’ll find that it cannot access the repository.
Okay, so can we install it manually then? Why yes, we can. You can still find the NuGet extension online. But once you installed it, does it work? No, it does not. The latest version for 2010 is 2.8.3. It only speaks the v2 protocol of the NuGet repositories. And support for that protocol has been switched off. Only v3 or higher is supported. So like with the extensions, you cannot access any repository, and would have to download packages manually.
Okay, so can you then create a local repository on disk from your downloaded packages, and install them into projects from there? Well, perhaps, but I had trouble doing that. So I ended up using the bruteforce way: a NuGet package is just a ZIP file. You can open it with a tool like WinZip, WinRAR or such, and then you can extract the actual assemblies and related files. So I ended up dropping those in a local folder, and referencing the assemblies directly in my projects. That way I could still use VS2010 for small test-projects to debug issues that were difficult to dive into with a cross-development setup.
But for the actual application, I wanted to stick to cross-development from a newer Visual Studio, so that I had proper NuGet support, recent language features and such. Which would allow me to still keep the code as close to the .NET 4.8 (and now .NET 4.6.2) branch as possible.
That wasn’t so bad…
Stripping out everything that didn’t work in .NET 4.0/XP went quite well. The main component that had to work here was SharpDX. And apparently it does. Language-wise, there were only a few minor issues I ran into. One of them was that Task.Run() doesn’t exist, but that can easily be emulated, since it’s basically just a shortcut for Task.Factory.StartNew() (or you can use the TaskEx.Run() method in the Microsoft.Bcl.Async NuGet package, but more on that later).
Another was that System.Buffer does not have a MemoryCopy() function. But that can be fixed by using P/Invoke to call a native function for copying memory (in fact, that’s how earlier versions worked anyway. I refactored the code to System.Buffer myself, so I could just revert those changes).
Then I arrived at the use of IReadOnlyCollection<>. I didn’t really see why this type was used, as an IEnumerable<> would do the job just as well in this particular case. So I refactored it to that.
I quickly arrived at a shell application that at least set up a window and a Direct3D9 device, and did some basic rendering of whatever components were left in the shell application. In this case only text was rendering correctly, as images wouldn’t load through WIC, and there was no working video option either. VLC and MediaFoundation were stripped out, and DirectShow had issues. Audio was also stripped as NAudio 2.x wouldn’t work in .NET 4.0.
But we had an application that started, and managed to get something rendered on screen via Direct3D9, so that’s a good starting point. Now let’s try to fix the issues with the various components one-by-one, and see how many of them we can get to work, ideally without any compromises to the functionality on newer systems.
Windows Imaging Component
Technically, WIC is supported on Windows XP SP3. But as we’ve seen with Vista, it’s been updated over time, and older OSes did not receive these updates. With Vista I could get away with it. In this case however, I ran into problems with the IWICFormatConverter that reported it couldn’t find any codecs. I use the IWICFormatConverter to ensure that any image I load will be in 32-bit RGB format, so they are compatible with D3D textures. As far as I could tell, the actual loading of a JPG or PNG image worked okay in XP, but I ended up with 24-bit pixels. I haven’t figured out if there’s some optional codec I could install on XP to fix that, or if you’d have to just manually perform the conversion.
At any rate, I decided to go with the quick-and-dirty solution of reverting that bit of code to the version before WIC. This at least got image loading up and running in XP quickly, and I may revisit WIC at a later time.
DirectShow, that should work, should it not?
DirectShow… That’s pretty mature technology. In fact, it is so mature that it wasn’t originally called DirectShow, and considered part of DirectX. It started life as ActiveMovie. Anyone who has ever programmed with DirectShow, will know that the interface names do not make any reference to DirectX or DirectShow. Instead, you will find some of the definitions in the Windows SDK in a file named ‘amvideo.h’. Some of them are however named IAM*, such as IAMStreamControl, which is Hungarian notation: the ‘I’ for ‘interface’ and the ‘AM’ for ‘ActiveMovie’.
Windows XP is great at running DirectShow. Just not *our* DirectShow. At least, not in its current state, as it would appear. Like Media Foundation, the DirectShow video renderer was partly written in native C++. So there was our first clue: compiling C++ code with a recent version of Visual Studio will break XP.
Now, Microsoft knew this, and provided a special XP-compatible target with the Visual Studio 2017 build tools. You can still use this target with Visual Studio 2022. So, that will fix our problems, won’t it? No, it in fact will not. For two reasons.
First reason: what do you mean by ‘XP’? There’s a 32-bit XP and a 64-bit XP. I found that the 2017 XP target does in fact NOT build a proper 64-bit binary for XP. Its MSVCP140.DLL runtime imports a kernel32.dll function that isn’t available: AcquireSRWLockExclusive. So apparently this ‘XP’ target that is available in newer Visual Studios is specifically only for 32-bit XP. For 64-bit XP I would need to go back to an earlier version of Visual Studio. In my case that was 2010. And if you have 2010 installed on your system, you can select it as a target in newer Visual Studios. So I rebuilt it that way, and I got it working in XP x64. Which brings us to the next reason why it didn’t work…
The DirectShow video renderer was built on top of the BaseClasses that were once distributed as part of the DirectShow SDK. They give you the basic boilerplate for implementing the various COM-interfaces for DirectShow filters. Your DirectShow filter, being a COM-object, will need to be installed in the registry in order to be able to instantiate it via its GUID.
Since the BaseClasses code is very old, it predates 64-bit. Our codebase was also 32-bit only when I started work on it. I had upgraded it to 64-bit, and then ran into an issue: the standard BaseClasss code would just write to a 32-bit registry key, which by default was also visible in 64-bit (via Registry Redirection). The issue here is that the registry key includes an absolute path to the registered DLL. This means that you can either register a 32-bit or a 64-bit DLL, but not both at the same time, as there is only one path.
I had solved that by modifying the registration code to disable this redirection, by calling RegDisableReflectionKey(). This works fine on any 64-bit OS, and also on any 32-bit version of Vista or newer, since the function will be available. On XP however, the function is not implemented, so we got another missing import problem. Had to rewrite that bit to dynamically load and call RegDisableReflectionKey() if it is available, and remove the static import, so it will load on XP. This again was some code that I merged into the mainline code, as it does not do any harm, and simply makes things more compatible and robust.
Now we have one video player working, two to go…
I was in for a nice surprise here. That is, apparently even the latest version of VLC still supports Windows XP out-of-the-box. By extension, LibVlcSharp also supports .NET 4.0, and thus Windows XP. So, where I originally expected to only get DirectShow support in XP, with whichever codecs I could manage to scrape together, apparently I can get a full up-to-date VLC installation working in XP. And VLC plays nearly everything.
However, as I said above, I had initially removed it from the codebase, as it wasn’t working. So if it is targeted to .NET 4.0, why isn’t it working? I had also said I would get back to Microsoft.Bcl.Async. Well here we are: the reason why LibVlcSharp didn’t want to work, is because it references Microsoft.Bcl.Async.
This problem was somewhat self-inflicted, it would seem. The issue is two-fold. Microsoft.Bcl.Async uses some hacks and trickery to add functionality of newer .NET frameworks to .NET 4.0. This means two things:
- The Microsoft.Bcl.Async package needs to be included by all assemblies that reference an assembly that includes it. They also need to reference the Microsoft.Bcl.Build package, which performs some magic to get the code working properly during compile.
- These packages have not been maintained since 2014. As such, they cannot handle the newer project structure (as also mentioned in my .NET Core article), since they aren’t aware of these changes.
In this case it was somewhat self-inflicted because I had converted the packages.config to PackageReference in my projects. That breaks the Microsoft.Bcl stuff. Now, I could revert that, but I found that it just scans the packages.config file directly, so you can leave your PackageReference in your project, as long as you mirror the relevant packages in a packages.config file that is in the same folder as the project.
Another issue is that your project must have an app.config file, because the Microsoft.Bcl packages will write some redirections in there, to make it all work. So if your project file doesn’t have an app.config and a packages.config, you can’t get Microsoft.Bcl.Async working properly. Which is what initially kept me from getting LibVlcSharp to work.
Once I figured out how to get Microsoft.Bcl.Async working with its recursive dependencies, I managed to get my code to build with LibVlcSharp in .NET 4.0. And indeed, since the underlying LibVLC was still XP-compatible, the whole video player now worked fine on XP. So that’s two out of three now. And at this stage, the application is already quite usable in XP. We need sound, though.
The NAudio dilemma is the same as with .NET 4.6.2: we can’t use the 2.x packages, so we would have to downgrade to 1.x. Or… we could try to build our own .NET 4.0-compatible version.
Since I already did a custom build for NAudio.WinForms last time, which was trivial, I decided to see if I could get NAudio to build for .NET 4.0. As it turned out, it wasn’t all that difficult. There were a few bits of code that used new syntactic sugar, that wasn’t available yet in .NET 4.0. For example, you’d see:
int mixerControlSize = Marshal.SizeOf<MixerInterop.MIXERCONTROL>();
This generic version of SizeOf wasn’t available yet in .NET 4.0. So you’d have to use the old-fasioned way, where you specify the type as a parameter:
int mixerControlSize = Marshal.SizeOf(typeof(<MixerInterop.MIXERCONTROL));
Another one was with PtrToStructure, where the new version was:
var mc = Marshal.PtrToStructure<MixerInterop.MIXERCONTROL>((IntPtr)address);
Which you had to rewrite back to a version with a cast:
var mc = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure((IntPtr)address, typeof(MixerInterop.MIXERCONTROL));
So it was just case of reverting a few minor syntactic tweaks, to make them compatible with .NET 4.0.
The other issue was that it used some advanced async functionality via Task.GetAwaiter<>(). This wasn’t available in .NET 4.0. But once again we can make use of Microsoft.Bcl, Microsoft.Bcl.Async and Microsoft.Bcl.Build to backport the required functionality. Once we have that set up, it can build in .NET 4.0.
From there I ran into an unexpected issue however… That is, our code supports all the usual outputs via NAudio: WaveOut, DirectSound, ASIO and WASAPI. Of those, only WASAPI is not expected to work, since it was introduced on Vista. However, on initialization I immediately ran into this exception:
This functionality is only supported on Windows Vista or newer.
As it turns out, this was coming from the MMDeviceEnumerator. This class ALSO uses an API that was introduced on Vista. So I had to create some workaround to make the code work without this particular enumerator. And once again, this was a simple fix that only made the code more robust, so I also added this to the mainline code. Now we had sound in XP. So we have a pretty much fully functional application now. Like Vista, we lost the web view functionality, but other than that, everything seems to work. We just had to work around WIC, and we cannot use Media Foundation. But DirectShow and VLC still give us video playback.
But in Vista we simply left CefSharp in there. In XP I had to strip the code out of the application, because you cannot get the NuGet packages installed. And even if you added them manually, the native code wouldn’t run on XP (or Vista for that matter). So let’s see if there is a way to bring the two codebases more together.
CefSharp in .NET 4.0?
My first idea was to do the same with CefSharp as I did with NAudio: get the code, and try to downgrade it so it builds in .NET 4.0. After some work, I managed to get it to build in .NET 4.0 and I could run the example projects.
Of course this will not actually make it work on XP or Vista, but it will now be part of the application, so that when you run the .NET 4.0 build on a compatible OS, CefSharp will work. Just like how you can optionally use Direct3D11, and with NAudio you can optionally choose to use WASAPI instead of the legacy WaveOut, DirectShow or ASIO APIs, if your OS supports it. This way the .NET 4.0 application wouldn’t just be a stripped-down custom build for XP, but can be used as complete replacement of the regular version, like the .NET 4.6.2 version was.
I think it may even be possible to ‘trick’ .NET here a bit: you can build your project with the following setting:
And you can also set the following setting on the references to CefSharp:
With these settings it should be possible to actually build against CefSharp binaries that target .NET 4.5 or even higher. Or at the least, it should relax the assembly resolution checking a bit so you can ‘short-change’ your application with the .NET 4.5 version of CefSharp after you built it against your .NET 4.0 port. A quick test with manually downloading and unzipping the CefSharp.Offscreen and CefSharp.Common packages (built against .NET 4.5.2) seems to indicate that this does indeed work. The limiting factor seems to be NuGet, which doesn’t want to install the packages in incompatible projects. If you manually reference them, you can override the target framework version mismatch at your own peril. In this case that seems to be a good compromise, as CefSharp will not actually be used on systems that don’t have at least .NET 4.5.2 or higher. For NAudio it may be a bigger risk, as the code would actually be active on XP, but I suppose you could try it there as well.
Anyway, let’s give WIC and Media Foundation a closer look, as the APIs are supported on XP, just in a minimal implementation. Perhaps we can work around that, and make the codebase into a full replacement for the regular one.
WIC, take two
As I looked into WIC on XP a bit more, I found that the IWICFormatConverter does work, but simply doesn’t support as many formats as it does on newer OSes. I simply assumed that the formats I required were supported (and you know what they say about that). Of course that assumption was never a problem in practice, but it wasn’t quite correct. The correct way is to first call the CanConvert() method. As it turned out, GUID_WICPixelFormat32bppBGRA was not supported, but GUID_WICPixelFormat32bppRGBA was.
There’s a bit of irony in the fact that Direct3D9 textures require the GUID_WICPixelFormat32bppBGRA format when initializing, while DXGI textures use GUID_WICPixelFormat32bppRGBA. So in theory, WIC would have worked with Direct2D/Direct3D10/Direct3D11 on XP, except these APIs aren’t available. And for Direct3D9, the R, G and B components are swapped.
It was not that difficult to fix though: the important part is that I can get a consistent output from WIC. This means I only need one manual RGBA-to-BGRA conversion routine. It’s not ideal, as you need an extra copy-step when loading textures. But it does mean WIC works, and the workaround is simple and can be merged into the mainline.
Media Foundation, take two
So, the Media Foundation video decoder was also written in C++. Which means we also need to use Visual Studio 2010 to make it work on XP and XP x64. The problem here is that you will be using the entire toolchain for Visual Studio 2010, even if you run it from the 2022 IDE. This means that you are also tied to the VS2010 level of language support.
And that is where we hit another snag with Media Foundation: we need to use a newer Windows SDK to get access to the more recent MF headers and libs that the codepath uses. And these new Windows SDKs use various language features that VS2010 cannot handle.
In this case, I ran into issues with Direct3D 10/11 helper objects. They use the ‘= default’ keyword on constructors, which is C++11, which VS2010 doesn’t understand. I got lucky here, since I was not using them anyway, and Microsoft had apparently foreseen trouble with these objects. They allow you to #define D3D10_NO_HELPERS and D3D11_NO_HELPERS, which will skip the problematic helper objects.
Now that we managed to build the binary with VS2010, it should now load on XP, right? Wrong! As it turns out, we still have missing imports. For starters, Mf.dll, Mfreadwrite.dll and Propsys.dll are not available. The only Media Foundation DLL that appears to be available on XP is Mfplat.dll. And that DLL does not implement all functions either.
Remember the weird version parameter for Vista/Win7 that was going on in MFStartup()? Here we find another weird thing that happened between Vista and Windows 7: Microsoft moved some functions around from one DLL to another. As a result, they have two sets of libraries to link to: Vista and Win7+. Since Microsoft is still Microsoft, they took care of backward compatibility of course, so the functions that have been moved, are still available as a redirecting stub in the old DLLs. So the old Vista libraries will always work, they will just be suboptimal. For completeness, the Vista Platform Update does not move these functions around. So even with this update installed, you will need the old Vista libraries when you target Vista. Just like you always need to pass the Vista value to MFStartup().
But we aren’t targeting Vista, we’re targeting XP. Now, Vista got the new IMFSourceReader with the Platform Update, and that is what my code was using. Before that new interface, how would one decode video? Well, you’d start with the source resolver.
Now, luckily I decided to try and write this code on XP, in Visual Studio 2010. Else I may have wasted quite a bit of time on writing a working video decoder pipeline using the old and nasty interfaces. Now I ran into issues almost immediately: on XP there is no MFCreateSourceResolver().
Poking around a bit, I found there were a lot more things missing. As I said above, Mf.dll itself is missing altogether. And apparently Mfplat.dll is not the full implementation of even the original release of Media Foundation that came with Vista.
So what do we have? Well, we have MFStartup(), and we seem to have a lot of helper files, like the work queues, the time source, sockets, sample/buffer management and functions to handle media types. Okay, now what are we looking at exactly here?
Microsoft did not actually say they support Media Foundation on XP anywhere. What they said was this, with MFStartup() and various other functions:
This function is available on the following platforms if the Windows Media Format 11 SDK redistributable components are installed:
- Windows XP with Service Pack 2 (SP2) and later.
- Windows XP Media Center Edition 2005 with KB900325 (Windows XP Media Center Edition 2005) and KB925766 (October 2006 Update Rollup for Windows XP Media Center Edition) installed.
So, they merely claim that certain *functions* are available on XP. And they are available when the “Windows Media Format 11 SDK redistributable components” are installed. So what are they? We will have to look at the Windows Media Format 11 SDK to find out.
And if we read all that, we have to conclude that it says absolutely nothing about Media Foundation whatsoever. It is mostly about Windows Media Player and the support of ASF files/streams. The programming reference does not list any of the Media Foundation functions or objects, not even the ones that are supported by it, such as MFStartup().
Another function that is supported, is MFTEnum(). The function works on XP, but when I call it to enumerate all of MFT_CATEGORY_VIDEO_DECODER, it returns 0 items. I also tried a few other categories, such as MFT_CATEGORY_OTHER, but I never got it to enumerate anything.
I suppose at this point we must conclude that there is no full implementation of Media Foundation. There is not even enough functionality to instantiate an IMFMediaSource or IMFTransform or anything. So clearly there is no way to actually decode a video via the provided Media Foundation functions and libraries on XP.
So what is it? It’s not entirely clear what the purpose of this is. Apparently there are some basic building blocks that may help to implement a media pipeline. Perhaps these are the building blocks that Microsoft used for Media Player 11 and the ASF format. Perhaps we should see this as some early ‘prototype’ for what became Media Foundation in Vista. Perhaps it is an attempt to backport enough of the functionality to XP to make it easier to share code between Media Player and codecs on XP and Vista.
Whatever it is exactly, I’m not sure what value it is to a developer. And it could well be that Microsoft agreed on that, which may explain why the Media Format 11 SDK does not actually document this part of the functionality that it installs on your system.
So what can we do next? Well, we can make the Media Foundation code compatible with XP to the point that it doesn’t crash on loading, and offer full functionality on Vista and above. The fix is similar to what we had to do with the DirectShow DLL: dynamically load function that aren’t available on XP.
This then gives us a working application on XP and up, with the following restrictions:
NAudio (limited to supported APIs on XP, no WASAPI)
|Windows 7+||Direct3D 9|
That’s not a bad score, really. From a functional point-of-view, XP works as well as Vista: the only missing functionality is anything based on web views. From a technical point-of-view, Vista allows some more up-to-date functionality, such as Direct3D 11 and Media Foundation, which may allow it to use the GPU to accelerate some things better than XP would.
But for the full functionality, you really need Windows 7 or better. And if we were to look at the details of the implementations with Direct3D 11 and Media Foundation, you will find that we optionally use some D3D11/Media Foundation functionality that was only added in Windows 8. So even there you will find minor differences in performance. The application will still run best on Windows 10/11.
I suppose the interesting part here is that if you stick to .NET 4.0, you can actually build an application like this, that can scale up from XP to Windows 10/11 and use the best available technology on each platform. Is it practical? Well no, because we had to make custom builds of NAudio and CefSharp to get there. Which means we have to run code that is not officially supported. I’ve made a few changes which were mostly trivial, but I did have to rely on Microsoft.Bcl to make it work like that, which is an unsupported and deprecated package. Without that package, a lot of asynchronous could would have to be rewritten as well. And asynchronous code may lead to bugs that are difficult to track.
This is different from .NET 4.6.2: it is still in active support, and NAudio.WinForms was the only roadblock there. And I could recompile that code without having to change a single line. So the risk there would be much smaller.
Even so, I would think that the best way to handle this, is to just have multiple branches. The mainline should continue to use .NET 4.8, as I said before. I can just merge the .NET 4.8 branch with the .NET 4.6.2 one everytime I want a custom build for .NET 4.6.2. A similar approach could be used for when you want a custom build of .NET 4.0. I tried to keep the changes to the code to an absolute minimum, and tried to merge most small fixes and workarounds into the mainline. So the biggest changes are in the project files themselves. And those generally don’t change, so merges will mainly be done on the code, where the changes have been kept to a mimimum. Aside from that, the risky parts are NAudio and CefSharp. CefSharp doesn’t work in XP anyway, so if you stick to running this version on XP only, it won’t matter. And with NAudio, the only code you can use is the WaveOut, ASIO or DirectSound code. The parts of the code that required Microsoft.Bcl is in the WASAPI support, which only works on Vista and higher anyway.
Pingback: Another adventure in downgrading, part 2: Vista | Scali's OpenBlog™
Pingback: Isn’t it great when things just… work? | Scali's OpenBlog™
Pingback: Another adventure in downgrading, part 4: Fixed function | Scali's OpenBlog™
A few years ago at my previous job I had to develop software that would run on Windows XP targeting NET 4.0 because most of our users had ancient PCs that still ran Windows XP and couldn’t or didn’t want to update because they used government issued software that couldn’t be installed on Vista and up and they weren’t the kind of people who would figure out how to use a Windows PC.
There is one big reason not to use Microsoft.Bcl.Async: it’s a Portable Library and that requires a specific Windows Update to work with .NET 4.0. If that update isn’t installed you get a nasty runtime error. Which is why you should always use AsyncBridge when you can
Thanks for the tip! I hadn’t heard of AsyncBridge. I suppose it is this one: