Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Some thoughts on Microsoft Visual C++ 8.0

43 views
Skip to first unread message

Ron Blaschke

unread,
Nov 21, 2006, 5:34:12 AM11/21/06
to perl5-...@perl.org, parrot-...@perl.org
Hello,

Sorry for cross-posting, but I hope this will be interesting to both
groups. I'm putting this down from the top of my head, and I hope I
remember things correctly. Let me know if there are any mistakes or
further questions. I don't add any references, but can sure come up
with some.


Starting with Visual Studio 2005, which includes Microsoft Visual C++
8.0, whose compiler reports version 14, Microsoft came up with the grand
scheme of "Unmanaged Assemblies." This is some derivate from the
"Managed Assemblies" in .NET, which is a fancy name for some bundled
code. If the code is running under the Microsoft Common Language
Runtime (CLR) it's called managed, otherwise - that means native - it's
called unmanaged. An "Unmanaged Assembly" is some native code - DLLs
and COM objects - and a descriptor. That's how new libraries in Windows
can be distributed, and Microsoft uses this scheme for the C Runtime for
Visual C++ 8.0, too. There are still Plain Old DLLs, too. These don't
need the things described below - just link-n-go.


Unmanaged assemblies are installed into the "Windows Side-by-Side Cache"
directory "%SystemRoot%\WinSxs" - usually "C:\WINDOWS\WinSxS." The
important word here is "installed," because these need to be put there
by the Installer. Just copying the files there does not work. Maybe
because of some dark magic that needs to be done to the Windows Registry.
Microsoft provides the standalone "vcredist_<platform>" installer for
this, and I think the full Visual Studio 2005 contains some installer
modules that can be used for own installers.

The C Runtime is called "Microsoft.VC80.CRT." The directory name
contains other information too, e.g. on my box it's
"x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_0de06acd."

Anyway, this is the first place the is searched for a compatible
unmanaged assembly. "compatible" because the version that is linked -
that is, specified in the manifest - must not, and in case of the C
Runtime most likely will not, match the installed version. There's a
version redirect file that says "if the requested version is in this
range, use that installed version." This redirect only applies to the
last two version fields, which means you can't redirect something from
version "8.0.a.b" to version "8.1.c.d".

If the unmanaged assembly is not found there the application directory
is searched - then it's called a "private unmanaged assembly." First in
a directory named after the assembly, e.g. "Microsoft.VC80.CRT."
Finally, and this is probably for compatability with older OS' like
Windows NT, in the directory containing the application.

Note that just putting the DLLs in this directory is not sufficient.
One needs a manifest - "<assembly name>.manifest," e.g.
"Microsoft.VC80.CRT.manifest" - that describes the DLLs.


So this is how the system searches for the unmanaged assemblies. The
application and libraries itself needs some work, too.

When an unmanaged assembly is used, the EXE or DLL needs some manifest
that describes the dependency. Here's a typical manifest for an
application depending on Microsoft.VC80.CRT:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly
xmlns='urn:schemas-microsoft-com:asm.v1'
manifestVersion='1.0'>
<dependency>
<dependentAssembly>
<assemblyIdentity
type='win32'
name='Microsoft.VC80.CRT'
version='8.0.50608.0'
processorArchitecture='x86'
publicKeyToken='1fc8b3b9a1e18e3b'
/>
</dependentAssembly>
</dependency>
</assembly>


Again, there's more than one place this manifest is searched for.
First, for EXE files the manifest may be in the image as a resource with
ID 1, or it can be in the same directory as the EXE as a file. I think
the latter takes precedence.

For DLLs there is no choice - it must be in the image as a resource with
ID 2. Yes, that's the number two here!

The best way to go seems to always include the manifest. There are two
ways to get the manifest in there: Add it just as any other resource
(create a resource script, compile it with the resource compiler rc and
supply the output to the linker), or use the "manifest tool" (mt.exe) to
add it.

There's also something called "strong assemblies," which also contain a
signature of the images. For these, only the resource way can be used
because adding the manifest with the manifest tool would invalidate the
signature.


Finally, there's the question where to get the the manifest from. One
way would be to add it as any other text file. Another would be to use
the one generated by the linker. Yes, the linker creates the manifest
file as part of it's output. Using the linker alternative above to
include the manifest would mean the linker needs to be invoked twice.


On Windows I think there's no good way around this new scheme. One way,
and I think this would be a bad hack, would be to compile the C Runtime
library as a plain old DLL. I think the source is distributed with the
full Visual Studio 2005, but not with the Express Edition. Not sure
what the terms are under with such a custom C runtime library may be
distributed, though.

Ron

Ron Blaschke

unread,
Nov 21, 2006, 4:34:25 PM11/21/06
to Steve Hay, perl5-...@perl.org, parrot-...@perl.org
Steve Hay wrote:
> FYI, I spent quite a while recently struggling with this stuff (for
> perl5) and eventually arrived at much the same conclusion. Change
> #29266 implements using the manifest tool to embed the manifest file
> generated by the linker:
> http://public.activestate.com/cgi-bin/perlbrowse?show_patch=Show+Patch&patch_num=29266

I had another look at Microsoft's website, and found this section.

Building C/C++ Isolated Applications and Side-by-side Assemblies
http://msdn2.microsoft.com/en-us/library/ms235532.aspx

Not sure if this is new or if I missed it the last time around.

Ron

0 new messages