Can I write a class using powershell?

后端 未结 3 1027
北恋
北恋 2020-12-13 00:01

I\'m still learning powershell, and so far I haven\'t found an answer on this website, despite a few searches. With Powershell being built on top of the .NET framework, can

相关标签:
3条回答
  • 2020-12-13 00:27

    I suspect that the solution that you are looking for is Powershell Modules. They perform the roles that classes typically perform in other languages. They give you a very simple yet structured way to reuse your code.

    Here is how to get the functionality of classes in PS using modules. At the command line you could do this:

    New-Module -ScriptBlock {function add($a,$b){return $a + $b}; function multiply($a,$b){return $a * $b}; function supersecret($a,$b){return multiply $a $b}; export-modulemember -function add, supersecret}
    

    Then you would be able to:

    PS C:\> add 2 4
    6
    PS C:\> multiply 2 4
    The term 'multiply' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was inc
    luded, verify that the path is correct and try again.
    At line:1 char:9
    + multiply <<<<  2 4
        + CategoryInfo          : ObjectNotFound: (multiply:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException
    
    PS C:\> supersecret 2 4
    8
    

    As you can see multiply is private within the module. More traditionally you would inatantiate an object that is an instance of the module. That is done via the -AsCustomObject parameter:

    $m = New-Module -ScriptBlock {function add($a,$b){return $a + $b}; function multiply($a,$b){return $a * $b}; function supersecret($a,$b){return multiply $a $b}; export-modulemember -function add, supersecret} -AsCustomObject
    

    Then you could:

    PS C:\> $m.add(2,4)
    6
    PS C:\> $m.multiply(2,4)
    Method invocation failed because [System.Management.Automation.PSCustomObject] doesn't contain a method named 'multiply'.
    At line:1 char:12
    + $m.multiply <<<< (2,4)
        + CategoryInfo          : InvalidOperation: (multiply:String) [], RuntimeException
        + FullyQualifiedErrorId : MethodNotFound
    
    PS C:\> $m.supersecret(2,4)
    
    8
    

    This all demonstrates the use of Dynamic modules meaning nothing is stored to disk for reuse. It is fine for very simple functionality. If you want to actually be able to read the code and reuse it in future sessions or scripts however you would want to store it in a .psm1 file then store that file in a folder with the same name (minus the extension) as the file. Then you can import the module into your session at the command line or into another script.

    As an example of this, let's say I took this code:

    function Add{
        param(
                $a,
                $b
             )
        return $a + $b
    }
    function Multiply{
        param(
                $a,
                $b
             )
        return $a + $b
    }
    function SuperSecret{
        param(
                $a,
                $b
             )
        return Multiply $a $b
    }
    Export-ModuleMember -Function Add, SuperSecret
    

    And saved it to a file called TestModule.psm1 in the folder: C:\Windows\System32\WindowsPowerShell\v1.0\Modules\TestModule

    The Modules folder in the Powershell install folder is a magic folder and any modules stored there are visible to the Import-Module cmdlet without having to specify a path. Now if we run Get-Module -List at the command line we see:

    ModuleType Name                      ExportedCommands
    ---------- ----                      ----------------
    Script     DotNet                    {}
    Manifest   FileSystem                {Get-FreeDiskSpace, New-Zip, Resolve-ShortcutFile, Mount-SpecialFolder...}
    Manifest   IsePack                   {Push-CurrentFileLocation, Select-CurrentTextAsVariable, ConvertTo-Short...
    Manifest   PowerShellPack            {New-ByteAnimationUsingKeyFrames, New-TiffBitmapEncoder, New-Viewbox, Ne...
    Manifest   PSCodeGen                 {New-Enum, New-ScriptCmdlet, New-PInvoke}
    Manifest   PSImageTools              {Add-CropFilter, Add-RotateFlipFilter, Add-OverlayFilter, Set-ImageFilte...
    Manifest   PSRss                     {Read-Article, New-Feed, Remove-Article, Remove-Feed...}
    Manifest   PSSystemTools             {Test-32Bit, Get-USB, Get-OSVersion, Get-MultiTouchMaximum...}
    Manifest   PSUserTools               {Start-ProcessAsAdministrator, Get-CurrentUser, Test-IsAdministrator, Ge...
    Manifest   TaskScheduler             {Remove-Task, Get-ScheduledTask, Stop-Task, Add-TaskTrigger...}
    Manifest   WPK                       {Get-DependencyProperty, New-ModelVisual3D, New-DiscreteVector3DKeyFrame...
    Manifest   AppLocker                 {}
    Manifest   BitsTransfer              {}
    Manifest   PSDiagnostics             {}
    Script     **TestModule**                {}
    Manifest   TroubleshootingPack       {}
    Manifest   Citrix.XenApp.Commands... {}
    

    We can see that our module is ready to import. We can import it into the session and use it in the raw using:

    Import-Module TestModule
    

    Or once again we can instantiate an object:

    $m = Import-Module TestModule -AsCustomObject
    
    0 讨论(0)
  • 2020-12-13 00:36

    You can use the class keyword that was introduced in PowerShell 5.0

    Here is an example by Trevor Sullivan. (Archived here.)

    ##################################################
    ####### WMF 5.0 November 2014 Preview ###########
    ##################################################
    class Beer {
        # Property: Holds the current size of the beer.
        [Uint32] $Size;
        # Property: Holds the name of the beer's owner.
        [String] $Name;
    
        # Constructor: Creates a new Beer object, with the specified
        #              size and name / owner.
        Beer([UInt32] $NewSize, [String] $NewName) {
            # Set the Beer size
            $this.Size = $NewSize;
            # Set the Beer name
            $this.Name = $NewName;
        }
    
        # Method: Drink the specified amount of beer.
        # Parameter: $Amount = The amount of beer to drink, as an 
        #            unsigned 32-bit integer.
        [void] Drink([UInt32] $Amount) {
            try {
                $this.Size = $this.Size - $Amount;
            }
            catch {
                Write-Warning -Message 'You tried to drink more beer than was available!';
            }
        }
    
        # Method: BreakGlass resets the beer size to 0.
        [void] BreakGlass() {
            Write-Warning -Message 'The beer glass has been broken. Resetting size to 0.';
            $this.Size = 0;
        }
    }
    

    This works on Windows 10 Pro.

    Test drive it like this:

    # Create a new 33 centilitre beer, named 'Chimay'
    $chimay = [Beer]::new(33, 'Chimay');
    
    $chimay.Drink(10)
    $chimay.Drink(10)
    
    # Need more beer!
    $chimay.Drink(200)
    
    $chimay.BreakGlass()
    
    0 讨论(0)
  • 2020-12-13 00:44

    Take a look at Add-Type cmdlet. It lets you write C# and other code in PowerShell. For example (from the above link),

    C:\PS>$source = @"
    public class BasicTest
    {
        public static int Add(int a, int b)
        {
            return (a + b);
        }
    
        public int Multiply(int a, int b)
        {
            return (a * b);
        }
    }
    "@
    
    C:\PS> Add-Type -TypeDefinition $source
    
    C:\PS> [BasicTest]::Add(4, 3)
    
    C:\PS> $basicTestObject = New-Object BasicTest 
    C:\PS> $basicTestObject.Multiply(5, 2)
    
    0 讨论(0)
提交回复
热议问题