Откройте несколько удаленных сеансов, используя «mstsc» в сценарии powershell

Я пытаюсь написать сценарий powershell, который открывает подключение к удаленному рабочему столу для каждого имени компьютера, сохраненного в текстовом файле. Когда я запускаю скрипт, он подключается только к первой машине в списке и выводит на консоль: CMDKEY: Credential added successfully один раз (не один раз для каждой машины). mstcs, похоже, завершает процесс после выполнения, и я не уверен, что правильно добавляю учетные данные. Может кто-то указать мне верное направление?

Вот несколько тестов, которые я пытался выяснить, что происходит:

  • Печатать после mstsc. Не печатает. Кажется, что процесс завершается после вызова mstcs. Кажется, это суть вопроса.
  • cmdkey /list показывает все учетные данные, которые я сохранил, и их цели. Выходные данные не включают все цели, определенные в текстовом файле. Даже если я закомментирую mstsc, то cmdkey /add:$MachineName /user:$User /pass:$Password, похоже, будет выполняться только для первой строки, о чем свидетельствует отсутствие большего количества выходных данных консоли и cmdkey /list, не дающие ожидаемых целей. Кроме того, я добавил оператор печати после этой строки cmdkey, и он печатает для каждой строки, поэтому он не завершается после запуска (о чем я уже знал, потому что mstcs выполняется после этой строки, когда она не закомментирована).
# 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: я также пытался заменить mstsc /v:$MachineName на Start-Process -FilePath "$env:windir\system32\mstsc.exe" -ArgumentList "/v:$MachineName" -Wait. В результате открывается сессия, а затем скрипт не завершается в консоли, но больше ничего не происходит.


person nonethewiser    schedule 19.11.2020    source источник
comment
Удалить | Out-String — он берет отдельные строки, которые вы только что прочитали из файла, и превращает их в одну многострочную строку, поэтому ваш цикл завершается после однократного запуска.   -  person Mathias R. Jessen    schedule 20.11.2020
comment
@mathiasR.Jessen, это работает! Я добавил, что раньше без особого понимания... в ретроспективе это было больше для целей отладки. Все еще пытаюсь понять, почему он вел себя именно так. Спасибо за ваш вклад.   -  person nonethewiser    schedule 20.11.2020
comment
мой первоначальный комментарий был до того, как вы добавили объяснение многострочной строки. Это делает причину понятной. Спасибо еще раз.   -  person nonethewiser    schedule 20.11.2020


Ответы (1)


Такое поведение вызвано тем, что вы используете Out-String.

Get-Content выводит несколько строк, по одной на строку в файле, но Out-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

Таким образом, ваш цикл foreach(){} запускается один раз, а значение $MachineName больше не является именем одной машины, а представляет собой многострочную строку со всеми ими одновременно — возможно, поэтому mstsc немедленно завершает работу. :)

Удалите |Out-String из первой строки, и ваш цикл заработает.

person Mathias R. Jessen    schedule 19.11.2020
comment
забавно то, что я распечатал каждую строку (как оказалось, только одну) в цикле for, чтобы попытаться отладить что-то. Казалось, что он печатает каждую строку (потому что все строки были напечатаны), но я не понял, что это была 1 многострочная строка. - person nonethewiser; 20.11.2020
comment
@nonethewiser Я всегда добавляю некоторые квалификаторы к значениям в сообщениях отладки, т.е. Write-Host "Machine Name is '$MachineName'" вместо простого Write-Host $MachineName - person Mathias R. Jessen; 20.11.2020