CSharp/CSharp.psm1

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
# Copyright 2019 Ryan James Decker

function Invoke-CSharpCompiler{

    <#

    #>


    [CmdletBinding(
        DefaultParameterSetName="Default"
    )]

    Param(
        
        [Parameter(
            ParameterSetName="CscLocations"
        )]
        [switch]$ListCscLocations,

        [Parameter(
            Mandatory=$true,
            ParameterSetName="Default"
        )]
        [Alias(
            "CSC"
        )]
        $CscLocation,
        
        [Parameter(
            Mandatory=$true,
            HelpMessage="Enter a filepath for the compiled output.",
            ParameterSetName="Default"
        )]
        [Alias("out")]
        $Path,

        [Parameter(
            ParameterSetName="Default"
        )]
        [ValidateSet(
            "ConsoleExecutable","exe",
            "WindowsExe","winexe",
            "library",
            "Module",
            "AppContainerExecutable","appcontainerexe",
            "winmdobj"
        )]
        [Alias("t")]
        $Target,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("doc")]
        $XmlDocument,
        
        [Parameter(
            ParameterSetName="Default"
        )]
        [ValidateSet(
            "x86",
            "Itanium",
            "x64",
            "arm",
            "anycpu32bitpreferred",
            "anycpu"
        )]
        $Platform,
        
        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("recurse")]
        $RecursiveSourcecodeSearchPattern,
        
        [Parameter(
            ParameterSetName="Default"
        )]
        $ReferenceAlias,
        
        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("r")]
        $Reference,
        
        [Parameter(
            ParameterSetName="Default"
        )]
        $AddModule,
        
        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("l")]
        $Link,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("win32res")]
        $Win32ResourceFile,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("Icon")]
        $Win32Icon,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("win32manifest")]
        $Win32ManifestFile,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("nowin32manifest")]
        [switch]
        $NoWin32ManifestFile,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("res")]
        $Resource,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("linkres")]
        $LinkResource,

        # ----------- CONTINUE HERE ---------------

        <#
        [Parameter(
            ParameterSetName="Default"
        )]
        [ValidateSet(
            "+",
            "-",
            "Full",
            "pdbonly"
        )]
        $Debug,

        [Parameter(
            ParameterSetName="Default"
        )]
        [ValidateSet(
            "+",
            "-"
        )]
        [Alias("o")]
        $Optimize,

        [Parameter(
            ParameterSetName="Default"
        )]
        $WarnAsError,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("w")]
        [ValidateSet(0,1,2,3,4)]
        [uint16]$Warn,

        [Parameter(
            ParameterSetName="Default"
        )]
        $NoWarn,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $Checked,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $Unsafe,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $Define,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("langversion")]
        $LanguageVersion,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $DelaySign,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $KeyFile,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $KeyContainer,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("highentropyva")]
        $HighEntropyValue,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $EnforceCodeIntegrity,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $ResponseFile,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("h")]
        $Help,
        #>


        [Parameter(
            ParameterSetName="Default"
        )]
        [switch]$NoLogo,

        <#
        [Parameter(
            ParameterSetName="Default"
        )]
        $NoConfig,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $BaseAddress,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $BugReport,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $CodePage,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $Utf8Output,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("m")]
        $Main,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $FullPaths,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $FileAlign,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $Pdb,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $ErrorEndLocation,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("preferreduilang")]
        $PreferredUiLanguage,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("nostdlib")]
        $NoStandardLibrary,

        [Parameter(
            ParameterSetName="Default"
        )]
        $SubsystemVersion,

        [Parameter(
            ParameterSetName="Default"
        )]
        $Lib,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $ErrorReport,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $AppConfig,

        [Parameter(
            ParameterSetName="Default"
        )]
        [Alias("")]
        $ModuleAssemblyName

        #>


        [switch]$Force
    )

    Begin{

        $_nl = [System.Environment]::NewLine

        if ($ListCscLocations.IsPresent){
            
            Write-Host "Searching for CSC.exe..."
            
            $_cscLocations = Get-ChildItem `
                -Path 'C:\' `
                -Recurse `
                -Filter "*csc.exe" `
                -ErrorAction SilentlyContinue | 
                    Sort-Object FullName | 
                        ? {$_ -notmatch '\.old'}
                    
            $_scriptShouldStopNow = $true
            
            return $_cscLocations.FullName
            
        }

        $_outFileExists = Test-Path -Path $Path

        if ($_outFileExists) {
            
            if ($Force.IsPresent) {
                
                $_message = "`"$Path`" will be overwritten."

                Write-Warning $_message

            } else {

                $_message = 
                    "File already exists: `"$Path`"" + $_nl + 
                    "Use -Force parameter to overwrite."
            
                Write-Error $_message

                $_scriptShouldStopNow = $true

                return

            }
        }
        
        $_csc = "$CscLocation"

        $Path = "/out:`"$Path`""
        
        if ($Target) {

            $_targetParameter = "/target:"

            switch ($Target) {

                "ConsoleApplication" {
                    $_targetArgument="exe"
                    break
                }

                "WindowsExe" {
                    $_targetArgument="winexe"
                    break
                }

                "AppContainerExecutable" {
                    $_targetArgument="appcontainerexe"
                    break
                }

                default {
                    $_targetArgument = "$Target"
                    break
                }

            }

            $_target = '"' + $_targetParameter + $_targetArgument + '"'
        }

        if ($XmlDocument) {$XmlDocument = "/doc:$XmlDocument"}
        
        if ($Platform) {$Platform = "/platform:$Platform"}
        
        if ($RecursiveSourcecodeSearchPattern) {

            $RecursiveSourcecodeSearchPattern = "/recurse:`"$RecursiveSourcecodeSearchPattern`""

        }
        
        if ($ReferenceAlias) {
            
            if ($ReferenceAlias -match ".\=.") {

                $ReferenceAlias = "/reference:$ReferenceAlias"

            } else {
                
                $_message = 
                    "Invalid use of -ReferenceAlias. Type in an alias in " + 
                    "this pattern: ALIAS=FILE"

                Write-Error $_message

                $_scriptShouldStopNow = $true

                return $null

            }

        }

        if ($Reference) {$Reference = "/reference:`"$Reference`""}

        if ($AddModule) {$AddModule = "/addmodule:$AddModule"}

        if ($Link) {$Link = "/link:$Link"}

        if ($Win32ResourceFile) {$Win32ResourceFile = "/win32res:$win32ResourceFile"}

        if ($Win32Icon) {$Win32Icon = "/win32icon:$Win32Icon"}

        if ($Win32ManifestFile) {$Win32ManifestFile = "/win32manifest:$Win32ManifestFile"}

        if ($NoWin32ManifestFile.IsPresent) {$_noWin32ManifestFile = "/nowin32manifest"}

        if ($Resource) {$Resource = "/resource:$Resource"}

        if ($LinkResource) {$LinkResource = "/linkres:$LinkResource"}

        # GAP

        if ($NoLogo.IsPresent) {$_noLogo = "/nologo"}
    }

    Process{
        
        if ($_scriptShouldStopNow) {return}

        $_message = 
            "Using Command $_csc $Path $_target $XmlDocument $Platform " + 
            "$RecursiveSourcecodeSearchPattern $ReferenceAlias $Reference " + 
            "$AddModule $Link $Win32ResourceFile $Win32Icon " + 
            "$Win32ManifestFile $_noWin32ManifestFile $Resource " + 
            "$LinkResource $_noLogo" -replace '\s+',' '

        Write-Verbose $_message
        
        & $_csc `
            $Path `
            $_target `
            $XmlDocument `
            $Platform `
            $RecursiveSourcecodeSearchPattern `
            $ReferenceAlias `
            $Reference `
            $AddModule `
            $Link `
            $Win32ResourceFile `
            $Win32Icon `
            $Win32ManifestFile `
            $_noWin32ManifestFile `
            $Resource `
            $LinkResource `
            $_noLogo

    }

    End{}

}