2

I'm trying to build a module in C# for Powershell 2.0 on a machine where I don't have administrator permissions and no tools installed explicitly for building. I've got almost everything I think I'd need to make this work, but I'm botching the csc call somehow.

My Powershell version is:

PS C:\temp\> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1

To get the System.Management.Automation dll out of the CAC, I followed this brilliant advice:

Copy ([PSObject].Assembly.Location) C:\temp

To build with csc, I'm trying to follow this advice from Mr. Skeet:

In addition to this, you can use /noconfig /nostdlib and then explicitly reference the .NET 2.0 assemblies (in c:\Windows\Microsoft.NET\Framework\v2.0.50727 for example). It looks like the /lib command line option can make this slightly easier by letting you specify a directory to look in for references, but I haven't tried that myself.

Here's my current command line:

csc /out:shims.dll /target:library /noconfig /nostdlib /lib:c:\Windows\Microsoft.NET\Framework\v2.0.50727 /r:..\System.Management.Automation.dll;System.dll;mscorlib.dll PowershellPlay.cs

That builds fine, but when I try to import the module, I get that I'm using too new a version of the framework -- which, of course, is what I was trying to avoid with the /lib, /nostdlib, and /noconfig settings.

Import-Module : Could not load file or assembly 'file:///C:\temp\PowerCLI_1\shi
ms.dll' or one of its dependencies. This assembly is built by a runtime newer t
han the currently loaded runtime and cannot be loaded.
At line:1 char:14
+ Import-Module <<<<  .\shims.dll
    + CategoryInfo          : NotSpecified: (:) [Import-Module], BadImageForma
   tException
    + FullyQualifiedErrorId : System.BadImageFormatException,Microsoft.PowerSh
   ell.Commands.ImportModuleCommand

Wonder if I have to change which csc I use? Doesn't seem like that should be a requirement/matter.

c:\temp>where csc
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe



EDIT: Okay, I think I've got the answer: I'm doing things in my code that aren't .NET 2.0 kosher. I'm a little surprised the 2.0 version of csc seems to compile it, though. ??

Anyhow, the below works:

Code for cmdlet:

using System;
using System.Management.Automation;

[Cmdlet("Test", "PowershellCompilation")]
public class Test : Cmdlet
{
    [Parameter]
    public string Server = "";

    protected override void ProcessRecord()
    {
        WriteObject(this.Server + "test");
    }
}

csc call:

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\csc /out:test.dll /target:library /r:..\System.Management.Automation.dll Test.cs

I've got that call in a bat file named buildTest.bat.

PS C:\temp\PowerCLI_1> .\buildTest.bat

C:\temp\PowerCLI_1>C:\Windows\Microsoft.NET\Framework64\v2.0.50727\csc /out:test
.dll /target:library /r:..\System.Management.Automation.dll Test.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.5483
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

PS C:\temp\PowerCLI_1> Import-Module .\test.dll
PS C:\temp\PowerCLI_1> Test-PowershellCompilation
test
PS C:\temp\PowerCLI_1> Test-PowershellCompilation -Server spam
spamtest
PS C:\temp\PowerCLI_1>

Note that I was unable to get the 4.0 version of csc to work using a command like this:

csc /out:test.dll /target:library /noconfig /nostdlib /lib:c:\Windows\Microsoft.NET\Framework\v2.0.50727 /r:..\System.Management.Automation.dll;System.dll;mscorlib.dll Test.cs

That gave the "runtime newer" error again.

So success. I'll try to convince Eris to turn the comment into an answer; if I'd tried the 2.0 version of csc first, I wouldn't've tried the "compile for 2 with csc for 4" madness.

7
  • @sepp2k (realizing he probably won't see this) I see where you're coming from, but I got the compiler tag following this question's lead. If that's not fair, fine, but 1.) a comment why is probably helpful & 2.) I'm going to add compiler-construction one more time just in case the other question's tagging wasn't illegitimate (note that I did add it in an edit; I was waffling on its use).
    – ruffin
    Commented Sep 25, 2014 at 17:31
  • 1
    Try using [Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()\csc.exe instead of the default? When I check the RuntimeDirectory on powershell -version 2, it shows ...Framework64\v2.0.50727
    – Eris
    Commented Sep 25, 2014 at 17:45
  • @Eris Ultimately, I think that's the right answer -- to build for 2.0, you need to use the csc for 2.0. Knowing that, it's easier to track down that the problem must be my code using stuff from > 2.0. Not sure why csc from 2.0 compiles it, but there you go. If you want to make your comment an answer, I'll accept it.
    – ruffin
    Commented Sep 25, 2014 at 18:20
  • BTW: you could just use Add-Type -OutputAssembly? It would do the same under the hood I think, but would prevent you from shooting yourself in the foot.
    – BartekB
    Commented Sep 25, 2014 at 18:46
  • @BartekB Yeah, I think you're right. I did wonder why I'd talked myself out of that. Been reading Bruce Payette's Windows Powershell in Action, and he goes Add-Type a good bit. There was something about "dynamic binary modules" that sounded squirrelly -- they don't compile to dlls, right? I'll take another look.
    – ruffin
    Commented Sep 25, 2014 at 18:54

1 Answer 1

2

Try using

[Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()\csc.exe 

PowerShell v2 uses the framework in ...Framework64\v2.0.50727

Not the answer you're looking for? Browse other questions tagged or ask your own question.