Signing unsigned assemblies in NuGet packages

I wrote a set of PowerShell cmdlets for signing unsigned assemblies with the SNK of your choice. Certain platforms (I'm looking at you, SharePoint) just work better with SN assemblies, but this constrains dependencies to NuGet packages that contain only signed assemblies.

Many people believe using strong names is more of a hindrance than a help (myself included,) but corporate policies often dictate their usage. My strong naming package makes it simple to sign assemblies, even without the source code. No more begging package authors to release signed packages, or fiddling with github repos.

If you sign 3rd party NuGet package assemblies, I suggest signing them in-situ, in their original locations, so you can continue to reference the package and so not risk missing out on updates. When you update a package, simply resign the assemblies and compile away.

To get started, open the NuGet PM console and type:

Install-Package Nivot.StrongNaming

You must have a solution open at this time. This package is not tied to any project; it just adds new commands to the PM console (documented below.)

Nivot.StrongNaming

  • v1.0.0 [2013/04/29]
    • Initial release.
  • v1.0.1 [2013/04/29]
    • Updated metadata.
  • v1.0.2 [2013/04/30]
    • Added license and project URL.
    • Added readme.MD

About

A set of PowerShell Cmdlets to facilitate signing of unsigned 3rd party assemblies with a key of your choice, to allow them to be referenced by strongly named projects.

A NuGet package is available at: https://nuget.org/packages/Nivot.StrongNaming

Syntax

All cmdlets accept pipeline input. The AssemblyFile parameter is aliased to PSPath, so it will bind to piped files.

  • Test-StrongName [-AssemblyFile] <string[]> [<CommonParameters>]

    Returns true if an assembly has a strong name.

  • Import-StrongNameKeyPair [-KeyFile] <string> [<CommonParameters>]

  • Import-StrongNameKeyPair [-KeyFile] <string> -Password <securestring> [<CommonParameters>]

    Imports a simple unprotected SNK or a password-protected PFX, returning a StrongNameKeyPair instance for consumption by Set-StrongName. If your PFX file has a blank password, you must provide a SecureString of the empty string "". SecureString instances are returned from the Read-Host cmdlet with the -AsSecureString parameter.

  • Set-StrongName [-AssemblyFile] <string[]> -KeyPair <StrongNameKeyPair> [-NoBackup] [-Passthru] [-Force] [-DelaySign] [-WhatIf] [-Confirm] [<CommonParameters>]

    Assigns a strong name identity to an assembly.

    The -KeyPair parameter accepts a System.Reflection.StrongNameKeyPair output from the Import-StrongNameKeyPair cmdlet., which accepts either simple unprotected SNK files or password-protected PFX files.

    The -NoBackup switch directs the cmdlet to skip creating a .bak file alongside the newly signed assembly.

    The -Passthru switch will output a FileInfo representing the newly signed assembly to the pipeline.

    The -DelaySign switch will create a delay-signed assembly from a public key only SNK (it can also create one if the SNK contains both private and public keys.) This is useful if you can't get access to the full private key at your company. This will allow you to compile against previously unsigned nuget packages at least.

    The -Force switch will allow you to overwrite an existing strong name on an assembly.

    NOTE: You may supply -WhatIf to see what would be done, without actually doing it.

  • Get-AssemblyName [-AssemblyFile] <string[]> [<CommonParameters>]

    Returns a System.Reflection.AssemblyName instance from any assembly file.

FAQ: How Do I?

Get the default package root folder

PM> $root = join-path (split-path $dte.solution.filename) packages

Load an unprotected snk

PM> $key = Import-StrongNameKeyPair -KeyFile .\folder\key.snk
PM> dir *.dll | Set-StrongName -KeyPair $key -Verbose

Load a password-protected PFX

PM> $key = Import-StrongNameKeyPair -KeyFile .\folder\key.pfx -Password (Read-Host -AsSecureString)
******

Sign some unsigned assemblies

PM> cd (join-path $root unsignedPackage)
PM> dir -rec *.dll | set-strongname -keypair $key -verbose

(Re)sign some assemblies forcefully

PM> dir -rec *.dll | set-strongname -keypair $key -force

Sign only unsigned assemblies

PM> dir -rec *.dll | where { -not (test-strongname $_) } | set-strongname -keypair $key -verbose

PowerShell– A Peek at the Poke Module

I wrote this a good long time ago now, but somehow I never bothered to blog it. I guess I thought it was a bit too specific to be of general interest to people, but my good friend and long time MVP Karl Prosser tells me otherwise. This is the Wiki page from bitbucket repository, the link for which you'll find at the foot of the page. Basically, it's a module that lets you "peek" at objects to view and manipulate their internals. That is to say, you can access non-public methods, fields and properties just like they were public. You can also create instances of non-public types easily. I originally wrote this to help me when debugging things and to explore PowerShell itself from the inside out, interactively. It turns out to be a pretty powerful tool. I hope you enjoy it.


Here you'll find examples of how to peek and poke objects using the Poke module.

Version History

  • 1.0.1 - Compatibility fixes for v3 beta / .net 4.5
  • 1.0 - Initial release
Examples
# peek at a Job instance using pipeline syntax
$job = start-job { 42 } | peek
$job | get-member

which results in the new extended output format for get-member:

   TypeName:
Pokeable.System.Management.Automation.PSRemotingJob#676f9716-c167-47c6-ab0d-4d8cedbbe44d

Name                            Modifier  MemberType Definition
----                            --------  ---------- ----------
Equals                          public    Method     bool Equals(System.Object obj)
GetHashCode                     public    Method     int GetHashCode()
GetType                         public    Method     type GetType()
CheckDisconnectedAndUpdateState private   Method*    void CheckDisconnectedAndUpdateState(System....
CommonInit                      private   Method*    void CommonInit(int throttleLimit, System.Co...
ConnectJob                      internal  Method*    void ConnectJob(guid runspaceInstanceId)
ConnectJobs                     internal  Method*    void ConnectJobs()
ConstructLocation               private   Method*    string ConstructLocation()
Dispose                         protected Method*    void Dispose(bool disposing)
FindDisconnectedChildJob        private   Method*    System.Management.Automation.PSRemotingChild...
GetAssociatedPowerShellObject   internal  Method*    powershell GetAssociatedPowerShellObject(gui...
GetJobsForComputer              internal  Method*    System.Collections.Generic.List[System.Manag...
GetJobsForOperation             internal  Method*    System.Collections.Generic.List[System.Manag...
GetJobsForRunspace              internal  Method*    System.Collections.Generic.List[System.Manag...
GetRunspaces                    internal  Method*    System.Collections.Generic.IEnumerable`1[[Sy...
HandleChildJobStateChanged      private   Method*    void HandleChildJobStateChanged(System.Objec...
HandleJobUnblocked              private   Method*    void HandleJobUnblocked(System.Object sender...
InternalStopJob                 internal  Method*    void InternalStopJob()
SetStatusMessage                private   Method*    void SetStatusMessage()
StopJob                         public    Method*    void StopJob()
SubmitAndWaitForConnect         private   Method*    void SubmitAndWaitForConnect(System.Collecti...
ToString                        public    Method*    string ToString()
__GetBaseObject                 -         Method*    System.Management.Automation.PSRemotingJob, ...
__GetModuleInfo                 -         Method*    psmoduleinfo __GetModuleInfo()
atleastOneChildJobFailed        private   Field*     bool atleastOneChildJobFailed
blockedChildJobsCount           private   Field*     int blockedChildJobsCount
CanDisconnect                   internal  Property*  bool CanDisconnect { get; set; }
disconnectedChildJobsCount      private   Field*     int disconnectedChildJobsCount
finishedChildJobsCount          private   Field*     int finishedChildJobsCount
HasMoreData                     public    Property*  bool HasMoreData { get; set; }
HideComputerName                internal  Property*  bool HideComputerName { get; set; }
isDisposed                      private   Field*     bool isDisposed
Location                        public    Property*  string Location { get; set; }
moreData                        private   Field*     bool moreData
StatusMessage                   public    Property*  string StatusMessage { get; set; }
throttleManager                 private   Field*     System.Management.Automation.Remoting.Thrott...
_stopIsCalled                   private   Field*     bool _stopIsCalled
_syncObject                     private   Field*     System.Object _syncObject

You can call methods, set fields and properties (if they have setters - it doesn't matter if they're private, protected or internal.)

You can proxy/peek Types as well as instances:

# proxy a public type by piping it
$type = [text.stringbuilder] | peek
   TypeName: Pokeable.System.RuntimeType#System.Text.StringBuilder

Name             Modifier MemberType Definition
----             -------- ---------- ----------
Equals           public   Method     bool Equals(System.Object obj)
GetHashCode      public   Method     int GetHashCode()
GetType          public   Method     type GetType()
FormatError      private  Method*    static void FormatError()
ThreadSafeCopy   private  Method*    static void ThreadSafeCopy(System.Char*, mscorlib, Version=4...
ToString         public   Method*    string ToString()
__CreateInstance -        Method*    .ctor (), .ctor (int capacity), .ctor (string value), .ctor ...
__GetBaseObject  -        Method*    type __GetBaseObject()
__GetModuleInfo  -        Method*    psmoduleinfo __GetModuleInfo()
CapacityField    private  Field*     string CapacityField
DefaultCapacity  internal Field*     int DefaultCapacity
MaxCapacityField private  Field*     string MaxCapacityField
MaxChunkSize     internal Field*     int MaxChunkSize
StringValueField private  Field*     string StringValueField
ThreadIDField    private  Field*     string ThreadIDField

Peeking at non-public types:

# nonpublic types can't be specified using type literal
# syntax, so in this case you should use the -name parameter
$type = peek -name MS.Internal.Xml.XPath.XPathParser

# nonpublic objects returned from methods, properties or fields
# are not "peeked" themselves, so you may need to peek the return value:
$manager = peek (start-job { 42 } | peek).throttlemanager
$manager.throttlelimit = 64 # bump throttle limit ;)

Of course, you can peek instances too:

$sb = new-object system.text.stringbuilder
$proxy = peek $sb
$proxy | gm
   TypeName: Pokeable.System.Text.StringBuilder#45f12364-1906-45b3-b48b-a77acd81e3f0

Name                                                     Modifier MemberType Definition
----                                                     -------- ---------- ----------
GetHashCode                                              public   Method     int GetHashCode()
GetType                                                  public   Method     type GetType()
Append                                                   public   Method*    System.Text.StringBu...
AppendFormat                                             public   Method*    System.Text.StringBu...
AppendHelper                                             private  Method*    void AppendHelper(st...
AppendLine                                               public   Method*    System.Text.StringBu...
Clear                                                    public   Method*    System.Text.StringBu...
CopyTo                                                   public   Method*    void CopyTo(int sour...
EnsureCapacity                                           public   Method*    int EnsureCapacity(i...
Equals                                                   public   Method*    bool Equals(System.T...
ExpandByABlock                                           private  Method*    void ExpandByABlock(...
FindChunkForByte                                         private  Method*    System.Text.StringBu...
FindChunkForIndex                                        private  Method*    System.Text.StringBu...
Insert                                                   public   Method*    System.Text.StringBu...
InternalCopy                                             internal Method*    void InternalCopy(Sy...
MakeRoom                                                 private  Method*    void MakeRoom(int in...
Next                                                     private  Method*    System.Text.StringBu...
Remove                                                   private  Method*    System.Text.StringBu...
Replace                                                  public   Method*    System.Text.StringBu...
ReplaceAllInChunk                                        private  Method*    void ReplaceAllInChu...
ReplaceBufferAnsiInternal                                internal Method*    void ReplaceBufferAn...
ReplaceBufferInternal                                    internal Method*    void ReplaceBufferIn...
ReplaceInPlaceAtChunk                                    private  Method*    void ReplaceInPlaceA...
StartsWith                                               private  Method*    bool StartsWith(Syst...
System.Runtime.Serialization.ISerializable.GetObjectData private  Method*    void System.Runtime....
ToString                                                 public   Method*    string ToString()
VerifyClassInvariant                                     private  Method*    void VerifyClassInva...
__GetBaseObject                                          -        Method*    System.Text.StringBu...
__GetModuleInfo                                          -        Method*    psmoduleinfo __GetMo...
Capacity                                                 public   Property*  int Capacity { get; ...
Chars                                                    public   Property*  char Chars { get; se...
Length                                                   public   Property*  int Length { get; se...
MaxCapacity                                              public   Property*  int MaxCapacity { ge...
m_ChunkChars                                             internal Field*     char[] m_ChunkChars
m_ChunkLength                                            internal Field*     int m_ChunkLength
m_ChunkOffset                                            internal Field*     int m_ChunkOffset
m_ChunkPrevious                                          internal Field*     System.Text.StringBu...
m_MaxCapacity                                            internal Field*     int m_MaxCapacity

Have fun!

View or download the Poke module from bitbucket.

The Bourne Again PowerShell (BAPS) AWKWARD Module

Update 2013/4/3: This is an April Fools post. I think I got a bit too subtle here despite best efforts to make this kind of ridiculous. Apparently being tagged “OMGPONIES” is not enough to give it away. Yes, the script actually works, but it’s more of a roundabout way to compare the “awkward” AWK syntax with the more readable, idiomatic PowerShell. Thanks for reading.

Sometimes PowerShell’s object pipeline just gets in the way. Often I find myself needing to pipe a few commands together and while I lay it out in my head, I am already unconsciously preparing the regular expressions I’ll need to convert the text to a structure required by the receiving command. Other times I am idly flicking through a well-thumbed and worn binder of common commands and their output on sheets of grid paper so I can figure out what columns I need to munge. Muscle memory is a hard beast to tame, so with that in mind, I started out designing a module that would let me scratch that regex itch, and also keep things kind of “PowerShelly.” It then dawned on me that I could probably extend this further into a full POSIX* compatibility layer, with the codename for this being WARD (Windows Adaptable Reusable Development). My first implementation for AWK/WARD looked a little like this:

function awk {
    $input
}

While that implementation works well for a surprising number of cases, there are others which are a little trickier, so I figured I'd add a little intelligence to the commands for some of the more common use cases for AWK. Some examples:

# count lines in a file
cat text.txt | awk 'END{print NR}'

# Add all fields in ALL lines and print the sum
#
# sheet is:
#
#    a, b, c, d
#    1, 2, 3, 4
#    1, 2, 3, 4
#    1, 2, 3, 4
cat sheet.txt | awk '{s=0; for (i=1; i<=NF; i++) s=s+$i; print s}'

# Print 25 "A" characters
awk 'BEGIN{while (a++<25) s=s "A"; print s}'

Here's the current source of the AWKWARD BAPS module:

function awk ($expression) {
    
    switch ($expression) {
        
        # count lines
        'END{print NR}' {
            $input | measure
        }

        # print the total number of fields ("words") in all lines
        '{ total = total + NF }; END {print total}' {
            $input | measure -word
        }

        # print the sums of the fields of every line
        '{s=0; for (i=1; i<=NF; i++) s=s+$i; print s}' {
            $input | convertfrom-csv | measure -sum * | select property, sum
        }

         # add all fields in ALL lines and print the sum
        '{for (i=1; i<=NF; i++) s=s+$i}; END{print s}' {
            $input | convertfrom-csv | measure -sum * | measure -sum sum
        }

         # create a string of a specific length (e.g., generate N spaces)
        ([regex]'BEGIN{while \(a\+\+<(\d+)\) s=s "(.+?)"; print s}') {
            $matches[2] * $matches[1]
        }
        
        # print first N lines of file (emulates behavior of "head")
        ([regex]'NR < (\d+)') {
            $input | select -first $matches[1]
        }

        # print the last 2 lines of a file
        '{y=x "\n" $0; x=$0};END{print y}' {
            $input | select -last 2    
        }

         # print the last line of a file
        'END{print}' {
            $input | select -last 1
        }

        # print the last N lines of a file (circular buffer)
        ([regex]'{a\[NR%(\d+)\]=\$0}END{for(i=NR+1;i<=NR+(?:\d+);i++)print a\[i%(?:\d+)\]}') {
            $input | select -last $matches[1]
        }

        # emit matching lines for regex
        { $_ -as [regex] } {
            $input | where { ($expression -as [regex]).ismatch($_) }
        }
        
        default {
            write-warning "unsupported expression"
            $input
        }
    }
}
}

If you want to play around with the module, you can autoinstall it by running the following one-liner:

iex (New-Object Net.WebClient).DownloadString(“http://bit.ly/e0Mw9w”)

Have fun!

About the author

Irish, PowerShell MVP, .NET/ASP.NET/SharePoint Developer, Budding Architect. Developer. Montrealer. Opinionated. Montreal, Quebec.

Month List

Page List