Sharing Code

J

Jonathan Wood

Smithers,
<< I'll probably just add references to the DLL >>

How does that satisfy any of your complaints about distributing multiple
copies of the .dll with each application?

What I've been describing is referencing the *same* DLL from several
applications, which are running only on my desktop BTW.

What distribution are you referring to?
 
G

GlennDoten

Jon said:
You've just provided the reason yourself. *Everything* has to be
signed. Not just your own code, but anything else you use.

Yes, and that's a good thing. It's better to make sure your assemblies,
and any dependent assemblies you need, are signed (or you have signed
yourself with the IL trick I described), from the get-go. That's a lot
easier than one day finding for whatever reason you must have the
assembly signed and now you have to spend all this time trying to do
that. Just do it from the beginning and you're all set. At the least,
you'll know if you have dependencies on unsigned assemblies, which is a
good thing to know about.

There's just too many good reasons to sign an assembly that far outweigh
the few seconds it takes to do so.
It doesn't take *no* effort to sign an assembly. Is it *fairly* quick?
Yes. That's not the same as *no* effort.

The effort to sign an assembly is about as close to 0 as you can get.
It's not "fairly quick" it's almost instantaneous. It literally takes
seconds to run sn.exe and once you have a key file it takes no effort at
all.
One you've signed your
production assembly, you're *forced* to sign your unit test assembly if
you want to use InternalsVisibleToAttribute.

First, if that were true, so what? Like I said, there's no reason not to
sign a test assembly.

In any event, I think you have the InternalsVisibleToAttribute attribute
backwards. The docs say this attribute can only be applied to
strong-named (i.e., signed) assemblies for the purpose of allowing
nonpublic types to be visible to another assembly. So you would use this
assembly *in* your production assembly, not in the *test* assembly. And
if you choose to use that attribute in your production assembly then you
have no choice but to sign it. The usage of that attribute in the
production assembly forces you to sign your test assembly just as much
as signing the production assembly does.

Do I misundertand the intent of the InternalsVisibleToAttribute
attribute? I mean it's not like you'd use the
InternalsVisibleToAttribute attribute in your test assembly to get at
nonpublic types in the production assembly, it would be the other way
around. Further, the attribute requires you to specify at compile-time
what assembly will be able to reflect on the nonpublic types at run-time
so I think throwing this attribute into a discussion about signing or
not signing, as a matter of course, the assemblies you create. I don't
see what you are driving at by mentioning this attribute.
These are all significant costs in my view. I'll sign an assembly when
I really need to, but I try to avoid it otherwise.

That's certainly a viable way to do things, and is probably what most
people do. But my dealings have shown me that when you suggest to
someone they sign any assemblies they create they think there is some
big, complex set of steps involved, when that is hardly the case.

Are you really saying that running sn.exe *once*, and only once, to get
a key file is a big deal. We're talking seconds here. And then to go
to a project's properties and browse to that key file *once per
project*, again, something that takes a few seconds, is really some sort
of burden that should be worried about? You view that as a significant
time cost? Paint me confused!

Let me ask you this: when do you "really need to" sign an assembly and
why? Under what circumstances would you sign an assembly and how would
those circumstances somehow make it undesirable to not just sign all the
assemblies and be done with it? Or would they?
 
J

J.B. Moreno

Jonathan Wood said:
As I indicated elsewhere, I can see wanting to stick the library in the same
folder as the application for libraries that receive wide distribution. But,
for in-house stuff, I don't like that approach.

When deciding to how to use/distribute a library, you need to look at
your situation and determine what your needs are.

Decide the things you want to happen, and how important they are...what
trade off as are you willing to make, what aren't you willing to do
without....

And there will be your answer as to what to do....
 
J

Jon Skeet [C# MVP]

GlennDoten said:
Yes, and that's a good thing. It's better to make sure your assemblies,
and any dependent assemblies you need, are signed (or you have signed
yourself with the IL trick I described), from the get-go. That's a lot
easier than one day finding for whatever reason you must have the
assembly signed and now you have to spend all this time trying to do
that. Just do it from the beginning and you're all set. At the least,
you'll know if you have dependencies on unsigned assemblies, which is a
good thing to know about.

There's just too many good reasons to sign an assembly that far outweigh
the few seconds it takes to do so.

I think we'll have to agree to differ.
The effort to sign an assembly is about as close to 0 as you can get.
It's not "fairly quick" it's almost instantaneous. It literally takes
seconds to run sn.exe and once you have a key file it takes no effort at
all.

Except putting things in source control (or deciding not to), undoing
whatever VS2005 does wrong (if you tell it to sign an assembly, it
decides that even if you've told it to sign the assembly using a key
which is already under source control, it will add another copy in the
current directory) etc.
First, if that were true, so what? Like I said, there's no reason not to
sign a test assembly.

Yes, it is true
In any event, I think you have the InternalsVisibleToAttribute attribute
backwards.

Nope. Believe me, I've run into this.
The docs say this attribute can only be applied to
strong-named (i.e., signed) assemblies for the purpose of allowing
nonpublic types to be visible to another assembly.

The docs for InternalsAreVisibleTo are completely broken. You don't
need assemblies to be signed at all for it to work normally, but if
you're going to use it on a signed assembly, the assembly you're
allowing access to it has to be signed to. It's sort of as if the
production assembly references the test assembly.
So you would use this
assembly *in* your production assembly, not in the *test* assembly.

Yes, I know.
And if you choose to use that attribute in your production assembly
then you have no choice but to sign it.

No, you don't.
The usage of that attribute in the production assembly forces you to
sign your test assembly just as much as signing the production
assembly does.

No: I can test a signed assembly from an unsigned assembly if I don't
need InternalsVisibleTo. I can't otherwise. Try it!
Do I misundertand the intent of the InternalsVisibleToAttribute
attribute?

No - you've just believed the docs, which are wrong. Give it a try and
you'll see what I mean.
I mean it's not like you'd use the
InternalsVisibleToAttribute attribute in your test assembly to get at
nonpublic types in the production assembly, it would be the other way
around. Further, the attribute requires you to specify at compile-time
what assembly will be able to reflect on the nonpublic types at run-time
so I think throwing this attribute into a discussion about signing or
not signing, as a matter of course, the assemblies you create. I don't
see what you are driving at by mentioning this attribute.

It forces me to sign something I wouldn't otherwise be forced to sign -
*if* I sign the production assembly. It's entirely relevant to the
discussion, as it's another way in which signing is viral.
That's certainly a viable way to do things, and is probably what most
people do. But my dealings have shown me that when you suggest to
someone they sign any assemblies they create they think there is some
big, complex set of steps involved, when that is hardly the case.

I don't think it's a big, complex set of steps. I think it's a small
set of steps which is reproduced for each projects. If you've got a lot
of projects, it's a significant hit.
Are you really saying that running sn.exe *once*, and only once, to get
a key file is a big deal. We're talking seconds here. And then to go
to a project's properties and browse to that key file *once per
project*, again, something that takes a few seconds, is really some sort
of burden that should be worried about? You view that as a significant
time cost? Paint me confused!

Managing projects is enough of a pain already (I really hate that VS
has to be told about each individual file) - I'd rather not add
anything else to that.
Let me ask you this: when do you "really need to" sign an assembly and
why? Under what circumstances would you sign an assembly and how would
those circumstances somehow make it undesirable to not just sign all the
assemblies and be done with it? Or would they?

I really need to sign an assembly if:

1) I need to reference it from another signed assembly
2) I have clients (of whatever nature) who need a signed assembly for
whatever reason
3) I want to put the assembly in the GAC (which I normally avoid)

Do you obfuscate your code, btw? I seem to remember (and it would make
sense) that it makes that slightly more tricky too. No doubt it's only
another couple of steps, but while I don't get significant benefit from
it, I'd rather not have the extra steps. (I prefer not to obfuscate in
the first place, but...)
 
S

Smithers

RE:
<< What I've been describing is referencing the *same* DLL from several
applications >>

Yes, I know - same DLL from several applicaitons - got it several posts ago.

So - what do you mean by "referencing the same DLL from several
applications" Are you talking about "setting a reference" to the DLL in
Visual Studio? If not, then how specifically are you planning to "set a
reference" outside of Visual Studio. It's starting to sound like you are
planning on running your applications from within Visual Studio - is that
correct.

RE:
<< What distribution are you referring to?>>

Your applications, of course.

-S
 
L

Leon Lambert

You must be working in isolation. On the other hand I work in a very
large company with global development. Our customers only want to deal
with validating few keys from a company. Our developers are not allowed
to willy nilly create keys to sign their assemblies. Microsoft
recommends that a very small group in a company manage all keys and
there should not be more than a hand full. Developers are not given the
keys. So as you can see this leads to a lot of pain to the developers
and organizations for managing things properly. Because of this most of
our developers want to avoid signing assemblies at all costs or they are
stuck having to deal with a lot of extra bureaucracy.

Bottom line is managing keys like Microsoft recommends is very painful
if you are in a large organization. If just one of a companies keys is
compromised by a hacker then it could lead to huge legal problems. So
keys need to be treated very seriously. So the tendency is to just key
stuff that represents the "Family Jewels".

Something to think about.
 
G

GlennDoten

You must be working in isolation. On the other hand I work in a very
large company with global development. Our customers only want to deal
with validating few keys from a company. Our developers are not allowed
to willy nilly create keys to sign their assemblies. Microsoft
recommends that a very small group in a company manage all keys and
there should not be more than a hand full. Developers are not given the
keys. So as you can see this leads to a lot of pain to the developers
and organizations for managing things properly. Because of this most of
our developers want to avoid signing assemblies at all costs or they are
stuck having to deal with a lot of extra bureaucracy.

Nope. Over the past seven years (my .NET time) I've worked in
multi-billion dollar companies. And very small ones too. And I do
independent development. In all scenarios I've always signed all
assemblies. It's the easiest way to operate. You must not have used
BizTalk for example. This thing (don't ask me why; I know why, but it
was a poor design decision on MS' part) requires all assemblies you
write for it to be signed.

What do you mean by "validating" keys from a company? How would you do
that and--more importantly--why would you do that?

The places I've worked (a 1.5bln company was the last one up until
March) we simply created a key once and used it whenever an assembly was
made. There were no developers creating keys willy-nilly. (However, it
doesn't matter if the same key is used or not for different assemblies.
It's only important that the assembly has the "I'm signed" bit set so
that features like being able to place the assembly in the GAC are enabled.)

MS gave us the option to partially sign assemblies for the very concerns
you bring up. Any developer can have, know, and use the poublic of the
signing key-pair to sign any assembly they want.

I don't know, I guess maybe you're experience with a key-pair has been
different than mine (and my colleague's) in this regard.

Have you used BizTalk in your big company? It does seem to be the rage
these days in all the large MS shops. If so, how did you get around MS'
requirement of signing assemblies that are used by BizTalk? I believe
that MS had no problem with this requirement (although developers do!)
because these keys are not a legal thing but are just a way to ensure an
assembly contains the same bits it was originally created with when the
run-time loads it.
Bottom line is managing keys like Microsoft recommends is very painful
if you are in a large organization.

It hasn't been in the big companies I've worked in, but it sounds like
your experience has been different. Far enough!
If just one of a companies keys is
compromised by a hacker then it could lead to huge legal problems.

Um, what sort of legal problems? These keys are not legal entities;
there's no laws governing them. All they do is tell the run-time that
the bits it is loading are the same bits the compiler emitted when it
created the assembly. That's why the technical name for such an assembly
is that it has a "stong name" or is a "strong-named" assembly. It just
means the run-time can verify that the bits have not been tampered with,
nothing more, nothing less.

I've heard this sort of comment before and don't understand where it
comes from. If you could elaborate on it I sure would appreciate it.

Let me put it this way: If I hacked MS' private part of their signing
key-pair and created my own System.Windows.Forms.dll assembly and aigned
it with the same key-pair that MS does (again, presuming I were able to
hack the key-pair) then shipped it with a product or otherwise made it
available in the wild I would not be breaking any legal laws. I would
not be making friends with fellow developers, for sure. Am I missing
something?
Something to think about.

Indeed!
 
G

GlennDoten

Jon said:
I think we'll have to agree to differ.

On which part, the time it takes to sign an assembly or that there are
good reasons to sign them?
Except putting things in source control (or deciding not to), undoing
whatever VS2005 does wrong (if you tell it to sign an assembly, it
decides that even if you've told it to sign the assembly using a key
which is already under source control, it will add another copy in the
current directory) etc.

I think you are doing something wrong with VS then.
Yes, it is true


Nope. Believe me, I've run into this.

Run into what? I think I'm missing your point here.
The docs for InternalsAreVisibleTo are completely broken. You don't
need assemblies to be signed at all for it to work normally, but if
you're going to use it on a signed assembly, the assembly you're
allowing access to it has to be signed to. It's sort of as if the
production assembly references the test assembly.

I see what you mean. Without doing any signing I can create a class
library with that attribute and point it to another class library and
this second class library can see the first's private members. And the
code runs without signing any of the assemblies. Either it is broken
documentation or the implementation has a bug.

In any event, I'm not sure I understand your point w.r.t. this
attribute. You apparently don't need to sign an assembly that uses this
attribute and you apparently don't need to sign an assembly that
references an assembly with this attribute. So you can choose to sign or
not sign assemblies that use this attribute. What I don't understand is
what this has to do with my contention that it's a really good idea to
just sign everything and be done with it? How does this attribute change
that thought? (Clearly you don't agree with the concept I'm throwing out
there, but I miss how this attribute is a pro or con for the concept.)
Yes, I know.


No, you don't.

Silly me for once again believing the docs!
No: I can test a signed assembly from an unsigned assembly if I don't
need InternalsVisibleTo. I can't otherwise. Try it!

Again, what I said was due to believing the docs. I know that a signed
assembly can be tested without signing the testing assembly. I've done
that plenty of times. But this attribute has never crept into the
picture either way. But then I've primarily used NUnit and the VS'05
built-in testing stuff.
No - you've just believed the docs, which are wrong. Give it a try and
you'll see what I mean.

I just tried and see what you mean. It was certainly interesting to
learn about this attribute.
It forces me to sign something I wouldn't otherwise be forced to sign -
*if* I sign the production assembly. It's entirely relevant to the
discussion, as it's another way in which signing is viral.

I think I'm being dense. Didn't you just establish--due to a bug in the
docs--that signing isn't required for this attribute? So if I use this
attribute in the production assembly then the testing assembly does not
have to be signed. It can be, doesn't have to be. (I wouldn't call
signing assemblies "viral"; pretty odd outlook, IMO.)
I don't think it's a big, complex set of steps. I think it's a small
set of steps which is reproduced for each projects. If you've got a lot
of projects, it's a significant hit.

Well, we'll have to agree to disagree here. Taking a few seconds to
browsed to a .pfx file *once* when a project is *created* seems to me to
be a zero-effort task. But if you see those few seconds as somehow
adding up to a "significant hit" then so be it. And for the record, I've
set up the signing on a solution with close to 100 projects in it. Now
it can easily be argued that a solution should not have that many
projects (and I would agree) but it was also no big deal to add the .pfx
file to each. It would have been even quicker if this had been done from
the get-go. Oh, and all the projects always use a common ProjectInfo.cs
file (as we call them) that has the line that refers to the key file, so
no changes required there.
Managing projects is enough of a pain already (I really hate that VS
has to be told about each individual file) - I'd rather not add
anything else to that.

Again, I'll agree to disagree. Adding one file does not a pain make.

So what do you do when you run into a situation where you must sign? Say
you decide to use BizTalk? Now you have to go back and do what should
have been done to start with. Or if you happen to work on shipping code.
Do you really want to send unsigned code out into the wild and also make
you code (as distributed) unusable to a customer's signed assembly? I
can be more flexible for internal-only assemblies, until some wonderful
product like BizTalk creeps into the shop. And then there's the general
ability to place the assembly in the GAC.
I really need to sign an assembly if:

1) I need to reference it from another signed assembly
2) I have clients (of whatever nature) who need a signed assembly for
whatever reason
3) I want to put the assembly in the GAC (which I normally avoid)

So you don't like strong-named assemblies nor the GAC. Interesting view!
(Just kidding. If you can't get VS to behave for you w.r.t. key files
and if you don't like sharing assemblies in the GAC then that's your
valid take on all this.)
Do you obfuscate your code, btw?

No, never.
I seem to remember (and it would make
sense) that it makes that slightly more tricky too.

I don't see how. Signing an assembly (I think better said: giving a
strong name to an assembly) just adds a little block of metadata to the
assembly. Any obfuscator would still work the same way with an assembly
that is strong-named.
No doubt it's only
another couple of steps, but while I don't get significant benefit from
it, I'd rather not have the extra steps.

There wouldn't be any changes required to a build process that
obfuscates the resultant assemblies in order to "support" signed assemblies.
(I prefer not to obfuscate in
the first place, but...)

I certainly agree there.

I appreciate you taking the time on this topic. I really do want to know
if there is any reason for me not to sign all assemblies under my
control (i.e., where I am the decision-maker on signing or not signing)
and whether I should stop preaching "just sign everything, it makes the
most sense all around". I understand you point about adding the .pfx
file to a project when it is created, but that alone would not change my
attitude (not to say you don't have a valid point, I think we just have
different views on how difficult it is to add a file to a project one
time and how that somehow makes the project more complex.)
 
J

Jonathan Wood

Smithers,
<< What I've been describing is referencing the *same* DLL from several
applications >>

Yes, I know - same DLL from several applicaitons - got it several posts
ago.

If I add a reference to the DLL from my applications running on my desktop,
then there is no need to make multiple copies of the DLL. I can just have
multiple applications reference the same DLL.
So - what do you mean by "referencing the same DLL from several
applications" Are you talking about "setting a reference" to the DLL in
Visual Studio? If not, then how specifically are you planning to "set a
reference" outside of Visual Studio. It's starting to sound like you are
planning on running your applications from within Visual Studio - is that
correct.

So it sounds like you are saying when I build an application in Visual
Studio that has references to a DLL, that the compiled application will not
run outside Visual Studio. Is that what you're saying?
 
C

Carl Daniel [VC++ MVP]

Jonathan said:
Smithers,


If I add a reference to the DLL from my applications running on my
desktop, then there is no need to make multiple copies of the DLL. I
can just have multiple applications reference the same DLL.


So it sounds like you are saying when I build an application in Visual
Studio that has references to a DLL, that the compiled application
will not run outside Visual Studio. Is that what you're saying?

It might not. Adding a reference to a DLL at a specific location doesn't
make that DLL available on the load path for your program . For your
program to function outside the IDE, you either need to provide a copy of
the DLL in your application folder (which is what VS does by default), or
set the appropriate module loading path via your application's configu file
to enable the CLR to find your DLL.

The reference that's embedded in the compiled code doesn't have a full path
to the DLL - it has the assembly name, version number and strong-name
information corresponding to the DLL that you specified at compile time.
None of that tells the CLR how to find the DLL at run time, however.

-cd
 
C

Carl Daniel [VC++ MVP]

GlennDoten said:
No, never.


I don't see how. Signing an assembly (I think better said: giving a
strong name to an assembly) just adds a little block of metadata to
the assembly. Any obfuscator would still work the same way with an
assembly that is strong-named.

If you obfuscate your code, then you have to re-sign after obfuscation.
Obfuscation tools have options to do this. The same is true for intrusive
profiling - the profiler has to re-sign the module after injecting the
profiling stubs.

All of this gets to be compilcated in larger organizations where the SNK
file is controlled by a distribution group and is not available to the
developers. In this case, devs must delay-sign their modules, or do all
testing with unsigned modules (which can't be in the GAC) then test again
with signed modules (which can be in the GAC), etc. None of the steps are
difficult - it's just more steps.

-cd
 
G

GlennDoten

Carl said:
If you obfuscate your code, then you have to re-sign after obfuscation.
Obfuscation tools have options to do this. The same is true for intrusive
profiling - the profiler has to re-sign the module after injecting the
profiling stubs.

Thanks, I didn't think of that, but it makes complete sense. Since the
obfuscator is changing the bits in the assembly the hash (strong-name)
will then be different.

One more reason not to use an obfuscator!
All of this gets to be compilcated in larger organizations where the SNK
file is controlled by a distribution group and is not available to the
developers. In this case, devs must delay-sign their modules, or do all
testing with unsigned modules (which can't be in the GAC) then test again
with signed modules (which can be in the GAC), etc. None of the steps are
difficult - it's just more steps.

I believe that is why MS added support for .pfx files (instead of having
to use a .snk file).

Also, if protecting the private part of the key-pair is important,
there's no reason a .pfx couldn't be created for developers to use
during development and testing to allow full signing to be done in one
step. Then only the buildmaster would have to switch the .pfx files when
a final, release build is done. So in this case there's no additional
burden on the developers in comparison to not signing the assemblies.
And it's a solution that would probably have to be used anyhow if the
assembly must be signed.
 
J

Jonathan Wood

Carl,
It might not. Adding a reference to a DLL at a specific location doesn't
make that DLL available on the load path for your program . For your
program to function outside the IDE, you either need to provide a copy of
the DLL in your application folder (which is what VS does by default), or
set the appropriate module loading path via your application's configu
file to enable the CLR to find your DLL.

The reference that's embedded in the compiled code doesn't have a full
path to the DLL - it has the assembly name, version number and strong-name
information corresponding to the DLL that you specified at compile time.
None of that tells the CLR how to find the DLL at run time, however.

Well, I'll have to play with it a bit then. All I need right now is for
these apps to run locally. I may just check out the config setting you
mentioned.

Thanks.
 
S

Smithers

So it sounds like you are saying when I build an application in Visual
Studio that has references to a DLL, that the compiled application will
not run outside Visual Studio. Is that what you're saying?

Yes, that's what I'm saying.

When you set a reference to a dll in Visual Studio, it will, by default,
copy the dll (the thing you say you do NOT want to happen) to your
application's \bin directory. To check me on this, go ahead and set your
reference in Visual Studio, then right-click the referenced assembly in the
solution explorer and view properties. You will see Boolean property named
"Copy Local". When the value is "true" then Visual Studio copies the dll to
the application's \bin folder. You can proceed to develop - but when you go
to run the application outside of Visual Studio (i.e., when you have
distributed it to a user or to some location other than the VS project's
folder structure) you STILL must decide how you are going deploy the
referenced DLL. Your options have already been enumerated elsewhere in this
thread; the option that VS is assuming is that you will have one copy of the
DLL per application... thus the copy in the \bin directory. You could
alternatively place the DLL in the GAC, or in an arbitrary location provided
that you then update the codebase or probing elements in your app's .config
file.

This might help:
http://msdn2.microsoft.com/en-us/library/yx7xezcf.aspx

You still haven't answered the question:
<< what do you mean by "referencing the same DLL from several applications"
Are you talking about "setting a reference" to the DLL in Visual Studio? >>

If you were to tell us what *you believe that means*, then we might be able
to help you more efficiently. Right now we have to guess - and I'm guessing
that you have some faulty assumptions about how the CLR locates an assembly
at runtime - either from within Visual Studio or once deployed (run outside
of Visual Studio).

Setting a reference in Visual Studio, just so you know, does NOTHING to
ensure that multiple applications can use a *single copy* of a DLL, as
Visual Studio makes multiple copies (one per application) for you (per the
Copy Local = true default). Even if you set Copy Local = false, then you
still have to tell your applications how to locate the DLL once you deploy
the application and run it beyond Visual Studio (options including the GAC
or specifying location via codebase and probing elements in .config file).

HTH

-S

-S
 
S

Smithers

<snip>

RE:
<< All I need right now is for these apps to run locally >>

This fact is irrellevant to the CLR. It must find the referenced .DLL, and
you must control how that happens. You can't [do nothing | not make a
choice] about this... If you do not specify your preference, then Visual
Studio will decide for you. By default, Visual Studio simply copies
referenced DLL files to EACH application's \bin folder... which is what you
say you do NOT want.

-S
 
J

Jonathan Wood

I said I'd look into that config setting you mentioned. I understood you
were saying that would addres the issue you're talking about.
 
J

Jonathan Wood

Smithers,
When you set a reference to a dll in Visual Studio, it will, by default,
copy the dll (the thing you say you do NOT want to happen) to your
application's \bin directory.

Okay, I didn't realize it copied it. (This is the first time anything like
that was mentioned in this thread.)
You can proceed to develop - but when you go to run the application
outside of Visual Studio (i.e., when you have distributed it to a user or
to some location other than the VS project's folder structure) you STILL
must decide how you are going deploy the referenced DLL. Your options have
already been enumerated elsewhere in this thread; the option that VS is
assuming is that you will have one copy of the DLL per application... thus
the copy in the \bin directory. You could alternatively place the DLL in
the GAC, or in an arbitrary location provided that you then update the
codebase or probing elements in your app's .config file.

For my immediate needs, there really is no deployment. But, for obvious
reasons, I would like the application to be able to run outside of Visual
Studio.
Setting a reference in Visual Studio, just so you know, does NOTHING to
ensure that multiple applications can use a *single copy* of a DLL, as
Visual Studio makes multiple copies (one per application) for you (per the
Copy Local = true default). Even if you set Copy Local = false, then you
still have to tell your applications how to locate the DLL once you deploy
the application and run it beyond Visual Studio (options including the GAC
or specifying location via codebase and probing elements in .config file).

Got it.
 
J

Jon Skeet [C# MVP]

GlennDoten said:
On which part, the time it takes to sign an assembly or that there are
good reasons to sign them?

There are good reasons to sign them sometimes. I believe that most of
the time there's no need to sign them, and that it takes more than a
few seconds in total maintenance time.
I think you are doing something wrong with VS then.

I'm not in the habit of saying something is broken when it's not. Try
the following in VS2005:

1) Create a new project in one directory, e.g. c:\TestProject
2) Create a new key in a different directory, e.g. c:\TestKey
3) Go to the Signing tab of the properties view of the project, tick
"Sign the assembly" and then browse to the key
4) Now look in c:\TestProject - you'll find it's copied the key.

I didn't want it to copy the key, I wanted it to use the location I
browsed to. Otherwise each project has it's own key file, which isn't
what I want.

So, what am I doing wrong with VS?
Run into what? I think I'm missing your point here.

I've run into the problem where a production assembly being signed
means that a unit test assembly needs to be signed too, if you want to
use InternalsVisibleTo.
I see what you mean. Without doing any signing I can create a class
library with that attribute and point it to another class library and
this second class library can see the first's private members. And the
code runs without signing any of the assemblies. Either it is broken
documentation or the implementation has a bug.

As I said, the documentation is completely broken. You can either sign
both assemblies, or sign neither of them - but you can't just sign the
production assembly.
In any event, I'm not sure I understand your point w.r.t. this
attribute. You apparently don't need to sign an assembly that uses this
attribute and you apparently don't need to sign an assembly that
references an assembly with this attribute. So you can choose to sign or
not sign assemblies that use this attribute. What I don't understand is
what this has to do with my contention that it's a really good idea to
just sign everything and be done with it? How does this attribute change
that thought? (Clearly you don't agree with the concept I'm throwing out
there, but I miss how this attribute is a pro or con for the concept.)

If you have to sign the unit test assembly, that means you then have to
make sure that everything you reference from the unit test assembly
also has to be signed - including any third party assemnblies etc. The
viral nature of signing strikes again.

I really don't want to have to sign third party software - and if I
only have the binaries, it's pretty difficult to do so...
Silly me for once again believing the docs!

Well, silly you for believing the docs when someone who is not prone to
making stuff up has disputed them.
Again, what I said was due to believing the docs. I know that a signed
assembly can be tested without signing the testing assembly. I've done
that plenty of times. But this attribute has never crept into the
picture either way. But then I've primarily used NUnit and the VS'05
built-in testing stuff.

We use NUnit too. The choice of unit test framework makes no difference
to whether or not InternalsVisibleTo is useful.
I just tried and see what you mean. It was certainly interesting to
learn about this attribute.

It's really helpful - but a pain when it means you have to sign stuff
you wouldn't otherwise bother with.
I think I'm being dense. Didn't you just establish--due to a bug in the
docs--that signing isn't required for this attribute? So if I use this
attribute in the production assembly then the testing assembly does not
have to be signed. It can be, doesn't have to be.

If the production assembly is signed, the test assembly has to be too.
If the production assembly isn't signed, the test assembly doesn't have
to be.
(I wouldn't call
signing assemblies "viral"; pretty odd outlook, IMO.)

It's viral in the same way that the GPL is often considered viral - by
applying the property to one thing, it's required for others: if I want
to sign one assembly, I have to sign everything it references *and* any
unit test assemblies which want to reference its internals.
Well, we'll have to agree to disagree here. Taking a few seconds to
browsed to a .pfx file *once* when a project is *created* seems to me to
be a zero-effort task.

How can doing something be zero effort?

I've just been upgrading a bunch of projects from 1.1 to 2.0. In each
projects which was signed, in order to avoid warnings I moved the
signing from AssemblyInfo to the properties pane. I then had to
manually edit the project file due to the problem referred to earlier.

Believe me, this was far from zero effort.
But if you see those few seconds as somehow
adding up to a "significant hit" then so be it. And for the record, I've
set up the signing on a solution with close to 100 projects in it. Now
it can easily be argued that a solution should not have that many
projects (and I would agree) but it was also no big deal to add the .pfx
file to each. It would have been even quicker if this had been done from
the get-go. Oh, and all the projects always use a common ProjectInfo.cs
file (as we call them) that has the line that refers to the key file, so
no changes required there.

Sounds like you'll get a load of warnings in VS2005, which recommends
setting the key file in the project properties rather than
AssemblyInfo...
Again, I'll agree to disagree. Adding one file does not a pain make.

It does if you have to do it time and time again.
So what do you do when you run into a situation where you must sign?

I sign the assemblies I have to sign, but not others.
Say you decide to use BizTalk? Now you have to go back and do what should
have been done to start with. Or if you happen to work on shipping code.
Do you really want to send unsigned code out into the wild and also make
you code (as distributed) unusable to a customer's signed assembly?

Customers don't reference our assemblies. (For my open source
libraries, they're welcome to sign it if they want to.)
I can be more flexible for internal-only assemblies, until some wonderful
product like BizTalk creeps into the shop. And then there's the general
ability to place the assembly in the GAC.

The GAC is a pain in the neck for non-system assemblies, IME. It's
great for framework libraries, but I avoid putting my own ones in
there.
So you don't like strong-named assemblies nor the GAC.

The GAC has its place, for system-level assemblies. I can't remember
writing an assembly which I'd classify as system-level.

Strongly-named assemblies have their place too, but it's certainly not
for every assembly IMO.
Interesting view!
(Just kidding. If you can't get VS to behave for you w.r.t. key files
and if you don't like sharing assemblies in the GAC then that's your
valid take on all this.)

Please try the simple steps I've shown earlier. I'm really not making
it up about VS copying key files for no reason.
No, never.


I don't see how. Signing an assembly (I think better said: giving a
strong name to an assembly) just adds a little block of metadata to the
assembly. Any obfuscator would still work the same way with an assembly
that is strong-named.

The strongly-named assembly contains a hash of the data in the
assembly. The obfuscator changes that data - therefore it has to resign
it.
There wouldn't be any changes required to a build process that
obfuscates the resultant assemblies in order to "support" signed assemblies.

See above. The obfuscator would have to know about the private key in
order to resign the modified assembly.
I certainly agree there.

I appreciate you taking the time on this topic. I really do want to know
if there is any reason for me not to sign all assemblies under my
control (i.e., where I am the decision-maker on signing or not signing)
and whether I should stop preaching "just sign everything, it makes the
most sense all around". I understand you point about adding the .pfx
file to a project when it is created, but that alone would not change my
attitude (not to say you don't have a valid point, I think we just have
different views on how difficult it is to add a file to a project one
time and how that somehow makes the project more complex.)

If you find it to be genuinely zero effort, then that's fine - but it's
been a source of annoyance on a number of fronts for me.

How do you cope with third party components which aren't signed, by the
way?
 
S

Smithers

I think you're on your way now... but to be sure:

RE:
<< For my immediate needs, there really is no deployment. ... >>

There is no such thing as "no deployment". I suspect you are going with a
working definition of "deployment" as at least installing your app on a
machine other than your dev box. That's not a complete understanding of
"deployment" - and at least that's not a useful definition that is congruent
with the docs that describe deployment options (XCopy, etc).

You have two basic options for running your apps on your local machine
without using the Visual Studio IDE.

1. Make use of the directory structure that Visual Studio sets up for you.
In this case, you would launch your .exe from a fulder under the \bin
directory (e.g. MyProject\bin\Debug. The debug folder is where VS places
projects you build in debug mode. You will see that all referenced
assemblies with Copy Local = true are also copied to the \bin\Debug folder
(I'm using VS2008 beta 2, but IIRC these folder structures haven't changed
from 2005).

2. Make use of some directory OTHER than that set up by Visual studio. When
you do this, you have "deployed" your application. It doesn't matter if it's
on the local machine or out to 5000 users. The easiest way to do this is to
simply copy all of the files in the \bin\Debug (or Release) folders to your
other folder. This is known as "XCopy deployment" because you are just
copying files to a new destination. If you want to make use of the GAC or
specify arbitrary folder from which to share dlls amongst apps, then you
cannot go with XCopy deployment and would have to then figure out how to get
your DLLs into the GAC or specify location via codebase or probing elements
in each application's .config file.

Note that option 1 above is really "XCopy deployment" that is done for you
by Visual Studio.

-HTH
 
J

Jonathan Wood

Smithers,
There is no such thing as "no deployment". I suspect you are going with a
working definition of "deployment" as at least installing your app on a
machine other than your dev box. That's not a complete understanding of
"deployment" - and at least that's not a useful definition that is
congruent with the docs that describe deployment options (XCopy, etc).

Well, my definition of "no deployment" for this discussion was to build my
application and then use that application file without changing its location
whatsoever. So, yeah, I guess it's hard for me to describe that as a
deployment.
You have two basic options for running your apps on your local machine
without using the Visual Studio IDE.

1. Make use of the directory structure that Visual Studio sets up for you.
In this case, you would launch your .exe from a fulder under the \bin
directory (e.g. MyProject\bin\Debug. The debug folder is where VS places
projects you build in debug mode. You will see that all referenced
assemblies with Copy Local = true are also copied to the \bin\Debug folder
(I'm using VS2008 beta 2, but IIRC these folder structures haven't changed
from 2005).

2. Make use of some directory OTHER than that set up by Visual studio.
When you do this, you have "deployed" your application. It doesn't matter
if it's on the local machine or out to 5000 users. The easiest way to do
this is to simply copy all of the files in the \bin\Debug (or Release)
folders to your other folder. This is known as "XCopy deployment" because
you are just copying files to a new destination. If you want to make use
of the GAC or specify arbitrary folder from which to share dlls amongst
apps, then you cannot go with XCopy deployment and would have to then
figure out how to get your DLLs into the GAC or specify location via
codebase or probing elements in each application's .config file.

Yeah, I'm not new to VS, only .NET, so I understand about the output folders
and I'm familiar with "XCOPY deployment."

I had understood your comments to mean I could use method 1 above with Copy
Local = false, and that there was was config setting that I could use to
tell my application how to locate a referenced assembly.
 

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