red-gate / XmlDoc2CmdletDoc

Create cmdlet XML help files from XML doc comments
Other
63 stars 24 forks source link

BadImageFormatException on x64 compiled cmdlet library #31

Closed mschnecke closed 7 years ago

mschnecke commented 7 years ago

BadImageFormatException occurs if you want to create help documentation for x64 compiled cmdlet-libraries.

I found the reason in the XmlDoc2CmdletDoc.exe project properties: the project is configured for Any CPU but the checkbox "Prefer 32-bit" is checked. So the method LoadAssembly() in the Engine class will always raise an exception on loading a x64-compiled library.

2017-02-01 07_27_48-xmldoc2cmdletdoc - microsoft visual studio

ChrisLambrou commented 7 years ago

Thanks for the report. I have a potential fix for this. Would you mind trying it out and letting me know if it solves the problem for you?

https://www.nuget.org/packages/XmlDoc2CmdletDoc/0.2.7-Fix64BitAssemblyLoad

If it works, I'll deploy v0.2.7 asap.

mschnecke commented 7 years ago

No, it doesn't work . Now it works with the x64-compiled assembly but not with the x86-compiled assembly.

Here is my sample project: https://github.com/mschnecke/Demo.XmlDoc2CmdletDoc.git

Following exception occurs in the LoadAssembly() method in the Engine class :

Could not load file or assembly 'Demo.XmlDoc2CmdletDoc.dll' or one of its dependencies. is not a valid Win32 application. (Exception from HRESULT: 0x800700C1)

I think there is no simple solution for this problem, because Assembly.LoadFile(path) depends on the kind of process - loading x86-assembly in x64-process and vice versa leads to the BadImageFormatException.

ChrisLambrou commented 7 years ago

Ah yes, you're right. The change I've made is probably still good. On balance, it's probably better to run as a 64-bit process if possible, and only as a 32-bit process if there's no 64-bit version of the runtime available. This doesn't help your situation, though. The tool has to load the target binary PowerShell module in order to reflect over its cmdlets and their parameters, but the same tool, unmodified, will be incapable of loading both 32-bit only assemblies and 64-bit only assemblies without some way of coercing a specific runtime.

One possible option would be to produce multiple versions of the XmlDoc2CmdletDoc.exe binary (i.e. a 32-bit version and a 64-bit version), and maybe add some support to the msbuild tasks to allow a project to specify which one to use.

IIRC, we considered doing this a few years ago, but decided against it on the basis that we wanted to avoid the BadImageFormatException issue altogether, so our binary modules are always CPU-agnostic. For any work that needs to be carried out by code that's architecture specific, we bundle both 32-bit and 64-bit versions of the code. The binary module just serves to define the cmdlets, and otherwise acts as a harness to execute the real work in a separate process. There's more work involved, having to deal with the inter-process communication, but it's ultimately a smoother experience for the end-users.

ChrisLambrou commented 7 years ago

I've published a new pre-release package.

https://www.nuget.org/packages/XmlDoc2CmdletDoc/0.2.7-Support32Bit001

It includes both XmlDoc2CmdletDoc.exe and XmlDoc2CmdletDoc32.exe, the latter being a copy of the former that requires the 32-bit CLR runtime. The version used depends on the PlatformTarget build property as follows:

The first case should hopefully fix your outstanding problem. The second and third cases already appear to work.

Once again, please let me know how it goes. :)

mschnecke commented 7 years ago

0.2.7-Support32Bit001 works fine. Thank you

ChrisLambrou commented 7 years ago

Glad to help. v0.2.7 is now published. https://www.nuget.org/packages/XmlDoc2CmdletDoc/0.2.7