none
Debugging WCF service with x86 dependencies on a x64 bit machine

    Question

  • Hi,
      I've got a WCF service that makes use of SQL compact edition -- which is only availible in 32 bit. The result is when I'm building and running on my x64 bit machine I have to tell the build system to build as x86 rather than "Any CPU". In the IDE, however, it seems like I loose a lot of functionality when I do this.

      For example, I have tests for all my WCF services using the IDE's built in testing framework. On my x86 machine it was great - I'd hit debug, the IDE would automatically start the WCF service in a local service host, and then if I'd set a breakpoint it would automatically stop. How sweet is that?

      But because of this x86 requirement, the IDE starts the WCF host process that is 64 bit, and that fails to load the x86 project... so it would seem that I've lost the ability to debug and step into my service automatically. This is too bad - this is a real productivity loss.

      Have others figure out a way around this? Thanks in advance for any advice!

        Cheers,
            Gordon.
    Gordon
    Saturday, February 14, 2009 11:24 PM

Answers

All replies

  • Hi,
      Ok -- I've made a few more tests and tried to isolate the problem - and managed to get myself more confused. Here are the steps to cause the problem:

    1. Create a WCF service library project.
    2. Create a test project, and add the WCF as a referenced service.
    3. Code up a test and run the test in debug mode and the IDE will start the service automatically and the test should complete.
    4. Add a local database file to your service project (a sdf file), add a simple table to it.
    5. Add an Entity model to your service project, have it build the model from the database file, and import the table you created in 4.
    6. In your test create the entity:
    using (WcfServiceSample.MyCompactStuffEntities e = new MyCompactStuffEntities())  
    {  
    7. Run in debug. You'll get a crash in the auto-generated code:
            public MyCompactStuffEntities() :   
                    base("name=MyCompactStuffEntities", "MyCompactStuffEntities") 
    and the exception is:
    System.ArgumentException was unhandled by user code  
      Message="The specified store provider cannot be found in the configuration, or is not valid." 
      Source="System.Data.Entity" 
      StackTrace:  
           at System.Data.EntityClient.EntityConnection.GetFactory(String providerString)  
           at System.Data.EntityClient.EntityConnection.ChangeConnectionString(String newConnectionString)  
           at System.Data.Objects.ObjectContext..ctor(String connectionString, String defaultContainerName)  
           at WcfServiceSample.MyCompactStuffEntities..ctor() in c:\users\gwatts\documents\visual studio 2008\projects\testmvc\wcfservicesample\mymodel.designer.cs:line 26  
           at WcfServiceSample.Service1.GetData(Int32 value) in C:\Users\gwatts\Documents\Visual Studio 2008\Projects\TestMVC\WcfServiceSample\Service1.cs:line 15  
           at SyncInvokeGetData(Object , Object[] , Object[] )  
           at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)  
           at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)  
      InnerException: System.ArgumentException  
           Message="Unable to find the requested .Net Framework Data Provider.  It may not be installed." 
           Source="System.Data" 
           StackTrace:  
                at System.Data.Common.DbProviderFactories.GetFactory(String providerInvariantName)  
                at System.Data.EntityClient.EntityConnection.GetFactory(String providerString)  
           InnerException:   
     

    and the connection string looks like the following:
     

    "metadata=res://*/ConferenceModel.csdl|res://*/ConferenceModel.ssdl|res://*/ConferenceModel.msl;provider=System.Data.SqlServerCe.3.5;provider connection string=\"Data Source=C:\\Users\\gwatts\\Documents\\Visual Studio 2008\\Projects\\DeepTalk\\TestResults\\gw[21]\\Out\\ConfData_TestEmptyDBUnrendered.sdf\""


    So -- the reason I've gotten myself totally confused is if I look carefully at the process that is hosting my service library -- the WcfTestClient, it looks like it is coming from the Program Files (x86) folder. Things get a little more bizzare in the sense that when I tell it to build in the x86 mode, the WcfTestClient fails (System.BadImageFormatException).

    I assume this is a x86 vs x64 bit problem, but I'm not really sure what I should be going after here. Any insite would be apprecaited! :-)

    -Gordon.



    Gordon
    Sunday, February 15, 2009 12:09 AM
  • This is a Visual Studio issue indeed, I cannot find any workaround except using ildasm.exe tool to disassemble WcfSvcHost.exe residing under C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE to IL, and use ilasm with x86 switch to compile the IL to a X86 executable. And replace the old version of WcfSvcHost.exe with this X86 version.

    You could file a bug on this at the connect site:
     

    https://connect.microsoft.com/feedback/default.aspx?SiteID=212&wa=wsignin1.0


    Thanks
    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Tuesday, February 17, 2009 9:36 AM
  •  Thanks, Marco. I'll try that out tomorrow.

     I didn't look carefully at WcfSvcHost - it seemed like it was WcfTestClient that was being run. I perhaps need to look a bit more into what is actualy going on there (i.e. what the rolls of these two guys are). Ok, a quick check shows that it is not running in *32 bit mode. Hmmm the funny thing is that it is being run from the x86 area. Must be built with "any CPU" mode.

      Thanks for the help. I'll post back as soon as I have it working.
    Gordon
    Tuesday, February 17, 2009 9:49 AM
  •   Hi,
      Ok -- this is a dumb question -- there is no x86 switch on the ilasm (at least, not in my VS 2008 pro installation). I'm afraid I've not used this tool before, so I must be missing somethign basic. Help appreciated. :-)

      I was able to dassemble by doing ildassm /out=wcf.ilasm WcfSvcHost.exe. If I needed any special command flags there please let me know!

      Thanks!
    Gordon
    Wednesday, February 18, 2009 1:21 PM
  • You only need to specify the /exe swith, ilasm be default generate PE file which targeting X86 architecture.

    Hope this clears things up a little bit.

    Thanks
    Another Paradigm Shift
    http://shevaspace.blogspot.com
    • Edited by Marco Zhou Thursday, February 19, 2009 5:48 AM bad typo
    Thursday, February 19, 2009 5:48 AM
  • Hi,
      Ok -- getting closer. I figured out what was at the root of my previous problem -- the WcfSvcHost is strong signed - I had to remove the .publickey section in order to get it to work at all.

      However, when it throws up the dialog box with the command line options (when you run it from the command line without any arguments) it does not have that distinctive "*32" by its process name in the task manager. So I don't think I'm getting it to target x86 at the moment.

      Here are the commands I am doing:

    1. Copy over WcfHostSvc
    2. ildasm /out=WcfSvcHost.il /typelist WcfSvcHost.exe
    3. Edit the .il file and remove the .publickey section
    4. Delete the WcfSvcHost.exe
    5. ilasm /exe/ resource=WcfSvcHost.res WcfSvcHost.il
    6. WcfSvcHost.exe

    At this  point I seem to have successfully round-tripped the exe. However, watching in the task manager I don't see the *32 on the process name, which makes me think this is still running in x64 bit mode.

    What have I done wrong? And many thanks! -Gordon.


    Gordon
    • Proposed as answer by Michael Dent Monday, July 12, 2010 3:14 PM
    Thursday, February 19, 2009 7:32 AM
  • -> What have I done wrong? And many thanks! -Gordon.

    Have you tried using dumpbin.exe tool to dump the PE headers of the executable to see if it's marked with X86.

    Try typing the following command:

    dumpbin.exe /headers WcfSvcHost.exe


    You can find this tool under C:\Program Files\Microsoft Visual Studio 9.0\VC\bin.

    Thanks
    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Thursday, February 19, 2009 9:17 AM
  • Hi,
      Thanks. dumpbin claims it is marked x86. But the original exe that that can be found in the following path is also marked the same way:

     

    c:\Users\gwatts\Documents\Visual Studio 2008\Projects\DeepTalk\wcfsvchost>dumpbi  
    n /headers "c:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\WcfSv  
    cHost.exe"  
    Microsoft (R) COFF/PE Dumper Version 9.00.30729.01  
    Copyright (C) Microsoft Corporation.  All rights reserved.  
     
     
    Dump of file c:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\WcfS  
    vcHost.exe  
     
    PE signature found  
     
    File Type: EXECUTABLE IMAGE  
     
    FILE HEADER VALUES  
                 14C machine (x86)  
                   3 number of sections  
            488F124D time date stamp Tue Jul 29 05:51:25 2008  
                   0 file pointer to symbol table  
                   0 number of symbols  
                  E0 size of optional header  
                 10E characteristics  
                       Executable  
                       Line numbers stripped  
                       Symbols stripped  
                       32 bit word machine 

    I took a look at WcfTestClient.exe - which is also located in the same directory. It is also marked with x86 as the machine. However, unlike WcfSvcHost, when it starts it is marked with "*32" in the process manager. So there is some other bit of information the system is using to decide to start a process in 32 bit mode vs 64 bit mode.

    Thanks for your help! -Gordon.
    Gordon
    Thursday, February 19, 2009 2:29 PM
  • Well, I only think that PE/COFF header should be enough to determine the bitness, but apparently I am wrong:)

    We also need to change the Corflags under CLR header as the following blog article illustrates:

    http://blogs.msdn.com/joshwil/archive/2005/05/06/415191.aspx

    Thanks
    Another Paradigm Shift
    http://shevaspace.blogspot.com
    • Marked as answer by GordonTWatts Saturday, February 21, 2009 6:26 AM
    Friday, February 20, 2009 7:06 AM
  • Hi,
      Ok - I ran the corflags /32BIT+ /FORCE WcfSvcHost.exe  - you need the Force because the executable is strong signed. And when I do that it runs in 32 bit mode now!

      I compared disassembly, and it looks like the difference is the .corflags directive. In the case of the ANYCPU version (the default distributed WcfSvcHost) the value of .coreflaags is 0x9. In the case of the 32 bit it is 0xB. The comments indicate the first is "ILONLY" flag, and the second is "ILFLAG | 32BITREQUIRED".

      When I copy that file back to the proper IDE place my tests work!!

      To summarize for everyone that comes after here and is looking for instructions:

    1. Copy WcfSvcHost.exe from C:\program files (x86)\Microsoft Visual Studio 9.0\Common7\IDE to a local directory. Keep a backup copy of this file, of course.
    2. Start a Visual Studio 2008 Command Prompt (one of the links from the start menu -> Visaul Studio 2008)
    3. "cd" to the directory where your copy of WcfSvcHost is located.
    4. Execute the command "corflags /32BIT+ /FORCE WcfSvcHost.exe"
    5. Copy the exe back to where you found it.

    Now your WcfSvcHost will be running in 32 bit mode and you can load things like the 32 bit dll for compact SQL.

    Many thanks for your help, Marco!

    Cheers, Gordon.


    Gordon
    • Proposed as answer by Ivan Kotev Friday, October 30, 2009 9:35 AM
    Saturday, February 21, 2009 6:25 AM
  • Many thanks to those who contributed to this thread, particularly Marco, and to Gordon for his clear list of steps at the end.  I needed this very information to run a service that makes use of the Jet 4.0 OLEDB provider to read XLS files, for which there is no x64 version.  This thread sorted my issue quick smart.
    Friday, September 25, 2009 1:44 AM
  • Thanks! Saved me hours of un-necessary cursing :)
    Thursday, October 08, 2009 8:18 AM
  • thankyouthankyouthankyouthankyou
    Monday, July 12, 2010 3:15 PM
  • Jackpot!

    I wasn't sure if the command had any effect since the timestamp on WcfSvcHost.exe didn't even change, but lo and behold, I see the *32 in Task Manager, and now my service can call an unmanaged 32-bit DLL with no problem!

    Wednesday, October 27, 2010 3:02 PM
  • Thanks a lot for the instruction. It really saved me after more than week being stuck.

     

     

    Monday, January 16, 2012 5:57 PM
  • Thanks for this - Gordon's solution works well.

    I wish there was an easier way (in Dev/Debug mode) - I tried to host my WCF Service in IIS locally with the "Enable 32-bit Applications" Application Pool setting set, but I could get my service to activate for whatever reason. 


    • Edited by Peter_D503 Monday, February 27, 2012 6:18 AM
    Monday, February 27, 2012 6:17 AM
  • Thank you. I am creating WCF services on a 64 bit machine using a 32 bit ODBC driver and could not debug them from the IDE. This solution was extremely helpful.  It works well on VS2010 also (of course the directory is under Visual Studio 10.0).
    • Edited by roger spark Friday, August 17, 2012 4:30 PM
    Friday, August 17, 2012 4:29 PM
  • Genius Watts. Thanks a ton

    Had a tough time working with oracle.dataaccess.dll

    Thought it was an issue with Oracle client/32/64 etc.

    I am using Win 7 Proff 64 Bit. VS 2010

    Created WCF using EF and data source Oracle.

    Never got it running. Had weird errors like BadImage, TNS unable to resolve., etc.

    Finally followed the solution you gave. 

    Thank you very very much

    Thursday, February 28, 2013 7:19 PM
  • Gordon and Marco,  thank you for posting your work.  I was running into this problem using WCF Test Client and calling code that accessed Oracle's 32-bit oracle.dataaccess.dll.  Great work!
    Tuesday, March 11, 2014 2:10 PM
  • Gordon and Marco,

    Thanks. Your Posting saved a lot of headache.

    Thursday, January 22, 2015 6:53 PM