2
votes

I am currently writing a PowerShell snapin that has specific dependencies on mixed-mode assemblies (assemblies containing native code) that specifically target x64 or x86. I have both versions of the dependent assembly, but I am wondering how best to manage the build and deployment of this snapin, specifically:

  1. Is it necessary to have two versions of the snapin, one x86 and one x64, and use the two different versions of installutil to install it, once for each architecture?
  2. Assuming #1 is true, is it recommended to install the two different versions of the snapin in the different "Program Files" and "Program Files (x86)" directories?
  3. What is the ideal (least hassle) way to structure a pair of projects that share everything but a single reference, in order to build for the two different architectures?
  4. If the snapin is compiled as "AnyCpu", and the dependent dlls are both loaded into the GAC, will the runtime load the correct assembly from the GAC based on the architecture of the currently running PowerShell host?
  5. Is there a slick way to dynamically, at run-time, choose which dependent dll to load (if it cannot, for various reasons, be installed in the GAC) without running into headaches with assembly load contexts?
2
Modules (added in PSH2) are much simpler -- don't require installation -- do you have a good reason to support PSH1?Richard
@Richard: can modules have compiled code?Mark
Modules can load assemblies and execute scripts (which can, in turn, use any of the [system.reflection.assembly]::LoadXXX methods to load an assembly. If you plan not to support PSH1, then @Richard's recommendation is very sound. In your .psd1 file, the RequiredAssemblies and ScriptsToProcess elements can enable you to handle assembly loads and custom initialization when your module loads. Consider giving it a go, if you aren't already heavily invested in a snap-in.kbrimington

2 Answers

4
votes

Mark, we have this very situation with the PowerShell Community Extensions with 32-bit and 64-bit versions of 7zip.dll. You can pretty easily work around this by PInvoking to LoadLibrary early in your snapin startup (or before you need to call out to the native DLL). You can then test if you're a 32-bit or 64-bit process (IntPtr.Size) and then load manually the correct DLL using the LoadLibrary PInvoke. After that the, DllImport("YourNative.dll") will notice that the dll is already loaded and use that DLL.

Take a look at these two PSCX source code files: http://pscx.codeplex.com/SourceControl/changeset/view/74794?ProjectName=Pscx#1358100 http://pscx.codeplex.com/SourceControl/changeset/view/74794?ProjectName=Pscx#1358102

1
votes

I ended up creating a module (thanks, Richard!), but that didn't solve the problems related to processor architecture. In order to solve that, I put both versions of the dependent dll in the module directory, and in each cmdlet's constructor I put some initialization code (that only runs once) to load the appropriate version of the dependent dll.

Thanks, all, for the pointers.