Manifests and VC8

R

Richard Grimes

I have just installed VS2005 RTM on a machine that has *never* had any
of the beta versions. It did have VS2003, but I uninstalled that.

I built a DLL with the new managed C++ syntax. The linker generated a
manifest, so far so good. The manifest says that there is a dependency
to Microsoft.VC80.CRT version 8.0.50608.0. (Note that I do not
explicitly use the CRT, the compiler is adding the dependency, but that
is not the issue in this post.)

When I run a process that uses this DLL I get a FileNotFoundException.
%windir%\WinSxS does not have an entry for this particular version. The
nearest I can find is

x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_f75eb16c

Note that the only difference between this and the reference in the
manifest is the version. (The public key token is the same.) So why is
link version 14.00.50727.42 creating a manifest to an unmanaged that
does not, and has never, existed on my machine?

Richard
 
C

Carl Daniel [VC++ MVP]

Richard said:
I have just installed VS2005 RTM on a machine that has *never* had any
of the beta versions. It did have VS2003, but I uninstalled that.

I built a DLL with the new managed C++ syntax. The linker generated a
manifest, so far so good. The manifest says that there is a dependency
to Microsoft.VC80.CRT version 8.0.50608.0. (Note that I do not
explicitly use the CRT, the compiler is adding the dependency, but
that is not the issue in this post.)

When I run a process that uses this DLL I get a FileNotFoundException.
%windir%\WinSxS does not have an entry for this particular version.
The nearest I can find is

x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_f75eb16c

Note that the only difference between this and the reference in the
manifest is the version. (The public key token is the same.) So why is
link version 14.00.50727.42 creating a manifest to an unmanaged that
does not, and has never, existed on my machine?

Interesting.

I just did a quick test, creating a C++ class library and a C# app that uses
that library. The app runs just fine, but examining the files produced for
the C++ class library, I see a manifest, and that manifest does indeed have
version 50608.0 specifies in it and not version 50727.42.

So there's at least two things here that I don't understand:

1. Why the wrong build number in the manifest?
2. Why did it work for me but not for you despite that wrong build number?

I'm going to forward those questions on to the VC++ team - there's something
very fishy going on here.

-cd
 
R

Richard Grimes

Carl said:
Richard Grimes wrote:

Interesting.

I just did a quick test, creating a C++ class library and a C# app
that uses that library. The app runs just fine, but examining the
files produced for the C++ class library, I see a manifest, and that
manifest does indeed have version 50608.0 specifies in it and not
version 50727.42.
So there's at least two things here that I don't understand:

1. Why the wrong build number in the manifest?
2. Why did it work for me but not for you despite that wrong build
number?

Here's some more information. I compiled on the command line, with no
pre-compiled headers (/clr /LD /Zi /MDd); I was not using a VS project.
Then I created a VS project for the class library, and compiled for
Debug. I copied this new library into the folder where my app was (a
simple C# process), ran it, and the problems disappeared.

Searching through the VS build output log the difference appears to be
that the VC project embeds the manifest using mt.exe, and I am not doing
this on the command line. So I took the library I created on the command
line and embedded the manifest in it with mt.exe. The library is now
loaded and I don't get any errors.

It seems to me that the managed C++ compiler is useless if it cannot be
used to build a library on the command line. I have been using it since
C/C++ v7 and as far as I can remember I have been able to compile and
link a DLL using just the compiler (cl.exe). Version 14 has broken this,
because to get a library that will load I must massage the DLL with
mt.exe. This is a step backward IMO.
I'm going to forward those questions on to the VC++ team - there's
something very fishy going on here.

Thanks, please do. It appears that as far as anyone on the .NET team is
concerned, I have been ex-communicated. :-(

Richard
 
C

Carl Daniel [VC++ MVP]

Richard Grimes said:
Here's some more information. I compiled on the command line, with no
pre-compiled headers (/clr /LD /Zi /MDd); I was not using a VS project.
Then I created a VS project for the class library, and compiled for Debug.
I copied this new library into the folder where my app was (a simple C#
process), ran it, and the problems disappeared.

Searching through the VS build output log the difference appears to be
that the VC project embeds the manifest using mt.exe, and I am not doing
this on the command line. So I took the library I created on the command
line and embedded the manifest in it with mt.exe. The library is now
loaded and I don't get any errors.

It seems to me that the managed C++ compiler is useless if it cannot be
used to build a library on the command line. I have been using it since
C/C++ v7 and as far as I can remember I have been able to compile and link
a DLL using just the compiler (cl.exe). Version 14 has broken this,
because to get a library that will load I must massage the DLL with
mt.exe. This is a step backward IMO.


Thanks, please do. It appears that as far as anyone on the .NET team is
concerned, I have been ex-communicated. :-(

Here's the reply that I got:

<quote>
The version in the external manifest file or the embeded manifest will show
8.0.50608.0 as you indicated. What really happens is that there are policies
at the WinSxS\policies directory that maps such version to 8.0.50727.42.
That explains why it works even when you are seeing the different version in
the manifest generated.

For example building a simple a.cpp application with /MD will generate a
manifest containing
<assemblyIdentity type='win32' name='Microsoft.VC80.CRT'
version='8.0.50608.0' processorArchitecture='x86'
publicKeyToken='1fc8b3b9a1e18e3b' />

Whe you run the application the policy on my machine at
%windir%\WinSxS\Policies\x86_policy.8.0.Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_x-ww_77c24773\8.0.50727.4
2.policy (which contains the below) will direct the binary to the new
version
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT"
processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
<bindingRedirect oldVersion="8.0.41204.256-8.0.50608.0"
newVersion="8.0.50727.42"/>

The policy directs a certain range of versions to the newer version manifest
at the SxS directroy.
</quote>

Looking on my machine, I have a file

8.0.50727.26.policy

in directory

C:\WINDOWS\WinSxS\Policies\x86_policy.8.0.Microsoft.VC80.DebugCRT_1fc8b3b9a1e18e3b_x-ww_09e017b4

that remaps the 50608.0 build to the correct assembly (I'm using RC1 instead
of RTM, which is why mine say .26 instead of .42).

Perhaps that policy is missing/wrong on your machine?

-cd
 
R

Richard Grimes

Carl,
Perhaps that policy is missing/wrong on your machine?

No I have the policy file and it contains the right information.
However, in my last post I identified what I think is the real reason
for the file load error in the original post.

I compiled at the command line and hence the manifest appeared in a
separate file. The documentation says that the side-by-side mechanism
should prefer the file to an embedded resource 'manifest'. However this
does not seem to be the case, the Win32 'assembly' will not be loaded.
If I embed the 'manifest' in the .NET assembly file (I wished SxS hadn't
decided to overload assembly and manifest) then the Win32 file is
correctly loaded.

Also, it seems odd to provide a policy file in this situation. Why
didn't they just issue a new version of the 'assemblies' for the RTM of
VS?

Richard
 
G

Guest

Hi Richard,
I am the one who actually posted the reply to Carl in his latest reply.

For dlls, you will have to embed the manifest into your dll. I can hook you
up with the Libraries folks if you need more info on why you need to do so.

Thanks,
Ayman
 
R

Richard Grimes

Hi Ayman,
I am the one who actually posted the reply to Carl in his latest
reply.

For dlls, you will have to embed the manifest into your dll. I can
hook you up with the Libraries folks if you need more info on why you
need to do so.

Thanks. I would like to know why the manifest has to be embedded. I am
writing about compiling .NET libraries with C++ and will publish it
here:

http://www.grimes.demon.co.uk/workshops/fusWSTwelve.htm

So it would be nice to give a definitive reason.

Richard
 
G

Guest

Hi,

DLLs have to have manifest embedded inside. It was a decision made by
Windows team that LoadLibrary() ignores external manifest for DLLs and loads
a DLL in activation context of the loader. To activate context of the DLL, it
has to have manifest embedded inside DLL with ID==2.

As for why linker does not embedd manifest, this is another question. There
are number of reasons why we did not do this in VS2005, however I think this
may be changed in the next release. This is certainly a feature on the top of
our list for the next release.

Nikola
VC++
 
R

Richard Grimes

Hi Nikola,

Thanks.
DLLs have to have manifest embedded inside. It was a decision made by
Windows team that LoadLibrary() ignores external manifest for DLLs
and loads a DLL in activation context of the loader. To activate
context of the DLL, it has to have manifest embedded inside DLL with
ID==2.

Indeed. So the rules have changed. OK, I can accept that, but it would
have been better if the OS people had made it more well known. Can you
get the documentation changed:

http://msdn.microsoft.com/library/en-us/sbscs/setup/assembly_manifests.asp

says:
Assembly manifests can be installed in three locations:

[snip]


a.. As manifests that accompany private assemblies, assembly manifests
should installed in the directory structure of the application. This is
usually a separate file in the same folder as the application's
executable file.
b.. As a resource in a DLL, the assembly is available for the private
use of the DLL. An assembly manifest cannot be included as a resource in
an EXE. An EXE file may include an application manifest as a resource.
This clearly says that a separate file is acceptable. Also:

http://msdn.microsoft.com/library/en-us/sbscs/setup/assembly_searching_sequence.asp

says:

The first time side-by-side searches for a private assembly, it
determines whether a language-specific subfolder exists in the
application's directory structure. If no language-specific subfolder
exists, side-by-side searches for the private assembly in the following
locations using the following sequence.
1.. Side-by-side searches the WinSxS folder.
2.. \\<appdir>\<assemblyname>.DLL
3.. \\<appdir>\<assemblyname>.manifest
4.. \\<appdir>\<assemblyname>\<assemblyname>.DLL
5.. \\<appdir>\<assemblyname>\<assemblyname>.manifest
etc etc (this page keeps saying that the manifest file will be used if a
bound unmanaged resource is not available).

Also while you are talking to the MSDN documention people could you get
them to document *all* of the switches for mt.exe?

Frankly, this page is pathetic:

http://msdn.microsoft.com/library/en-us/sbscs/setup/mt_exe.asp

mt /?

at the command line gives pages of switches.
As for why linker does not embedd manifest, this is another question.
There are number of reasons why we did not do this in VS2005, however
I think this may be changed in the next release. This is certainly a
feature on the top of our list for the next release.

That is good news. I am sure I am like most C++ developers, I expect the
C++ compiler/linker to compile my code and work straightaway, just as it
did with the last version of the compiler/linker. This does not happen
with the current version and in my opinion that is a 'feature' that
should not have occurred.

It would have been less bad if the linker had a
create-manifest-but-don't-link option so that I could call the linker
once to create the manifest, generate a resource script and compile it,
and then call the linker again to create the pe file. Calling the linker
twice just feels wrong. However, manipulating the output of the linker
with mt.exe feels even more wrong.

Anyway, I have written up the process of handling manifest files in both
managed and unmanaged code and they will appear on this page in a day or
two:

http://www.grimes.demon.co.uk/workshops/fusWSThirteen.htm

Richard
 
T

Ted

Wow, excellent article. A absolute must read for any unmanaged VC 2005 C++
programmer.

Ted.

Richard Grimes said:
Hi Nikola,

Thanks.
DLLs have to have manifest embedded inside. It was a decision made by
Windows team that LoadLibrary() ignores external manifest for DLLs
and loads a DLL in activation context of the loader. To activate
context of the DLL, it has to have manifest embedded inside DLL with
ID==2.

Indeed. So the rules have changed. OK, I can accept that, but it would
have been better if the OS people had made it more well known. Can you get
the documentation changed:

http://msdn.microsoft.com/library/en-us/sbscs/setup/assembly_manifests.asp

says:
Assembly manifests can be installed in three locations:

[snip]


a.. As manifests that accompany private assemblies, assembly manifests
should installed in the directory structure of the application. This is
usually a separate file in the same folder as the application's executable
file.
b.. As a resource in a DLL, the assembly is available for the private use
of the DLL. An assembly manifest cannot be included as a resource in an
EXE. An EXE file may include an application manifest as a resource.
This clearly says that a separate file is acceptable. Also:

http://msdn.microsoft.com/library/en-us/sbscs/setup/assembly_searching_sequence.asp

says:

The first time side-by-side searches for a private assembly, it determines
whether a language-specific subfolder exists in the application's
directory structure. If no language-specific subfolder exists,
side-by-side searches for the private assembly in the following locations
using the following sequence.
1.. Side-by-side searches the WinSxS folder.
2.. \\<appdir>\<assemblyname>.DLL
3.. \\<appdir>\<assemblyname>.manifest
4.. \\<appdir>\<assemblyname>\<assemblyname>.DLL
5.. \\<appdir>\<assemblyname>\<assemblyname>.manifest
etc etc (this page keeps saying that the manifest file will be used if a
bound unmanaged resource is not available).

Also while you are talking to the MSDN documention people could you get
them to document *all* of the switches for mt.exe?

Frankly, this page is pathetic:

http://msdn.microsoft.com/library/en-us/sbscs/setup/mt_exe.asp

mt /?

at the command line gives pages of switches.
As for why linker does not embedd manifest, this is another question.
There are number of reasons why we did not do this in VS2005, however
I think this may be changed in the next release. This is certainly a
feature on the top of our list for the next release.

That is good news. I am sure I am like most C++ developers, I expect the
C++ compiler/linker to compile my code and work straightaway, just as it
did with the last version of the compiler/linker. This does not happen
with the current version and in my opinion that is a 'feature' that should
not have occurred.

It would have been less bad if the linker had a
create-manifest-but-don't-link option so that I could call the linker once
to create the manifest, generate a resource script and compile it, and
then call the linker again to create the pe file. Calling the linker twice
just feels wrong. However, manipulating the output of the linker with
mt.exe feels even more wrong.

Anyway, I have written up the process of handling manifest files in both
managed and unmanaged code and they will appear on this page in a day or
two:

http://www.grimes.demon.co.uk/workshops/fusWSThirteen.htm

Richard
 
R

Richard Grimes

Ted said:
Wow, excellent article. A absolute must read for any unmanaged VC
2005 C++ programmer.

Thanks. It's a pity that the only place I can publish now is on my own
site.

Richard
 
D

Dave

As for why linker does not embedd manifest, this is another question. There
are number of reasons why we did not do this in VS2005, however I think this
may be changed in the next release. This is certainly a feature on the top of
our list for the next release.

Nikola, The whole process is counterintuitive in many respects. MS
and MVPs have said that unmanaged apps will work as they always have
and that nothing is needed except new runtime DLLs. Not only is that
incorrect, but as mentioned in a separate thread, the current system
does not seem to generate reliable standalone EXEs even when the
proper folders, dlls, manifests, policies and other convoluted
procedures are followed.

I've diff'd WinSxS folders between 'clean' test machines and the
development system and everything seems to be in line. Project
folders are Xcopied. All Win32 programs run on the development
machine. On the test machine they say: "The application has failed
to start because the application configuration is incorrect.
Reinstalling the application may fix this problem."

It would seem that there are still pieces missing. (Was this tested
thoroughly?)

By the way, I've also tried the procedure on your blog: Copy DLLs to
local folder, copy the manifest and rename it. Given that VS2005
generates a manifest that designates DLL a generation back (why?!!),
I wonder how that process would work. Don't you need a local policy
file to translate the DLL version number?

I've even tried updating the manifest number in the exe with a hex
editor, thinking that it may find the DLLs in the local folder. Still
no go.

So...what else could cause the error message above?
 
D

Dave

Thanks. It's a pity that the only place I can publish now is on my own
site.

Your books' info on bridging managed and unmanaged worlds was very
important when .NET was trying to get off the ground. I hope that MS
still appreciates that.

(Now PLEASE write a book on C++/CLI).
 
D

Dave

PS: Richard, your article states that shared assemblies (I'm assuming
that includes all WinSxS folders and files) *must* be installed by
Windows Installer. So...no XCopy deployment after all. What is
Windows Installer doing that XCopy wouldn't? (I do hope you're not
going to say the word 'registry.')
 
R

Richard Grimes

Dave said:
PS: Richard, your article states that shared assemblies (I'm assuming
that includes all WinSxS folders and files) *must* be installed by
Windows Installer.

Well, it comes from the documentation:

http://msdn.microsoft.com/library/d...es_for_side_by_side_sharing_on_windows_xp.asp

I have to admit I haven't tried to install a shared SxS assembly by hand
into the SxS cache, basically because I am not interested in native code
development. However, I guess the general principle is sound. The ACL on
the WinSxS folder only allows SYSTEM and Administrators to write there.
Also, a shared component should have a careful mechanism to uninstall it
(in particular, to have some reference count so that the number of
'uninstalls' correspond to the 'installs' of the same component).
Windows installer provides all of this.
So...no XCopy deployment after all. What is
Windows Installer doing that XCopy wouldn't? (I do hope you're not
going to say the word 'registry.')

he he, Windows Installer is not a .NET technology...

Richard
 
N

Nikola Dudar [MSFT]

Sorry for a late reply, somehow I only now can see this thread.

Information on these pages is correct. You DLL is not an side-by-side
assembly unless it has a corresponding manifest and follows naming rules. If
this is just a b.dll, it is not an assembly. All of information described in
this pages does not apply to your b.dll.

In a case of b.dll, the loader detects an attempt to load a b.dll and tries
activate proper context for this Dll. If a DLL specifies a manifest in ID=2,
the loader is going to try loading dependencies specified by the manifest.
Otherwise it relies on activation context of a loader (EXE or DLL).

The instruction on these MSDN pages apply to SxS assemblies. This is a a
case when b.dll has a manifest MyCompany.MyProduct.manifest and any consumer
of b.dll uses manifest to resolve dependency on this. In this case
MyCompany.MyProduct.manifest is an assembly manifest and all rules described
on these pages apply now.

This is a great article indeed. Thanks for summarizing all of this. As I
described above, text in the first black box is not correct. I should have
some time to review your article later today and send out some comments.

Thanks,
Nikola

--
Nikola Dudar
Visual C++ Team
This posting is provided "AS IS" with no warranties, and confers no rights.
Suggestions? Bugs? Talk directly to dev teams using
http://lab.msdn.microsoft.com/productfeedback/
My Blog - http://blogs.msdn.com/nikolad/


Richard Grimes said:
Hi Nikola,

Thanks.
DLLs have to have manifest embedded inside. It was a decision made by
Windows team that LoadLibrary() ignores external manifest for DLLs
and loads a DLL in activation context of the loader. To activate
context of the DLL, it has to have manifest embedded inside DLL with
ID==2.

Indeed. So the rules have changed. OK, I can accept that, but it would
have been better if the OS people had made it more well known. Can you get
the documentation changed:

http://msdn.microsoft.com/library/en-us/sbscs/setup/assembly_manifests.asp

says:
Assembly manifests can be installed in three locations:

[snip]


a.. As manifests that accompany private assemblies, assembly manifests
should installed in the directory structure of the application. This is
usually a separate file in the same folder as the application's executable
file.
b.. As a resource in a DLL, the assembly is available for the private use
of the DLL. An assembly manifest cannot be included as a resource in an
EXE. An EXE file may include an application manifest as a resource.
This clearly says that a separate file is acceptable. Also:

http://msdn.microsoft.com/library/en-us/sbscs/setup/assembly_searching_sequence.asp

says:

The first time side-by-side searches for a private assembly, it determines
whether a language-specific subfolder exists in the application's
directory structure. If no language-specific subfolder exists,
side-by-side searches for the private assembly in the following locations
using the following sequence.
1.. Side-by-side searches the WinSxS folder.
2.. \\<appdir>\<assemblyname>.DLL
3.. \\<appdir>\<assemblyname>.manifest
4.. \\<appdir>\<assemblyname>\<assemblyname>.DLL
5.. \\<appdir>\<assemblyname>\<assemblyname>.manifest
etc etc (this page keeps saying that the manifest file will be used if a
bound unmanaged resource is not available).

Also while you are talking to the MSDN documention people could you get
them to document *all* of the switches for mt.exe?

Frankly, this page is pathetic:

http://msdn.microsoft.com/library/en-us/sbscs/setup/mt_exe.asp

mt /?

at the command line gives pages of switches.
As for why linker does not embedd manifest, this is another question.
There are number of reasons why we did not do this in VS2005, however
I think this may be changed in the next release. This is certainly a
feature on the top of our list for the next release.

That is good news. I am sure I am like most C++ developers, I expect the
C++ compiler/linker to compile my code and work straightaway, just as it
did with the last version of the compiler/linker. This does not happen
with the current version and in my opinion that is a 'feature' that should
not have occurred.

It would have been less bad if the linker had a
create-manifest-but-don't-link option so that I could call the linker once
to create the manifest, generate a resource script and compile it, and
then call the linker again to create the pe file. Calling the linker twice
just feels wrong. However, manipulating the output of the linker with
mt.exe feels even more wrong.

Anyway, I have written up the process of handling manifest files in both
managed and unmanaged code and they will appear on this page in a day or
two:

http://www.grimes.demon.co.uk/workshops/fusWSThirteen.htm

Richard
 
N

Nikola Dudar [MSFT]

Hi Dave,

I am sorry for a late reply. Somehow I have missed replies to this thread.

I am hearing your concern. It is a new technology that we have to use in
VS2005 because of reasons greatly summarized by Martyn on his blog,
http://blogs.msdn.com/martynl/archive/2005/10/13/480880.aspx We attempted to
reduce any pain related to adaption of this change. Same merge modules were
provided with VS2005 for redistribution of VC apps as they were in VS2002
and VS2003, plus we enabled applocal redistribution and redistribution as a
bootstrapper package using vcredist_*.exe. As you may see, the whole section
of documentation was restructured and new guidance were added. This feature
does not change how VC apps function, it only brings up to surface a well
know issue that VC++ applications depends on VC++ DLLs and that these DLLs
have to be redistributed with your app. I see many folks that came from VC6
who was not doing this at all, expecting these DLLs be already installed by
OS. A model that was before in this area was more along lines of copying
DLLs to System32 or applocal folder or another folder on a PATH so your app
work now. This completely ignores issues that appear when another app may
install DLLs of other versions, uninstall your DLLs, etc. and how it may or
may not break your application. And emergency servicing of redistributed
DLLs is just a nightmare.Quite opposite to old model, the new naming of DLLs
inside VC++ assemblies and new deployment model provides a complete and
robust solution to redistribution of VC++ DLLs and methods of deployment
VC++ apps on end-user computers. Even there may be several improvements
should made to PSDK docs, docs for mt.exe or how linker operates on
manifest.

I am not aware of that another thread you have mentioned. I disagree with a
statement that the current version of VS2005 builds un-reliable EXEs. If you
have an example of this, please feel free to post it here. Of course, there
may be bugs but these are parts of different story. If you have similar
issues with your app, please feel free to follow up with me directly or
report them on Product Feedback site. Also you may find helpful in debugging
these issues Troubleshooting section of docs,
http://msdn2.microsoft.com/en-us/library/ms235342.aspx, section with
examples on how to deploy apps,
http://msdn2.microsoft.com/en-us/library/ms235285.aspx and overall section
describing supported policies for redistribution of VC++ libraries,
http://msdn2.microsoft.com/en-us/library/ms235316.aspx.

Thanks,
Nikola


--
Nikola Dudar
Visual C++ Team
This posting is provided "AS IS" with no warranties, and confers no rights.
Suggestions? Bugs? Talk directly to dev teams using
http://lab.msdn.microsoft.com/productfeedback/
My Blog - http://blogs.msdn.com/nikolad/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top