github.com/observiq/carbon@v0.9.11-0.20200820160507-1b872e368a5e/scripts/windows-install.ps1 (about)

     1  new-module -name LogAgentInstall -scriptblock {
     2  
     3    # Constants
     4    $DEFAULT_WINDOW_TITLE = $host.ui.rawui.WindowTitle
     5    $DEFAULT_INSTALL_PATH = 'C:\'
     6    $DOWNLOAD_BASE = "https://github.com/observiq/carbon/releases"
     7    $SERVICE_NAME = 'carbon'
     8    $INDENT_WIDTH = '  '
     9    $MIN_DOT_NET_VERSION = '4.5'
    10  
    11    # Functions
    12    function Set-Variables {
    13      if ($host.name -NotMatch "ISE") {
    14        $IS_PS_ISE = $false
    15        $script:DEFAULT_FG_COLOR = $host.ui.rawui.ForegroundColor
    16        $script:DEFAULT_BG_COLOR = $host.ui.rawui.BackgroundColor
    17      }
    18      else {
    19        $script:IS_PS_ISE = $true
    20        $script:DEFAULT_FG_COLOR = [System.ConsoleColor]::White
    21        $script:DEFAULT_BG_COLOR = $psIse.Options.ConsolePaneBackgroundColor
    22      }
    23    }
    24  
    25    function Add-Indent {
    26      $script:indent = "${script:indent}$INDENT_WIDTH"
    27    }
    28  
    29    function Remove-Indent {
    30      $script:indent = $script:indent -replace "^$INDENT_WIDTH", ''
    31    }
    32  
    33    # Takes a variable amount of alternating strings and their colors.
    34    # An empty-string color uses the default text color.
    35    # The last given string does not require a color (uses default)
    36    # e.g.: string1 color1 string2 color2 string3
    37    function Show-ColorText {
    38      Write-Host "$indent" -NoNewline
    39      for ($i = 0; $i -lt $args.count; $i++) {
    40        $message = $args[$i]
    41        $i++
    42        $color = $args[$i]
    43        if (!$color) {
    44          $color = $script:DEFAULT_FG_COLOR
    45        }
    46        Write-Host "$message" -ForegroundColor "$color" -NoNewline
    47      }
    48      Write-Host ""
    49    }
    50  
    51    function Show-Separator {
    52      Show-ColorText "============================================" $args
    53    }
    54  
    55    function Show-Header {
    56      $message, $color = $args
    57      Show-ColorText ""
    58      Show-Separator
    59      Show-ColorText '| ' '' "$message" $color
    60      Show-Separator
    61    }
    62  
    63    function Set-Window-Title {
    64      $host.ui.rawui.windowtitle = "Carbon Install"
    65    }
    66  
    67    function Restore-Window-Title {
    68      $host.ui.rawui.windowtitle = $DEFAULT_WINDOW_TITLE
    69    }
    70  
    71    function Complete {
    72      Show-ColorText "Complete" DarkGray
    73    }
    74  
    75    function Succeeded {
    76      Add-Indent
    77      Show-ColorText "Succeeded!" Green
    78      Remove-Indent
    79    }
    80  
    81    function Failed {
    82      Add-Indent
    83      Show-ColorText "Failed!" Red
    84      Remove-Indent
    85    }
    86  
    87    function Show-Usage {
    88      Add-Indent
    89      Show-ColorText 'Options:'
    90      Add-Indent
    91  
    92      Show-ColorText ''
    93      Show-ColorText '-y, --accept_defaults'
    94      Add-Indent
    95      Show-ColorText 'Accepts all default values for installation.' DarkCyan
    96      Remove-Indent
    97  
    98      Show-ColorText ''
    99      Show-ColorText '-v, --version'
   100      Add-Indent
   101      Show-ColorText 'Defines the version of the agent.' DarkCyan
   102      Show-ColorText 'If not provided, this will default to the latest version.' DarkCyan
   103      Remove-Indent
   104  
   105      Show-ColorText ''
   106      Show-ColorText '-i, --install_dir'
   107      Add-Indent
   108      Show-ColorText 'Defines the install directory of the agent.' DarkCyan
   109      Show-ColorText 'If not provided, this will default to C:/observiq.' DarkCyan
   110      Remove-Indent
   111  
   112      Show-ColorText ''
   113      Show-ColorText '-u, --service_user'
   114      Add-Indent
   115      Show-ColorText 'Defines the service user that will run the agent.' DarkCyan
   116      Show-ColorText 'If not provided, this will default to the current user.' DarkCyan
   117      Remove-Indent
   118  
   119      Remove-Indent
   120      Remove-Indent
   121    }
   122  
   123    function Exit-Error {
   124      if ($indent) { Add-Indent }
   125      $line_number = $args[0]
   126      $message = ""
   127      if ($args[1]) { $message += "`n${indent}- [Issue]: $($args[1])" }
   128      if ($args[2]) { $message += "`n${indent}- [Resolution]: $($args[2])" }
   129      if ($args[3]) { $message += "`n${indent}- [Help Link]: $($args[3])" }
   130      if ($args[4]) {
   131        $message += "`n${indent}- [Rerun]: $($args[4])"
   132      }
   133      elseif ($script:rerun_command) {
   134        $message += "`n${indent}- [Rerun]: $script:rerun_command"
   135      }
   136      throw "Error (windows_install.ps1:${line_number}): $message"
   137      if ($indent) { Remove-Indent }
   138    }
   139  
   140    function Get-AbsolutePath ($path) {
   141      $path = [System.IO.Path]::Combine(((Get-Location).Path), ($path))
   142      $path = [System.IO.Path]::GetFullPath($path)
   143      return $path;
   144    }
   145  
   146    function Request-Confirmation ($default = "y") {
   147      if ($default -eq "n") {
   148        Write-Host -NoNewline "y/"
   149        Write-Host -NoNewline -ForegroundColor Red "[n]: "
   150      }
   151      else {
   152        Write-Host -NoNewline -ForegroundColor Green "[y]"
   153        Write-Host -NoNewline "/n: "
   154      }
   155    }
   156  
   157    # This will check for all required conditions
   158    # before executing an installation.
   159    function Test-Prerequisites {
   160      Show-Header "Checking Prerequisites"
   161      Add-Indent
   162      Test-PowerShell
   163      Test-Architecture
   164      Test-DotNet
   165      Complete
   166      Remove-Indent
   167    }
   168  
   169    # This will ensure that the script is executed
   170    # in the correct version of PowerShell.
   171    function Test-PowerShell {
   172      Show-ColorText  "Checking PowerShell... "
   173      if (!$ENV:OS) {
   174        Failed
   175        Exit-Error $MyInvocation.ScriptLineNumber 'Install script was not executed in PowerShell.'
   176      }
   177  
   178      $script:PSVersion = $PSVersionTable.PSVersion.Major
   179      if ($script:PSVersion -lt 3) {
   180        Failed
   181        Exit-Error $MyInvocation.ScriptLineNumber 'Your PowerShell version is not supported.' 'Please update to PowerShell 3+.'
   182      }
   183      Succeeded
   184    }
   185  
   186  
   187    # This will ensure that the CPU Architecture is supported.
   188    function Test-Architecture {
   189      Show-ColorText 'Checking CPU Architecture... '
   190      if ([System.IntPtr]::Size -eq 4) {
   191        Failed
   192        Exit-Error $MyInvocation.ScriptLineNumber '32-bit Operating Systems are currently not supported.'
   193      }
   194      else {
   195        Succeeded
   196      }
   197    }
   198  
   199    # This will ensure that the version of .NET is supported.
   200    function Test-DotNet {
   201      Show-ColorText 'Checking .NET Framework Version...'
   202      if ([System.Version](Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -recurse | Get-ItemProperty -name Version, Release -EA 0 | Where-Object { $_.PSChildName -match '^(?!S)\p{L}' } | Sort-Object -Property Version -Descending | Select-Object Version -First 1).version -ge [System.Version]"$MIN_DOT_NET_VERSION") {
   203        Succeeded
   204      }
   205      else {
   206        Failed
   207        Exit-Error $MyInvocation.ScriptLineNumber ".NET Framework $MIN_DOT_NET_VERSION is required." "Install .NET Framework $MIN_DOT_NET_VERSION or later"
   208      }
   209    }
   210  
   211    # This will set the values of all installation variables.
   212    function Set-InstallVariables {
   213      Show-Header "Configuring Installation Variables"
   214      Add-Indent
   215      Set-Defaults
   216      Set-DownloadURLs
   217      Set-InstallDir
   218      Set-HomeDir
   219      Set-PluginDir
   220      Set-BinaryLocation
   221      Set-ServiceUser
   222  
   223      Complete
   224      Remove-Indent
   225    }
   226  
   227    # This will prompt a user to use default values. If yes, this
   228    # will set the install_dir, agent_name, and service_user to their
   229    # default values.
   230    function Set-Defaults {
   231      If ( !$script:accept_defaults ) {
   232        Write-Host -NoNewline "${indent}Accept installation default values? "
   233        Request-Confirmation
   234        $script:accept_defaults = Read-Host
   235      }
   236      Else {
   237        $accepted_defaults_via_args = "true"
   238      }
   239  
   240      Switch ( $script:accept_defaults.ToLower()) {
   241        { ($_ -in "n", "no") } {
   242          return
   243        }
   244        default {
   245          If (!$accepted_defaults_via_args) { Write-Host -NoNewline "${indent}" }
   246          Show-ColorText "Using default installation values" Green
   247          If (!$script:install_dir) {
   248            $script:install_dir = $DEFAULT_INSTALL_PATH
   249          }
   250          If (!$script:service_user) {
   251            $script:service_user = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
   252          }
   253        }
   254      }
   255    }
   256  
   257    # This will set the install path of the agent. If not provided as a flag,
   258    # the user will be prompted for this information.
   259    function Set-InstallDir {
   260      Show-ColorText 'Setting install directory...'
   261      Add-Indent
   262      If ( !$script:install_dir ) {
   263        Write-Host -NoNewline "${indent}Install path   ["
   264        Write-Host -NoNewline -ForegroundColor Cyan "$DEFAULT_INSTALL_PATH"
   265        Write-Host -NoNewline ']: '
   266        $script:install_dir = Read-Host
   267        If ( !$script:install_dir ) {
   268          $script:install_dir = $DEFAULT_INSTALL_PATH
   269        }
   270        $script:install_dir = Get-AbsolutePath($script:install_dir)
   271      }
   272      else {
   273        $script:install_dir = [System.IO.Path]::GetFullPath($script:install_dir)
   274      }
   275  
   276      If (-Not (Test-Path $script:install_dir) ) {
   277        New-Item -ItemType directory -Path $script:install_dir | Out-Null
   278      }
   279  
   280      Show-ColorText 'Using install directory: ' '' "$script:install_dir" DarkCyan
   281      Remove-Indent
   282    }
   283  
   284    # This will set the urls to use when downloading the agent and its plugins.
   285    # These urls are constructed based on the --version flag.
   286    # If not specified, the version defaults to "latest".
   287    function Set-DownloadURLs {
   288      Show-ColorText 'Configuring download urls...'
   289      Add-Indent
   290      if ( !$script:version ) {
   291        $script:agent_download_url = "$DOWNLOAD_BASE/latest/download/carbon_windows_amd64"
   292        $script:plugins_download_url = "$DOWNLOAD_BASE/latest/download/carbon-plugins.zip"
   293      }
   294      else {
   295        $script:agent_download_url = "$DOWNLOAD_BASE/download/$script:version/carbon_windows_amd64"
   296        $script:plugins_download_url = "$DOWNLOAD_BASE/download/$script:version/carbon-plugins.zip"
   297      }
   298      Show-ColorText "Using agent download url: " '' "$script:agent_download_url" DarkCyan
   299      Show-ColorText "Using plugins download url: " '' "$script:plugins_download_url" DarkCyan
   300      Remove-Indent
   301    }
   302  
   303    # This will set the home directory of the agent based on
   304    # the install directory provided.
   305    function Set-HomeDir {
   306      Show-ColorText 'Setting home directory...'
   307      Add-Indent
   308      $script:agent_home = "{0}observiq\carbon" -f $script:install_dir
   309  
   310      If (-Not (Test-Path $script:agent_home) ) {
   311        New-Item -ItemType directory -Path $agent_home | Out-Null
   312      }
   313  
   314      Show-ColorText "Using home directory: " '' "$script:agent_home" DarkCyan
   315      Remove-Indent
   316    }
   317  
   318    # This will set the plugins directory of the agent based on
   319    # the install directory provided.
   320    function Set-PluginDir {
   321      Show-ColorText 'Setting plugin directory...'
   322      Add-Indent
   323      $script:plugin_dir = "{0}\plugins" -f $script:agent_home
   324  
   325      If (-Not (Test-Path $script:plugin_dir) ) {
   326        New-Item -ItemType directory -Path $plugin_dir | Out-Null
   327      }
   328  
   329      Show-ColorText "Using plugin directory: " '' "$script:plugin_dir" DarkCyan
   330      Remove-Indent
   331    }
   332  
   333    # This will set the path for the agent binary.
   334    function Set-BinaryLocation {
   335      Show-ColorText 'Setting binary location...'
   336      Add-Indent
   337  
   338      $script:binary_location = Get-AbsolutePath("$script:agent_home\carbon.exe")
   339      Show-ColorText "Using binary location: " '' "$script:binary_location" DarkCyan
   340      Remove-Indent
   341    }
   342  
   343    # This will set the user that will run the agent as a service.
   344    # If not provided as a flag, this will default to the current user.
   345    function Set-ServiceUser {
   346      Show-ColorText 'Setting service user...'
   347      Add-Indent
   348      If (!$script:service_user ) {
   349        $current_user = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
   350        $script:service_user = $current_user
   351      }
   352      Show-ColorText "Using service user: " '' "$script:service_user" DarkCyan
   353      Remove-Indent
   354    }
   355  
   356    # This will set user permissions on the install directory.
   357    function Set-Permissions {
   358      Show-Header "Setting Permissions"
   359      Add-Indent
   360      Show-ColorText "Setting file permissions for NetworkService user..."
   361  
   362      try {
   363        $Account = New-Object System.Security.Principal.NTAccount "NT AUTHORITY\NetworkService"
   364        $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
   365        $PropagationFlag = 0
   366        $NewAccessRule = New-Object Security.AccessControl.FileSystemAccessRule $Account, "Modify", $InheritanceFlag, $PropagationFlag, "Allow"
   367        $FolderAcl = Get-Acl $script:agent_home
   368        $FolderAcl.SetAccessRule($NewAccessRule)
   369        $FolderAcl | Set-Acl $script:agent_home
   370        Succeeded
   371      }
   372      catch {
   373        Failed
   374        Exit-Error $MyInvocation.ScriptLineNumber "Unable to set file permissions for NetworkService user: $($_.Exception.Message)"
   375      }
   376  
   377      try {
   378        $Account = New-Object System.Security.Principal.NTAccount "$script:service_user"
   379  
   380        # First, ensure modify permissions on the install path
   381        Show-ColorText 'Checking for ' '' 'Modify' Yellow ' permissions...'
   382        Add-Indent
   383        $ModifyValue = [System.Security.AccessControl.FileSystemRights]::Modify -as [int]
   384        $FolderAcl = Get-Acl $script:agent_home
   385  
   386        $UserHasModify = $FolderAcl.Access | Where-Object { ($_.FileSystemRights -band $ModifyValue) -eq $ModifyValue -and $_.IdentityReference -eq $Account }
   387        if (-not $UserHasModify) {
   388          Show-ColorText 'Modify' Yellow ' permissions not found for ' '' "$Account" DarkCyan
   389          Remove-Indent
   390          Show-ColorText 'Granting permissions...'
   391          $NewAccessRule = New-Object Security.AccessControl.FileSystemAccessRule $Account, "Modify", $InheritanceFlag, $PropagationFlag, "Allow"
   392          $FolderAcl.SetAccessRule($NewAccessRule)
   393          $FolderAcl | Set-Acl $script:agent_home
   394          Succeeded
   395        }
   396        else {
   397          Show-ColorText "$Account" DarkCyan ' already possesses ' "" 'Modify' Yellow ' permissions on the install directory.'
   398          Remove-Indent
   399        }
   400      }
   401      catch {
   402        Show-ColorText "Unable to verify user permissions: $($_.Exception.Message)" Yellow
   403      }
   404      Complete
   405      Remove-Indent
   406    }
   407  
   408    # This will download the agent binary to the binary location.
   409    function Get-CarbonBinary {
   410      Show-Header "Downloading Carbon Binary"
   411      Add-Indent
   412      Show-ColorText 'Downloading binary. Please wait...'
   413      Show-ColorText "$INDENT_WIDTH$script:agent_download_url" DarkCyan ' -> ' '' "$script:binary_location" DarkCyan
   414      try {
   415        $WebClient = New-Object System.Net.WebClient
   416        $WebClient.DownloadFile($script:agent_download_url, $script:binary_location)
   417        Complete
   418      }
   419      catch {
   420        Failed
   421        $error_message = $_.Exception.Message -replace 'Exception calling.*?: ', ''
   422        Exit-Error $MyInvocation.ScriptLineNumber "Failed to download agent binary: $error_message"
   423      }
   424      Remove-Indent
   425    }
   426  
   427    # This will download and extract plugins to the plugins directory.
   428    function Get-CarbonPlugins {
   429      Show-Header "Downloading Carbon Plugins"
   430      Add-Indent
   431      Show-ColorText 'Downloading plugins. Please wait...'
   432      Show-ColorText "$INDENT_WIDTH$script:plugins_download_url" DarkCyan ' -> ' '' "$script:agent_home\plugins.zip" DarkCyan
   433  
   434      try {
   435        New-Item -Path "$script:agent_home\download\tmp" -ItemType "directory"
   436        Complete
   437      }
   438      catch {
   439        Failed
   440        $error_message = $_.Exception.Message -replace 'Exception calling.*?: ', ''
   441        Exit-Error $MyInvocation.ScriptLineNumber "Failed to create tmp directory plugins: $error_message"
   442      }
   443  
   444      try {
   445        $WebClient = New-Object System.Net.WebClient
   446        $WebClient.DownloadFile($script:plugins_download_url, "$script:agent_home\download\plugins.zip")
   447        Complete
   448      }
   449      catch {
   450        Failed
   451        $error_message = $_.Exception.Message -replace 'Exception calling.*?: ', ''
   452        Exit-Error $MyInvocation.ScriptLineNumber "Failed to download plugins: $error_message"
   453      }
   454  
   455      try {
   456        [System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null
   457        [System.IO.Compression.ZipFile]::ExtractToDirectory("$script:agent_home\download\plugins.zip", "$script:agent_home\download")
   458        Complete
   459      }
   460      catch {
   461        Failed
   462        $error_message = $_.Exception.Message -replace 'Exception calling.*?: ', ''
   463        Exit-Error $MyInvocation.ScriptLineNumber "Failed to expand plugins archive: $error_message"
   464      }
   465  
   466      try {
   467        Copy-Item -Path "$script:agent_home\download\plugins\*.yaml" -Destination "$script:agent_home\plugins"
   468        Complete
   469      }
   470      catch {
   471        Failed
   472        $error_message = $_.Exception.Message -replace 'Exception calling.*?: ', ''
   473        Exit-Error $MyInvocation.ScriptLineNumber "Failed to relocate plugins: $error_message"
   474      }
   475  
   476      try {
   477        Remove-Item -Path "$script:agent_home\download" -Recurse
   478        Complete
   479      }
   480      catch {
   481        Failed
   482        $error_message = $_.Exception.Message -replace 'Exception calling.*?: ', ''
   483        Exit-Error $MyInvocation.ScriptLineNumber "Failed to clean up download: $error_message"
   484      }
   485  
   486      Remove-Indent
   487    }
   488  
   489    # This will remove the agent service.
   490    function Remove-AgentService {
   491      $service = Get-Service $SERVICE_NAME -ErrorAction SilentlyContinue
   492      If ($service) {
   493        Show-ColorText 'Previous ' '' "$SERVICE_NAME" DarkCyan ' service detected.'
   494        If ($service.Status -eq 'Running') {
   495          Show-ColorText 'Stopping ' '' "$SERVICE_NAME" DarkCyan '...'
   496          if ($script:PSVersion -ge 5) {
   497            Stop-Service $SERVICE_NAME -NoWait -Force | Out-Null
   498          }
   499          else {
   500            Stop-Service $SERVICE_NAME | Out-Null
   501          }
   502          Show-ColorText "Service Stopped."
   503        }
   504        Show-ColorText 'Removing ' '' "$SERVICE_NAME" DarkCyan ' service...'
   505        (Get-WmiObject win32_service -Filter "name='$SERVICE_NAME'").delete() | Out-Null
   506  
   507        If ( $LASTEXITCODE -eq 0 ) {
   508          # Sleep 5 seconds to give time for the service to be fully deleted
   509          sleep -s 5
   510          Show-ColorText 'Previous service removed.'
   511        }
   512      }
   513    }
   514  
   515    # This will create the agent config.
   516    function New-AgentConfig {
   517      Show-Header "Generating Config"
   518      Add-Indent
   519      $config_file = "$script:agent_home\config.yaml"
   520      Show-ColorText 'Writing config file: ' '' "$config_file" DarkCyan
   521      try {
   522        Write-Config $config_file
   523      }
   524      catch {
   525        Exit-Error $MyInvocation.ScriptLineNumber "Failed to write config file: $($_.Exception.Message)" 'Please ensure you have permission to create this file.'
   526      }
   527  
   528      Complete
   529      Remove-Indent
   530    }
   531  
   532    # This will write the agent config.
   533    function Write-Config {
   534      # Skip overwriting the config file if it already exists
   535      if (Test-Path $args) { return }
   536  
   537      @"
   538  pipeline:
   539  # An example input that generates a single log entry when Carbon starts up.
   540    - type: generate_input
   541      count: 1
   542      entry:
   543        record: This is a sample log generated by Carbon
   544      output: example_output
   545  
   546    # An example input that monitors the contents of a file.
   547    # For more info: https://github.com/observIQ/carbon/blob/master/docs/operators/file_input.md
   548    #
   549    # - #   type: file_input
   550    #   include:
   551    #     - /sample/file/path
   552    #   output: example_output
   553  
   554    # An example output that sends captured logs to stdout.
   555    - id: example_output
   556      type: stdout
   557  
   558    # An example output that sends captured logs to google cloud logging.
   559    # For more info: https://github.com/observIQ/carbon/blob/master/docs/operators/google_cloud_output.md
   560    #
   561    # - id: example_output
   562    #   type: google_cloud_output
   563    #   credentials_file: /my/credentials/file
   564  
   565    # An example output that sends captured logs to elasticsearch.
   566    # For more info: https://github.com/observIQ/carbon/blob/master/docs/operators/elastic_output.md
   567    #
   568    # - id: example_output
   569    #   type: elastic_output
   570    #   addresses:
   571    #     - http://my_node_address:9200
   572    #   api_key: my_api_key
   573  "@ > $args
   574    }
   575  
   576    # This will create a new agent service.
   577    function New-AgentService {
   578      Show-Header "Creating Service"
   579      Add-Indent
   580      Install-AgentService
   581      Start-AgentService
   582      Complete
   583      Remove-Indent
   584    }
   585  
   586    # This will install the agent service.
   587    function Install-AgentService {
   588      Show-ColorText 'Installing ' '' "$SERVICE_NAME" DarkCyan ' service...'
   589  
   590      $service_params = @{
   591        Name           = "$SERVICE_NAME"
   592        DisplayName    = "$SERVICE_NAME"
   593        BinaryPathName = "$script:binary_location --config $script:agent_home\config.yaml --log_file $script:agent_home\$SERVICE_NAME.log --database $script:agent_home\$SERVICE_NAME.db --plugin_dir $script:plugin_dir"
   594        Description    = "Monitors and processes logs."
   595        StartupType    = "Automatic"
   596      }
   597  
   598      try {
   599        New-Service @service_params -ErrorAction Stop | Out-Null
   600      }
   601      catch {
   602        Exit-Error $MyInvocation.ScriptLineNumber "Failed to install the $SERVICE_NAME service." 'Please ensure you have permission to install services.'
   603      }
   604  
   605  
   606      $script:startup_cmd = "net start `"$SERVICE_NAME`""
   607      $script:shutdown_cmd = "net stop `"$SERVICE_NAME`""
   608      $script:autostart = "Yes"
   609    }
   610  
   611    # This will start the agent service.
   612    function Start-AgentService {
   613      Show-ColorText 'Starting service...'
   614      try {
   615        Start-Service -name $SERVICE_NAME -ErrorAction Stop
   616      }
   617      catch {
   618        $script:START_SERVICE = $FALSE
   619        Show-ColorText "Warning: An error prevented service startup: $($_.Exception.Message)" Yellow
   620        Show-ColorText "A restart may be required to start the service on some systems." Yellow
   621      }
   622    }
   623  
   624    # This will finish the install by printing out the results.
   625    function Complete-Install {
   626      Show-AgentInfo
   627      Show-InstallComplete
   628    }
   629  
   630    # This will display information about the agent after install.
   631    function Show-AgentInfo {
   632      Show-Header 'Information'
   633      Add-Indent
   634      Show-ColorText 'Carbon Home:   ' '' "$script:agent_home" DarkCyan
   635      Show-ColorText 'Carbon Config: ' '' "$script:agent_home\config.yaml"
   636      Show-ColorText 'Start On Boot: ' '' "$script:autostart" DarkCyan
   637      Show-ColorText 'Start Command: ' '' "$script:startup_cmd" DarkCyan
   638      Show-ColorText 'Stop Command:  ' '' "$script:shutdown_cmd" DarkCyan
   639      Complete
   640      Remove-Indent
   641    }
   642  
   643    # This will provide a user friendly message after the installation is complete.
   644    function Show-InstallComplete {
   645      Show-Header 'Installation Complete!' Green
   646      Add-Indent
   647      if ( $script:START_SERVICE ) {
   648        Show-ColorText "Your agent is installed and running.`n" Green
   649      }
   650      else {
   651        Show-ColorText 'Your agent is installed but not running.' Green
   652        Show-ColorText "Please restart to complete service installation.`n" Yellow
   653      }
   654      Remove-Indent
   655    }
   656  
   657    function Main {
   658      [cmdletbinding()]
   659      param (
   660        [Alias('y', 'accept_defaults')]
   661        [string]$script:accept_defaults,
   662  
   663        [Alias('v', 'version')]
   664        [string]$script:version,
   665  
   666        [Alias('i', 'install_dir')]
   667        [string]$script:install_dir = '',
   668  
   669        [Alias('u', 'service_user')]
   670        [string]$script:service_user,
   671  
   672        [Alias('h', 'help')]
   673        [switch]$script:help
   674      )
   675      try {
   676        Set-Variables
   677        # Variables which should be reset if the user calls Log-Agent-Install without redownloading script
   678        $script:indent = ''
   679        $script:START_SERVICE = $TRUE
   680        if ($MyInvocation.Line -match 'Log-Agent-Install.*') {
   681          $script:rerun_command = $matches[0]
   682        }
   683        if ($PSBoundParameters.ContainsKey("script:help")) {
   684          Show-Usage
   685        }
   686        else {
   687          Set-Window-Title
   688          Show-Separator
   689          Test-Prerequisites
   690          Set-InstallVariables
   691          Set-Permissions
   692          Remove-AgentService
   693          Get-CarbonBinary
   694          Get-CarbonPlugins
   695          New-AgentConfig
   696          New-AgentService
   697          Complete-Install
   698          Show-Separator
   699        }
   700        $exited_success = $true
   701      }
   702      catch {
   703        if ($_.Exception.Message) {
   704          if ($script:IS_PS_ISE) {
   705            $psIse.Options.ConsolePaneBackgroundColor = $script:DEFAULT_BG_COLOR
   706          }
   707          else {
   708            $host.ui.rawui.BackgroundColor = $script:DEFAULT_BG_COLOR
   709          }
   710  
   711          Show-ColorText "$_" Red
   712        }
   713        $exited_error = $true
   714      }
   715      finally {
   716        Restore-Window-Title
   717        if (!$exited_success -and !$exited_error) {
   718          # Write-Host is required here; anything that uses the pipeline will block
   719          # and not print if the user cancels with ctrl+c.
   720          Write-Host "`nScript canceled by user.`n" -ForegroundColor Yellow
   721        }
   722      }
   723    }
   724  
   725    set-alias 'Log-Agent-Install' -value Main
   726    Export-ModuleMember -Function 'Main', 'Get-ProjectMetadata' -alias 'Log-Agent-Install'
   727  } | Out-Null