1111 using System . Text ;
1212 using Microsoft . Build . Framework ;
1313 using Microsoft . Build . Utilities ;
14- #if NET45
15- using PInvoke ;
16- #endif
14+
1715 public class AssemblyVersionInfo : Task
1816 {
1917#if NET45
@@ -121,7 +119,7 @@ private CodeTypeDeclaration CreateThisAssemblyClass()
121119
122120 // Determine information about the public key used in the assembly name.
123121 string publicKey , publicKeyToken ;
124- this . ReadKeyInfo ( out publicKey , out publicKeyToken ) ;
122+ bool hasKeyInfo = this . TryReadKeyInfo ( out publicKey , out publicKeyToken ) ;
125123
126124 // Define the constants.
127125 thisAssembly . Members . AddRange ( CreateFields ( new Dictionary < string , string >
@@ -130,58 +128,25 @@ private CodeTypeDeclaration CreateThisAssemblyClass()
130128 { "AssemblyFileVersion" , this . AssemblyFileVersion } ,
131129 { "AssemblyInformationalVersion" , this . AssemblyInformationalVersion } ,
132130 { "AssemblyName" , this . AssemblyName } ,
133- { "PublicKey" , publicKey } ,
134- { "PublicKeyToken" , publicKeyToken } ,
135131 { "AssemblyTitle" , this . AssemblyTitle } ,
136132 { "AssemblyProduct" , this . AssemblyProduct } ,
137133 { "AssemblyCopyright" , this . AssemblyCopyright } ,
138134 { "AssemblyCompany" , this . AssemblyCompany } ,
139135 { "AssemblyConfiguration" , this . AssemblyConfiguration }
140136 } ) . ToArray ( ) ) ;
141-
142- // These properties should be defined even if they are empty.
143- thisAssembly . Members . Add ( CreateField ( "RootNamespace" , this . RootNamespace ) ) ;
144-
145- return thisAssembly ;
146- }
147-
148- private void ReadKeyInfo ( out string publicKey , out string publicKeyToken )
149- {
150- byte [ ] publicKeyBytes = null ;
151- if ( ! string . IsNullOrEmpty ( this . AssemblyOriginatorKeyFile ) && File . Exists ( this . AssemblyOriginatorKeyFile ) )
137+ if ( hasKeyInfo )
152138 {
153- if ( Path . GetExtension ( this . AssemblyOriginatorKeyFile ) . Equals ( ".snk" , StringComparison . OrdinalIgnoreCase ) )
139+ thisAssembly . Members . AddRange ( CreateFields ( new Dictionary < string , string >
154140 {
155- byte [ ] keyBytes = File . ReadAllBytes ( this . AssemblyOriginatorKeyFile ) ;
156- bool publicKeyOnly = keyBytes [ 0 ] != 0x07 ;
157- publicKeyBytes = publicKeyOnly ? keyBytes : MSCorEE . StrongNameGetPublicKey ( keyBytes ) ;
158- }
159- }
160- else if ( ! string . IsNullOrEmpty ( this . AssemblyKeyContainerName ) )
161- {
162- publicKeyBytes = MSCorEE . StrongNameGetPublicKey ( this . AssemblyKeyContainerName ) ;
163- }
164-
165- if ( publicKeyBytes != null && publicKeyBytes . Length > 0 ) // If .NET 2.0 isn't installed, we get byte[0] back.
166- {
167- publicKey = ToHex ( publicKeyBytes ) ;
168- publicKeyToken = ToHex ( MSCorEE . StrongNameTokenFromPublicKey ( publicKeyBytes ) ) ;
141+ { "PublicKey" , publicKey } ,
142+ { "PublicKeyToken" , publicKeyToken } ,
143+ } ) . ToArray ( ) ) ;
169144 }
170- else
171- {
172- if ( publicKeyBytes != null )
173- {
174- this . Log . LogWarning ( "Unable to emit public key fields in ThisAssembly class because .NET 2.0 isn't installed." ) ;
175- }
176145
177- publicKey = null ;
178- publicKeyToken = null ;
179- }
180- }
146+ // These properties should be defined even if they are empty.
147+ thisAssembly . Members . Add ( CreateField ( "RootNamespace" , this . RootNamespace ) ) ;
181148
182- private static string ToHex ( byte [ ] data )
183- {
184- return BitConverter . ToString ( data ) . Replace ( "-" , "" ) . ToLowerInvariant ( ) ;
149+ return thisAssembly ;
185150 }
186151
187152 private IEnumerable < CodeAttributeDeclaration > CreateAssemblyAttributes ( )
@@ -276,9 +241,9 @@ private void CreateThisAssemblyClass()
276241 {
277242 this . generator . StartThisAssemblyClass ( ) ;
278243
279- ////// Determine information about the public key used in the assembly name.
280- //// string publicKey, publicKeyToken;
281- //// this.ReadKeyInfo (out publicKey, out publicKeyToken);
244+ // Determine information about the public key used in the assembly name.
245+ string publicKey , publicKeyToken ;
246+ bool hasKeyInfo = this . TryReadKeyInfo ( out publicKey , out publicKeyToken ) ;
282247
283248 // Define the constants.
284249 var fields = new Dictionary < string , string >
@@ -287,14 +252,18 @@ private void CreateThisAssemblyClass()
287252 { "AssemblyFileVersion" , this . AssemblyFileVersion } ,
288253 { "AssemblyInformationalVersion" , this . AssemblyInformationalVersion } ,
289254 { "AssemblyName" , this . AssemblyName } ,
290- ////{ "PublicKey", publicKey },
291- ////{ "PublicKeyToken", publicKeyToken },
292255 { "AssemblyTitle" , this . AssemblyTitle } ,
293256 { "AssemblyProduct" , this . AssemblyProduct } ,
294257 { "AssemblyCopyright" , this . AssemblyCopyright } ,
295258 { "AssemblyCompany" , this . AssemblyCompany } ,
296259 { "AssemblyConfiguration" , this . AssemblyConfiguration }
297260 } ;
261+ if ( hasKeyInfo )
262+ {
263+ fields . Add ( "PublicKey" , publicKey ) ;
264+ fields . Add ( "PublicKeyToken" , publicKeyToken ) ;
265+ }
266+
298267 foreach ( var pair in fields )
299268 {
300269 if ( ! string . IsNullOrEmpty ( pair . Value ) )
@@ -389,5 +358,79 @@ internal override void EndThisAssemblyClass()
389358 }
390359 }
391360#endif
361+
362+ private static string ToHex ( byte [ ] data )
363+ {
364+ return BitConverter . ToString ( data ) . Replace ( "-" , "" ) . ToLowerInvariant ( ) ;
365+ }
366+
367+ /// <summary>
368+ /// Gets the public key from a key container.
369+ /// </summary>
370+ /// <param name="containerName">The name of the container.</param>
371+ /// <returns>The public key.</returns>
372+ private static byte [ ] GetPublicKeyFromKeyContainer ( string containerName )
373+ {
374+ throw new NotImplementedException ( ) ;
375+ }
376+
377+ private static byte [ ] GetPublicKeyFromKeyPair ( byte [ ] keyPair )
378+ {
379+ byte [ ] publicKey ;
380+ if ( CryptoBlobParser . TryGetPublicKeyFromPrivateKeyBlob ( keyPair , out publicKey ) )
381+ {
382+ return publicKey ;
383+ }
384+ else
385+ {
386+ throw new ArgumentException ( "Invalid keypair" ) ;
387+ }
388+ }
389+
390+ private bool TryReadKeyInfo ( out string publicKey , out string publicKeyToken )
391+ {
392+ try
393+ {
394+ byte [ ] publicKeyBytes = null ;
395+ if ( ! string . IsNullOrEmpty ( this . AssemblyOriginatorKeyFile ) && File . Exists ( this . AssemblyOriginatorKeyFile ) )
396+ {
397+ if ( Path . GetExtension ( this . AssemblyOriginatorKeyFile ) . Equals ( ".snk" , StringComparison . OrdinalIgnoreCase ) )
398+ {
399+ byte [ ] keyBytes = File . ReadAllBytes ( this . AssemblyOriginatorKeyFile ) ;
400+ bool publicKeyOnly = keyBytes [ 0 ] != 0x07 ;
401+ publicKeyBytes = publicKeyOnly ? keyBytes : GetPublicKeyFromKeyPair ( keyBytes ) ;
402+ }
403+ }
404+ else if ( ! string . IsNullOrEmpty ( this . AssemblyKeyContainerName ) )
405+ {
406+ publicKeyBytes = GetPublicKeyFromKeyContainer ( this . AssemblyKeyContainerName ) ;
407+ }
408+
409+ if ( publicKeyBytes != null && publicKeyBytes . Length > 0 ) // If .NET 2.0 isn't installed, we get byte[0] back.
410+ {
411+ publicKey = ToHex ( publicKeyBytes ) ;
412+ publicKeyToken = ToHex ( CryptoBlobParser . GetStrongNameTokenFromPublicKey ( publicKeyBytes ) ) ;
413+ }
414+ else
415+ {
416+ if ( publicKeyBytes != null )
417+ {
418+ this . Log . LogWarning ( "Unable to emit public key fields in ThisAssembly class because .NET 2.0 isn't installed." ) ;
419+ }
420+
421+ publicKey = null ;
422+ publicKeyToken = null ;
423+ return false ;
424+ }
425+
426+ return true ;
427+ }
428+ catch ( NotImplementedException )
429+ {
430+ publicKey = null ;
431+ publicKeyToken = null ;
432+ return false ;
433+ }
434+ }
392435 }
393436}
0 commit comments