1

How can I generate a compiler error if the platform target is not set to x86?

Motivation: A particular method dynamically loads a 32-bit COM dll. If the project is built for "x64" or "Any CPU" and is run in a 64-bit environment, then naturally loading the COM object fails at run time. I want a compile-time check to make sure this can't happen.

This is intended to be a safety check of the project settings, encapsulated entirely in the source file that requires 32-bitness. So I can't accept a solution (such as this) that requires defining a conditional compilation symbol in the project settings.

Community
  • 1
  • 1
Ian Goldby
  • 5,609
  • 1
  • 45
  • 81
  • This looks a lot like an XY problem. I would suggest hosting your COM component in a dedicated server process through COM+ (DCOM). That way, a `dllhost` process will be launched around your component and will marshal the calls. Since these are cross-process calls, the bitness of your C# project will not matter anymore. – Frédéric Hamidi Oct 12 '16 at 08:40
  • @FrédéricHamidi Thanks for suggesting that. It's something I wanted to avoid - there's no advantage to running this in 64-bit. – Ian Goldby Oct 12 '16 at 08:41
  • You could evaluate IntPtr.Size as discussed [here](http://www.hanselman.com/blog/BackToBasics32bitAnd64bitConfusionAroundX86AndX64AndTheNETFrameworkAndCLR.aspx). – Axel Kemper Oct 12 '16 at 08:42
  • @AxelKemper I don't think IntPtr.Size can be evaluated at compile time. – Ian Goldby Oct 12 '16 at 08:52

2 Answers2

1

You can write a Roslyn Diagnostic Analyzer to do this.

First, write something in your code to search for. You could use an attribute, for example. It could be an assembly level attribute, for example:

[assembly: Require32bit]

It could also be an attribute you apply to the class or even the method that is calling the COM component, as you choose.

Then write an analyzer to search for the presence of this. In the analyzer, you can use the Compilation.Options.Platform property to determine the platform. The compilation is available from e.g. the SyntaxNodeAnalysisContext.

Kris Vandermotten
  • 10,111
  • 38
  • 49
  • You would have to add the analyzer to the project as a Nuget package. That's not as bad as it seems, because the attribute you use needs to come from somewhere, and it may be in the same Nuget package. (Alternatively, you could install the analyzer in Visual Studio using a .vsix, but for this scenario I would require the Nuget solution.) You'll need to read up on Roslyn analyzers. This should get you started: https://www.bing.com/search?q=developing+roslyn+diagnostic+analyzer – Kris Vandermotten Oct 12 '16 at 08:54
  • Well, if the source code needed a reference to some DLL, that other project would need to reference that DLL in order to compile, right? That is the case for *any* DLL it references, not just the one containing the attribute. So they need to add the reference anyway. And here's the beauty of it all: if they reference the DLL with the attribute via a Nuget package, and that Nuget package also contains the analyzer, the analyzer will run automatically with every build! – Kris Vandermotten Oct 12 '16 at 09:07
  • No, the COM object is loaded dynamically. (As in `Type.GetTypeFromProgID()`, `Activator.CreateInstance()`.) Very nice solution though for the case you describe. – Ian Goldby Oct 12 '16 at 09:09
  • Yes, but the attribute isn't. – Kris Vandermotten Oct 12 '16 at 09:10
  • `Require32BitAttribute` doesn't exist. You would create it. So in order to compile code that uses it, you have to reference the assembly that contains it. That assembly sits in a Nuget package that also contains the analyzer. – Kris Vandermotten Oct 12 '16 at 09:15
  • *Very* clever +1. But I've decided to go with the simpler (albeit not quite as robust) answer by @Gnqz. – Ian Goldby Oct 12 '16 at 09:16
0

Did you try something like:

#if PLATFORM_X86
    #error Target platform needs to be x86!
#endif
Gnqz
  • 3,292
  • 3
  • 25
  • 35
  • To be honest, I've not tested exactly this one, but something similar few months ago. I can try it once I get home (in 6 hours), if that works for you? – Gnqz Oct 12 '16 at 08:46
  • Sadly, it doesn't work. There is no PLATFORM_X86 symbol. (Yes I could define one, but then there's no protection when the code is used in another project.) – Ian Goldby Oct 12 '16 at 08:48
  • 1
    Did you add it as a conditional compilation symbol. It's in the Build tab. – Gnqz Oct 12 '16 at 09:09
  • Actually, this is the solution I decided to go with. I made the error say `#error This method requires that the platform target is x86. To resolve this error set the platform target and also a PLATFORM_X86 compilation symbol.` It's a bit clunky but it should be effective. – Ian Goldby Oct 12 '16 at 09:14