2

I'm trying a to make this PowerShell script that would ask for the user to input a service name, run through Get-Service, and show the result to the user.

For example, if the user was to enter vmtools it would show:

Status      Name      DisplayName
------      ----      -----------
Running     vmtools   VMware Tools

This is my code:

Write-host "Enter Service name"
$ServiceName = read-host
$Result = get-service $ServiceName
Write-Output "$Result" 

However, it only outputs: System.ServiceProcess.ServiceController

Maxime Franchot
  • 1,015
  • 1
  • 10
  • 24

2 Answers2

3

tl;dr

$Result # Implicitly outputs $Result - no need for Write-Output or "..."

Unlike POSIX-like shells (Unix):

  • PowerShell never requires "..." around a variable reference such as $Result.

    • In fact, doing so converts the variable to a string - which may or may not be the intent.
  • If you do want a string, using "..." around a variable reference often - but not necessarily - results in a different representation than when printing to the terminal (console).

  • If the object is to be processed further, pass it on as-is, otherwise you'll lose the benefits of PowerShell's object orientation.

PowerShell passes objects around - which represents its great evolutionary leap from traditional shells - and only on (a) output to the terminal or sending output to a file with > (Out-File) / Out-String or (b) inside "..." or (c) when applying .ToString() are these objects stringified:

  • (a) uses PowerShell's default formatting system, which allows you to define custom representations for any .NET type (with several representations predefined); e.g., outputting hashtable @{ one = 1; two = 2} yields a pretty-printed 2-column layout; see Get-Help about_format.ps1xml.

  • (b) and (c) bypass PowerShell's default formatting:

    • (c), directly calling each object's .ToString() method - can range from a virtually meaningless type name-only representation (as in your case, or as in @{ one = 1; two = 2 }.ToString(), which yields System.Collection.Hashtable) to a culture-sensitive representation (e.g., (Get-Date '2017-01-01').ToString() yields 1/1/17 12:00:00 AM on a US-English system) - depending on whatever the given type supports.
      For the .NET base types, the .ToString() representation is the same as PowerShell's default formatting.

    • (b)'s rules (implicit stringification inside "...") are similar to (c)'s except that PowerShell by design seeks a culture-invariant representation where supported - for details, see this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

That is because when you add quotation marks around certain types of variables, it outputs the variable type, not the actual contents of the variable. Therefore, removing quotation marks on the variable output will fix your problem. Replace your last line with this:

Write-Output $Result 
Maxime Franchot
  • 1,015
  • 1
  • 10
  • 24
  • It doesn't output a _type_ - it does output the _contents_ of the variable, albeit in _stringified form_, via the type's `.ToString()` method - and only if a given type doesn't override the default implementation of that method does it result in a string containing the _type name_. A counterexample is `$Result = Get-Date; "$Result"` – mklement0 Feb 02 '23 at 20:28