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:


 


http://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.


 


 

Comments (3)

  1. Webdav101 says:

    Please note that I wrote this blog post as an "ahhhhhhhh!!!" article and not a how-to. The how-to will be out in the future.  

    Oh, you might find an easier solution if you just put your code into com+, running under an exchange admin account and then call it from your application ;-).  This should get you around com+ issues.

  2. pjhutch says:

    I have written an ASP.Net web application using ADSI and CDO/CDOEXM to create AD and Exchange 2003 accounts over the web. I used the LDAPAuthentication.vb method (see MSDN website) and changed the Anon user in IIS to a Domain account which the appropiate AD/Exchange rights.

    Now, I am using powershell commands. I have written some useful functions that run the PowerShell commands with all the gubbins thats needed to run them. I pass the commands and parameters as arrays to be processed by the function(s) – a nice piece of programming (if you want to see it let me know).

    Anyway, my question is, if using the LDAPAuthentication.vb method, do you still need the BeginImpersonation() and EndPersonation() functions in the code?

  3. dominic@breeze.name says:

    Do you have anything that works with Exchange 2010 via ASP.NET? I would rather use impersonation, i.e. have the user who has rights to make changes to Exchange objects, i.e. DLs, log into the website and use their credentials to make the change.

    I figure Exchange 2010 is different because of the requirement to initiate a Remote PS connection.

Skip to main content