Prompt for selection of Get-Content file to perform action against

I have a list of servers that I use in code to verify last reboot (or uptime). I often change the contents (server names) of the text file to get uptime for another set of servers.

Rather than changing the contents of the list, my goal is to have a PS script that allows me to choose a pre-populated .txt file, containing the listing of servers.

I’d like for PS to ask "Choose which file to check uptime from…
1-server list A
2-Server list B
3-etc
4-Cancel

then then the code should perform the following working code:

Start-Transcript -Path "C:\uptime\scripterroruptime.txt"
ForEach ($server in Get-Content "C:\uptime\ListA.txt")
{

echo $server

if(Test-Connection -ComputerName $server -Count 1 -quiet)
{
$uptime = Get-WmiObject -computername $server -Class win32_operatingsystem
$uptime1 = $uptime.ConvertToDateTime($uptime.LastBootUpTime)
$computer= $uptime.PSComputerName
#echo $computer
#echo $uptime1

$Object = New-Object PSObject -Property @{
 
    ComputerName     = $computer
    Serveruptime = $uptime1 
        }

$AllComputers = $Object
$AllComputers | select ComputerName, Serveruptime  | Export-Csv -append -path C:\uptime\ServerUptime_ListA.csv -NoTypeInformation
}

Else
  {echo "$server not reachable"}

}
Stop-Transcript

rick,
Welcome to the forum. :wave:t3:

What’s the question?

I’d like for PS to ask "Choose which file to check uptime from, if anyone could assist with this, or at least a starting point?

Have you tried to search for it? When you search for “Powershell prompt for choice” with Google you don’t even need to scroll down. The first three hits already explain everything you need. :man_shrugging:t3:

If that’s not what you’re looking for you should explain more detailed what need.

I think i am being pretty clear on what i am looking for. You may be some sort of admin or top commenter, however, based on some other posts i came across in here. I was hoping someone would just help me connect my piece of code provided, to a piece of code that assists with selecting the file to pull from. If you’re just worried about how to properly format my question, then i may have come to the wrong site. I really just want someone to assist me with code, not formatting of posts.

With that said, I did look up “powershell prompt to select get-content”, “powershell prommpt choose alternate .txt file in get-content”.

With me not being an expert in PS code, i came across many articles that quite frankly, overwhelmed me. None of them were the same. They had information that may or may not apply to me.

That is what led me to this site, after spending a few hours online on google.

Hopefully someone in here understands where i am coming from and are willing to help.

Thanks

It is quite unlikely that you’ll find a code snippet online matching 100 % exactly what you’re looking for. So you will have to adapt what you’ve found to your particular needs.

Have you tried some of the options you’ve found online? What exactly is it what you’re struggling with?

Thanks. I’ll wait for someone else to answer that I can work with. Maybe a suggestion of code that they may have in mind. Im thinking something related to “System.Management.Automation.Host.ChoiceDescription” that i just learned about and also know nothing about.

So you want to go with the dotNet method.

One of the hits I’ve got when I searched on Google was this:

There you have 3 option to choose from and 3 according script blocks. IMHO that’s quite easy to understand, don’t you agree?

The asking for a choice part appears to be understandable, however, out of all of the articles that have come up, they all demo some text being returned on the command prompt, for the purposes of the demo, however, I’ve been struggling tying the script that i have, to the choices code. Bridging both things is my issue here, and need assistance with.

You can stop mentioning Google, as I am quite familiar with going to that first.

OK, since you want to provide the content of different text files according to your choice you simply replace the demo text with the command reading the content of your input files and saving it to a variable. Later you simply use this variable to provide the content of either file to your loop. Is it this what you mean?

$Title = "Hi Rick, What server list do you want to check?"
$Prompt = "Enter your choice"
$Choices = [System.Management.Automation.Host.ChoiceDescription[]] @("&One", "&Two", "&None")
$Default = 0

# Prompt for the choice
$Choice = $host.UI.PromptForChoice($Title, $Prompt, $Choices, $Default)

# Action based on the choice
switch($Choice)
{
    0 { $ServerList = Get-Content - Path 'Path to input file one.txt'}
    1 { $ServerList = Get-Content - Path 'Path to input file two.txt'}
    2 { Exit}
}

Now, instead of using Get-Content ... directly in your foreach loop you use the variable. :wink:

Ok i think we are getting somewhere now! But I am extremely unfamiliar, so I am still unclear on how to change the ForEach loop to the variable, as I am not sure which part is the variable. Is it “$Choice”.

And if so, how do i translate this in to my code to use the variable? Sorry if i am being very basic. Trying to learn, but I am a novice

$Title = "Hi Rick, What server list do you want to check?"
$Prompt = "Enter your choice"
$Choices = [System.Management.Automation.Host.ChoiceDescription[]] @("&One", "&Two", "&None")
$Default = 1

# Prompt for the choice
$Choice = $host.UI.PromptForChoice($Title, $Prompt, $Choices, $Default)

# Action based on the choice
switch($Choice)
{
    1 { $ServerList = Get-Content - Path 'C:\PS\Uptime\ListA.txt'}
    2 { $ServerList = Get-Content - Path 'C:\PS\Uptime\ListB.txt'}
    3 { Exit}
}

Start-Transcript -Path "C:\uptime\scripterroruptime.txt"
ForEach ($server in Get-Content "C:\uptime\ListA.txt")
{

echo $server

if(Test-Connection -ComputerName $server -Count 1 -quiet)
{
$uptime = Get-WmiObject -computername $server -Class win32_operatingsystem
$uptime1 = $uptime.ConvertToDateTime($uptime.LastBootUpTime)
$computer= $uptime.PSComputerName
#echo $computer
#echo $uptime1

$Object = New-Object PSObject -Property @{
 
    ComputerName     = $computer
    Serveruptime = $uptime1 
        }

$AllComputers = $Object
$AllComputers | select ComputerName, Serveruptime  | Export-Csv -append -path C:\uptime\ServerUptime_ListA.csv -NoTypeInformation
}

Else
  {echo "$server not reachable"}

}
Stop-Transcript

We all started once. :man_shrugging:t3:

The best way to figure things out is to try!! :wink: Since you’re not using any invasive cmdlets you cannot break anything. :man_shrugging:t3:

Sorry if I’m being pushy. :wink:

I will quote myself:

According to your choice you are filling a variable with the content of an input text file. And in your original loop you use directly Get-Content. What variable could it be? :smirk:

You can even just assign the path to the according input files and still use your Get-Content in your loop. You just provide the path with the variable containing the path to the chosen input file.
Play a little with the code. Try this and that. This way you’ll learn it wayfaster and more sustainably than getting the finished code. :+1:t3: :love_you_gesture:t3:

I’ll have to try another site as I am needing this to complete a work-related task. Thanks anyway

I don’t get it. You’re almost there. But it’s your decision. :man_shrugging:t3: Good luck. :love_you_gesture:t3:

If i can just get first one to work. Choice 2 (just a simple ping) works. The first one does nothing

$Title = "Hi Rick, What server list do you want to check?"
$Prompt = "Enter your choice"
$Choices = [System.Management.Automation.Host.ChoiceDescription[]] @("&One", "&Two", "&None")
$Default = 1

# Prompt for the choice
$Choice = $host.UI.PromptForChoice($Title, $Prompt, $Choices, $Default)

# Action based on the choice
switch ($Choice)
{
    0 {$ServerList = Get-Content -Path 'C:\PS\Uptime\ListA.txt'
    
    ForEach ($server in $ServerList) {

        echo $server

        {
$uptime = Get-WmiObject -Class win32_operatingsystem
$uptime1 = $uptime.ConvertToDateTime($uptime.LastBootUpTime)
$computer= $uptime.PSComputerName
#echo $computer
#echo $uptime1

$Object = New-Object PSObject -Property @{
 
    ComputerName     = $computer
    Serveruptime = $uptime1 
        }

$AllComputers = $Object
$AllComputers | select ComputerName, Serveruptime  | Export-Csv -append -path C:\PS\Uptime\ListA.csv -NoTypeInformation
}

}}    
    
    1 {$ServerList = Get-Content -Path 'C:\PS\Uptime\ListB.txt'
    
    ForEach ($server in $ServerList) {

        ping $server
    
    
}}
    2 {Exit}
}

Of course you could put a whole script block inside the switch statement but since the input is the only difference between both options it does not make that much sense. You end up with unnecessarily repetitive code.

Simply use my code suggestion and change your loop from

ForEach ($server in Get-Content "C:\uptime\ListA.txt")

to

ForEach ($server in $ServerList)

That’s exactly what I described earlier.
:man_shrugging:t3:

Ok so the code below works, however, can you review and see if there is anything i can do to make it more efficient or remove unnecessary items/structure? Please reply with the entire code modified. It helps me see it better, rather than telling me what to change, because that doesnt always work, or I may mis-place something…

OPTION ONE (“0”) checks ListA (this performs the function that i will eventually roll out to all options)
OPTION TWO (“1”) checks ListB (simple ping to list of servers, just for now as i work on code)
OPTION NONE (“2”) exits choice

$Title = "Hi Rick, What server list do you want to check?"
$Prompt = "Enter your choice"
$Choices = [System.Management.Automation.Host.ChoiceDescription[]] @("&One", "&Two", "&None")
$Default = 1

# Prompt for the choice
$Choice = $host.UI.PromptForChoice($Title, $Prompt, $Choices, $Default)

# Action based on the choice
switch ($Choice)
{
    0 {$ServerList = Get-Content -Path 'C:\PS\Uptime\ListA.txt'
    
    ForEach ($server in $ServerList) {

        echo $server
        if(Test-Connection -ComputerName $server -Count 1 -quiet)
        {
            $uptime = Get-WmiObject -computername $server -Class win32_operatingsystem
            $uptime1 = $uptime.ConvertToDateTime($uptime.LastBootUpTime)
            $computer= $uptime.PSComputerName

#echo $computer
#echo $uptime1

$Object = New-Object PSObject -Property @{
 
    ComputerName     = $computer
    Serveruptime = $uptime1 
        }

$AllComputers = $Object
$AllComputers | select ComputerName, Serveruptime  | Export-Csv -append -path C:\PS\Uptime\ListA.csv -NoTypeInformation
}

Else
  {echo "$server not reachable"}

}}    
    
    1 {$ServerList = Get-Content -Path 'C:\PS\Uptime\ListB.txt'
    
    ForEach ($server in $ServerList) {

        ping $server
    
    
}}
    2 {Exit}
}

Great. :+1:t3:

Seems like you changed your requirement or the actual goal of the script.

As I already mentioned … while it is possible to add longer scriptblocks inside your switch statement it makes your code hard to read and to maintain.

Your code is badly formatted, uses aliasses and unnecessary intermediate auxillary variables.

I highly recommend to read

Regardless of that you should not use Get-WmiObject anymore since it is deprecated. Use

instead.

Last but not least … instead of ping we use Test-Connection in PowerShell. :smirk: … as you already did for your first option. :man_shrugging:t3:

You are very vague, however, I will read the articles you mentioned.

An example of any of my “intermediate auxiliary variables” would be nice, so that i can get a clue as to what you are referring to. I believe you, i just dont know what to look at, exactly.

Thanks for your help.

For your option one

$Result = 
ForEach ($ComputerName in (Get-Content -Path 'C:\PS\Uptime\ListA.txt')) {
    if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet) {
        [PSCustomObject]@{
            ComputerName   = $ComputerName
            Online         = $true
            LastBootUptime = (Get-CimInstance -ClassName CIM_OperatingSystem -ComputerName $ComputerName ).LastBootUpTime
        }
    }
    Else { 
        [PSCustomObject]@{
            ComputerName   = $ComputerName
            Online         = $false
            LastBootUptime = 'n/a'
        }
    }
}
$Result |
Export-Csv -Path 'C:\PS\Uptime\ListA.csv' -NoTypeInformation