2

I have used the editbin /LARGEADDRESSAWARE command to change my .NET C# exe so that it can address memory > 2 GB. This works fine and I can run the dumpbin command to verify that it's been modified successfully.

I then proceed to create a .msi package that includes this exe. When I run this .msi on a windows 7 target machine it successfully installs the exe. But now if I run dumpbin on the same exe that got installed on the target machine is shows that it is no longer supporting memory > 2 GB.

What is causing this? Is is the process of building .msi or the running of .msi on the target machine?

phuclv
  • 37,963
  • 15
  • 156
  • 475
  • My crystal ball says you did this for the Debug build but not the Release build. – Hans Passant Aug 29 '13 at 20:27
  • 1
    Any reason you can't just build it as x64 or "any" (but not the any-prefer-32 thing)? – Marc Gravell Aug 29 '13 at 22:09
  • I did run the command editbin on my release build and dumpbin was also run on this release build exe. I am compiling it for x86 as my user base is both xp and windows 7. – user2730707 Aug 29 '13 at 22:32
  • Ok I may have a clue. I am running the editbin command in my post build event for the exe project. The setup project runs after that to build .msi package. I read somewhere that the Installer project is grabbing /obj/Release/myApp.exe instead of /bin/Release/myApp.exe. Is that true? Can anyone confirm that? – user2730707 Aug 29 '13 at 22:47
  • You can verify the file access with a file monitor such as sysinternals' [Process Monitor](http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx). – Chris O Aug 30 '13 at 16:57

3 Answers3

4

Whatever is going wrong here, it surely has something to do with you doing this by hand. Let the build system do this for you. Project + Properties, Build Events tab. Paste this into the "Post-build event command line" box:

set pathsave=%path%
set path=$(devenvdir);$(devenvdir)..\..\vc\bin
editbin.exe /nologo /largeaddressaware "$(targetfilename)"
set path=%pathsave%
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Please see my comment above. I am using the post build command.I am using this post build command editbin.exe /nologo /largeaddressaware "$(targetpath)" – user2730707 Aug 30 '13 at 16:15
  • I think the installer is grabbing /obj/Release/myApp.exe instead of /bin/Release/myApp.exe. – user2730707 Aug 30 '13 at 16:16
1

There are several issues with editbin to set the LARGEADDRESSAWARE flag in an msbuild post build step.

  1. EditBin x32 does not run outside of VS command prompt because mspdb100.dll is not found. Why should you care? Well if you run a TFS build workflow msbuild is NOT called from a VS command prompt. This will cause issues ...
  2. You can fix this one by using the one in bin\amd64\editbin.exe but then you can build your exe only on a x64 build machine.
  3. If you patch the final file at $(TargetPath) then it will work but if you rebuild your project and you have set Inputs and Outputs for your task then it will not run again. This is an issue because during a rebuild the exe from the intermediate folder is copied again to the final location which was not patched.
  4. This is still not it. Because if you did strong name your exe you need to re-sign it to make the strong name valid again. It will run on you dev machine because most of the time dev machines have disabled strong name verification but it will fail to run on customer machines.

Finally your task will look like this:

<Target Name="AfterBuild" BeforeTargets="CopyFilesToOutputDirectory" Inputs="$(IntermediateOutputPath)$(TargetFileName)" Outputs="$(IntermediateOutputPath)largaddessaware.tmp">
   <Exec Command="xxxxxbin\amd64\EditBin.exe /LARGEADDRESSAWARE &quot;$(IntermediateOutputPath)$(TargetFileName)&quot;"/>
   <Exec Command="sn -Ra &quot;$(IntermediateOutputPath)$(TargetFileName)&quot; &quot;$(AssemblyOriginatorKeyFile)&quot;"/>
   <Touch AlwaysCreate="true" Files="$(IntermediateOutputPath)largaddessaware.tmp"/>
</Target>

We need to patch the executable before CopyFiletoOutputDirectory has run otherwise we will patch the intermediate file after the unpatched file has already been copied to the ouptut folder. The final file cannot be patched because this target will not run when the exe has not changed to prevent breaking the incremental build.

This is a classic example of a simple task (set one bit in the PE header) which is quite difficult to get right. It is (nearly) never as easy as it might look like at the beginning.

Alois Kraus
  • 13,229
  • 1
  • 38
  • 64
  • I found AfterCompile to be better than AfterBuild, because it comes before all the signing and manifest generation and whatnot. – Mark Sowul Mar 24 '14 at 18:10
1

I thinks in the end I found that the Installer was picking my exe from a different path than the one I was using to update using editbin post build command. I added this line in my post build command of my exe

copy "$(targetpath)"  "$(ProjectDir)\obj\x86\release"

So the entire post build command looks like this

set pathsave=%path%
set path=$(devenvdir);$(devenvdir)..\..\vc\bin
editbin.exe /nologo /largeaddressaware "$(targetpath)"
copy "$(targetpath)"  "$(ProjectDir)\obj\x86\release"
set path=%pathsave%

Thanks

phuclv
  • 37,963
  • 15
  • 156
  • 475