An Adventure: Building an ASP.NET application to call 64bit Powershell.

I keep seeing quesions on calling Exchange PowerShell from ASP.NET pop-up. Not all the banter I've seen on the web and elsewhere seems to be correct, I decided to look into this. I see that some people end-up setting up speical accounts or putting the code into COM+ because they give up trying to make the calls work directly from ASP.NET. So as a test, I'm trying to call "Enable-Mailbox" from C# code in an ASP.NET application.

There are a few things you should note about calling PowerShell.

1)  64bit code is not supported calling 32bit code.

2)  32bit code is not supported calling 64bit code.

3) Only the 64bit version of Exchange is supported for production.

4) You can put the 32 bit version Exchange admin tools of 2007 on a box and use PowerShell automation to work with Exchange 64bit.

5) The proper refernce to System.Management.Automation.dll is: C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll
The location of this dll is improperly documented as being in other folders - so watch out.
So, no its not under C:\WINDOWS\system32\windowspowershell\v1.0 or C:\WINDOWS\SysWOW64\windowspowershell\v1.0
You will be using the same reference for building 32bit or 64bit automation apps.

6) On a 64bit Exchagne server, you will be using the 64bit version of Powershell - this means that your application will need to be 64bit if the code runs on that box.

7) If you put CDOEXM and PowerShell automation calls into the same program, then your likely to run into issues - so dont do it.

8) If you want to do impersonation, you should be on the latest and greatest updates for Exchange. If your calling PowerShell from box like Vista, be sure that both the Exchange server and the Vista box (used to call PowerShell) have been patched.

OK, first hurdle here...

When buuilding under VS 2008, I ran into issues with 64bit code under ASP.NET. While calling "config.AddPSSnapIn"

worked from my WinForm application, I got an error from the WebForm.

"No Windows PowerShell Snap-ins are available for version 1."

So, whats going on here? I did some checking and it seems to be related to calling 64bit

PowerShell from 32bit code. So, I set the code as targeted as 64bit in the solution properties.

Next, I got:

Warning 1 C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\ExchangePowerShellAdmin\ExchangePowerShellAdmin\Default.aspx: ASP.NET runtime error: Attempted to load a 64-bit assembly on a 32-bit platform. Use ReflectionOnlyLoad() instead if trying to load for reflection purposes. C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\ExchangePowerShellAdmin\ExchangePowerShellAdmin\Default.aspx 1 1 ExchangePowerShellAdmin

WOW… looks interesting…

OK, specifying the platform as 64bit alone for the solution does not make it 64bit....?

So, I did more checking and found that that the Configuration Manager was not showing in the menu. What gives?

Where has the Configuration manager setings gone??? I did some checking and found how to make it visible.

  #1 Make the Configuration Manager visiable in the menu:

            Go to: Tool -> Options -> Projects and Solutions -> General

            Check "Show advanced build configurations". Yep, its not checked by default.

    Note: Now, you can get to the Configuration Manager under Build -> Configuration Manager.

   

  #2 Build the configuration for 64bit.

    Go to: Build -> Configuration Manager

    Create a 64bit build...

   

  #3 Go back to the solution and set as 64bit.

   

Now I can build this as 64bit, eh? Ummm... I'm getting another error... says I'm referencing the the wrong assemblies for the processor.

Looks like Visual Studion does not automatically change these over.

Example: Warning 1 Assembly generation -- Referenced assembly 'System.Web.dll' targets a different processor WebApplication1

These warnings are ignorable, however I don't like unresolved warnings of any

kind - so, I removed the references to System.Data.DLL, System.Web.dll and

System.Enterprise Services. Next, I added-in new references to the 64bit

version of these assemblies.

c:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Data.dll

            c:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Web.dll

            c:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.EnterpriseServices.dll

           

Next in the solutions Build -> Advanced Build Settings windows I unchecked

“Do not reference mscorlib.dll” . This prevents VS from automatically adding

a reference to the 32bit version of mscorlib.dll. The problem here is that doing so caused

an error to be thrown during compilation:

    Error 1 Predefined type 'System.Object' is not defined or imported ExchangePowerShellAdmin

Ahhhh... so, I'll uncheck “Do not reference mscorlib.dll” and live with the warnining for now.

So, is it working?

   ... NO...

  

   I'm still getting "No Windows PowerShell Snap-ins are available for version 1." .

I went into the solution settings for Web->Server and changed the appliation to use IIS

instead of Visual Studio. Be sure to specify the virtual directory folder when doing

this - you likely dont want your app written to the sites root. I compiles and ran - ok,

says I need to turn Windows auth to debug. I turned on Windows Auth from IIS and it ran.

Soooo.... changing the solution to run the Winform from IIS instead of from Visual Studio's

Development Server seems to help get rid of the "No Windows PowerShell Snap-ins are available

for version 1." message. - at least it seems to be a factor here.

Hold on - Windows auth is on and I'm signed-in as Admin... so I need to be sure that this

thing works when impersonation is used. Ok, it works out of the domain - I'm using Anonymous.

Here is a clip from my web.config:

<authentication mode="None"/>

<authorization>

    <allow users="*" />

</authorization>

 

 So, it seems to all work now. I'm using the code from a prior post I did on PowerShell Impersonation if your curious:

https://blogs.msdn.com/webdav\_101/archive/2008/09/25/howto-calling-exchange-powershell-from-an-impersonated-thead.aspx

   

The one change I did though was to move the call to BeginImpersonation above config.AddPSSSnapIn. However, I would think it would be best to have AddPSSSnapIn called first.

 

In my test, I did not setup any special account. The calls however are being done with the thread being impersonated as noted in the article link above.

I'll try to write-up some concise instructions on how to build an ASP.NET application for 64bit in the future.