0

I am trying to write a powershell script that opens a remote desktop connection for each machine name saved in a text file. When I run the script, it only connects to the first machine in the list and outputs to the console: CMDKEY: Credential added successfully once (not once for each machine). mstcs seems to terminate the process after executing, and I'm not sure I'm adding credentials the right way. Can anyone point me in the right direction?

Here are some tests I've tried to figure out what's going on:

  • Print after mstsc. Doesn't print. Process seems to terminate after mstcs is called. This seems to be the crux of the issue.
  • cmdkey /list shows all the credentials I have stored and their targets. The output does not include all the targets defined in the text file. Even if I comment out mstsc, then cmdkey /add:$MachineName /user:$User /pass:$Password only seems to execute for the first line, evidenced by the lack of more console outputs and cmdkey /list not yielding the expected targets. In addition, I have added a print statement after this cmdkey line and it prints for each line, so it doesn't terminate after running (which I already knew because mstcs executes after this line when it's not commented out).
# Read from file
$Lines = Get-Content -Path .\machines.txt | Out-String

# For each machine ...
foreach($Line in $Lines){
    # Split line, save name and domain
    $Tokens = $Line.Split(".")

    $MachineName = $Tokens[0]
    $Domain = $Tokens[1]
    $User = "someDomain\someUsername"
    $Password="somePassword"

    # Switch username if someOtherDomain
    if ($Domain -eq "someOtherDomain"){
        $User = "someOtherDomain\someOtherUsername"
    }

    #set credentials and open connection
    cmdkey /add:$MachineName /user:$User /pass:$Password
    mstsc /v:$MachineName /console
}

EDIT: I have also tried replacing mstsc /v:$MachineName with Start-Process -FilePath "$env:windir\system32\mstsc.exe" -ArgumentList "/v:$MachineName" -Wait. The result is opening the session and then the script does not finish in the console but nothing additional happens.

nonethewiser
  • 550
  • 1
  • 6
  • 18
  • 1
    Remove `| Out-String` - it takes the individual lines you just read from the file and turns them into a single multiline string, which is why your loop exits after running once – Mathias R. Jessen Nov 19 '20 at 23:12
  • @mathiasR.Jessen that works! I added that earlier without a great understanding... in retrospect it was more for debugging purposes. Still trying to process why it behaved the way it did. Thanks for your input. – nonethewiser Nov 19 '20 at 23:19
  • my initial comment was before you added the explanation about the multiline string. That makes the reason clear. Thanks again. – nonethewiser Nov 19 '20 at 23:31

1 Answers1

1

This behavior is cause by your use of Out-String.

Get-Content outputs multiple strings, one per line in the file - but Out-String stitches them back together into a single multi-line string:

PS C:\> $machines = Get-Content machines.txt
PS C:\> $machines.GetType().Name   # definitely an array
Object[]
PS C:\> $machines.Count            # multiple strings in there
4
PS C:\> $machines = Get-Content machines.txt | Out-String
PS C:\> $machines.GetType().Name   # now it's just a single string
String

So your foreach(){} loop only runs once, and the value of $MachineName is no longer the name of a single machine, but a multi-line string with all of them at once - which is probably why mstsc exits immediately :)

Remove |Out-String from the first line and your loop will work

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • the funny thing is I printed out "each" line (as it turns out, just one) in the for-loop to try and debug things. It appeared to print each line (because all lines were printed) but I did not realize it was 1 multiline string. – nonethewiser Nov 20 '20 at 02:49
  • 1
    @nonethewiser I tend to always add some qualifier around values in debug messages ie. `Write-Host "Machine Name is '$MachineName'"` instead of just plain `Write-Host $MachineName` – Mathias R. Jessen Nov 20 '20 at 02:53