remote session returning local results

Welcome Forums General PowerShell Q&A remote session returning local results

This topic contains 11 replies, has 3 voices, and was last updated by

 
Participant
1 month, 3 weeks ago.

  • Author
    Posts
  • #114229

    Participant
    Points: 0
    Rank: Member

    Hello All, first time poster here.  I have a script that is driving me a little nuts. The intent is for me to provide it a list of computernames, it will pssession to each one and search c:\users recurse to find any .lnk.  then, if the target of the link is a specific target it will log some info into a variable object and dump it into a csv file on a server.  Each time i manually step through the code using a remote session, it works correctly; however when I feed it a list of computers it returns MY machine's information for some reason. See code.  Any help is appreciated . . .

    $computers = get-content -path 'somepath'
    foreach ($computer in $computers){
    enter-pssession $computer
    invoke-command  {
    $mypwd = "*" | convertto-securestring -key (*)
    $mycred = new-object system.management.automation.pscredential "somecred",$mypwd
    function GetShortcuts{
    $shortcuts = get-childitem -recurse 'c:\users' -include *.lnk
    $Shell = New-Object -ComObject WScript.Shell
    $Link = @()
    new-psdrive X -PSProvider FileSystem -root "somepath" -Credential $mycred
    foreach ($shortcut in $shortcuts){
    if($shell.createshortcut($shortcut).targetpath -eq 'targetexe'){
    $link += [pscustomobject]@{
    CompName = $env:computername
    IconName = $shortcut.name
    Location = $shortcut.fullname
    Target = $shell.createshortcut($shortcut).targetpath
    }
    $link | export-csv -path "X:\shortcuts.csv" -NoTypeInformation -Append -NoClobber
    }

    }
    remove-psdrive -name X
    #   return $link
    }
    $output = GetShortcuts
    Exit-PSSession
    }
    }

     

  • #114271

    Keymaster
    Points: 1,673
    Helping HandTeam Member
    Rank: Community Hero

    It's really tough to follow code when you don't take a moment to format it – the instructions are right in the bulleted list above the posting box. When you don't do that, you lose all the indentation, and it's beastly to try and follow the logic.

    I'm curious why you're using Enter-PSSession, rather than just giving an array of computer names to Invoke-Command? This is an odd pattern.

    I would ordinarily expect to see something like...

    
    Invoke-Command -computername $computers -scriptblock {
    
    # whatever you want run remotely
    
    }
    
    

     

    But bear in mind that if the remote computer is sending its output to a CSV file, that CSV file will appear on each remote computer, and you won't get any other output back. It's important to really think about "what's running on my local computer, and what's running remotely," because the two can't "see" each other, share variables, share files, etc.

     

    • #114283

      Participant
      Points: 0
      Rank: Member

      I apologize for the formatting, I will pay more attention next time.  I originally started off  with Invoke-Command -computername $computers -scriptblock {

      however I had the machines all writing to a csv file on a network share to compile the data in one place and kept getting errors about the file in use.  So i figured i'd hit them one by one so the file wouldn't be locked by another machine at the time. I've only been using PowerShell for a couple weeks and am still fumbling around a lot!

  • #114277

    Participant
    Points: 814
    Helping Hand
    Rank: Major Contributor

    @paul, Adding to what Don has mentioned, you are trying to mix interactive and non interactive remoting.

    Enter-PSSession is for interactive remoting and has to be used like ssh in unix environments.

    For executing scripts remotely, you have to use Invoke-Command. You can even have a session object created and be used for subsequent remote calls. PowerShell remoting is very powerful and explaining the E2E use cases will not be possible via a Forum, hence I would ask to to take some time and go through the documentations., you can start from about_remote

  • #114286

    Participant
    Points: 0
    Rank: Member

    Does this help with formatting?

    $computers = get-content -path 'somepath'
    
    
    foreach ($computer in $computers){
        enter-pssession $computer
        invoke-command  {
            $mypwd = "encryptedpwd" | convertto-securestring -key (encryptionkey)
            $mycred = new-object system.management.automation.pscredential "usercred",$mypwd
            function GetShortcuts{
                $shortcuts = get-childitem -recurse 'c:\users' -include *.lnk
                $Shell = New-Object -ComObject WScript.Shell
                $Link = @()
                new-psdrive X -PSProvider FileSystem -root "servershare" -Credential $mycred 
        
                     foreach ($shortcut in $shortcuts){
                        if($shell.createshortcut($shortcut).targetpath -eq 'target.exe'){
                        $link += [pscustomobject]@{
                            CompName = $env:computername
                            IconName = $shortcut.name
                            Location = $shortcut.fullname
                            Target = $shell.createshortcut($shortcut).targetpath
                            }
                        $link | export-csv -path "X:\shortcuts.csv" -NoTypeInformation -Append -NoClobber
                        }
                 
                    }
                remove-psdrive -name X
               
              }
          $output = GetShortcuts
       Exit-PSSession
        }  
        
      }
    
  • #114289

    Keymaster
    Points: 1,673
    Helping HandTeam Member
    Rank: Community Hero

    Yeah, so here's the pattern:

    
    Invoke-Command -comp $computers -script {
    
    # whatever
    
    } | Export-CSV output.csv
    
    

     

    The idea is, you let the results of Invoke-Command come back to YOUR computer, and YOUR computer writes the results to a CSV. Only one computer nosing in the CSV. You rely on the PSComputerName add-on property, which Remoting will add, to tell which result came from where. So in your case, just "Write-Output $link" if that's what you want in the CSV.

    -Append and -NoClobber are mutually exclusive. You don't need them both.

  • #114291

    Participant
    Points: 814
    Helping Hand
    Rank: Major Contributor

    you can hit them one by one using Invoke-Command in foreach, please remove Enter-PSSession.
    Since you used array of computers, everyone tried to write to the same file and file lock has happened, what you can do is

    either, call Invoke-Command for each computer in computers
    or, call it using array of computers and get the output as object from everyone to the source machine, the convert them to CSV and copy to the share location.

  • #114292

    Participant
    Points: 0
    Rank: Member

    Would this be more appropriate?  Nevermind you guys were quick, I will rework this a little and try again! thanks!

    $computers = get-content -path 'computersonline.txt'
    $c=new-pssession -computername $computers
    
    icm -session $c{
            $mypwd = "encryptedpwd" | convertto-securestring -key (encryptionkey)
            $mycred = new-object system.management.automation.pscredential "cred",$mypwd
            function GetShortcuts{
                $shortcuts = get-childitem -recurse 'c:\users' -include *.lnk
                $Shell = New-Object -ComObject WScript.Shell
                $Link = @()
                new-psdrive X -PSProvider FileSystem -root "servershare" -Credential $mycred 
        
                     foreach ($shortcut in $shortcuts){
                        if($shell.createshortcut($shortcut).targetpath -eq 'target.exe'){
                        $link += [pscustomobject]@{
                            CompName = $env:computername
                            IconName = $shortcut.name
                            Location = $shortcut.fullname
                            Target = $shell.createshortcut($shortcut).targetpath
                            }
                        $link | export-csv -path "X:\shortcuts.csv" -NoTypeInformation -Append -NoClobber
                        }
                 
                    }
                remove-psdrive -name X
                 #   return $link
              }
          $output = GetShortcuts
       
        }
    
  • #114295

    Keymaster
    Points: 1,673
    Helping HandTeam Member
    Rank: Community Hero

    Close.

    
    $computers = get-content -path 'computersonline.txt'
    
    $c=new-pssession -computername $computers
    
     
    
    icm -session $c{
    
    $mypwd = "encryptedpwd" | convertto-securestring -key (encryptionkey)
    
    $mycred = new-object system.management.automation.pscredential "cred",$mypwd
    
    function GetShortcuts{
    
    $shortcuts = get-childitem -recurse 'c:\users' -include *.lnk
    
    $Shell = New-Object -ComObject WScript.Shell
    
    $Link = @()
    
    new-psdrive X -PSProvider FileSystem -root "servershare" -Credential $mycred
    
     
    
    foreach ($shortcut in $shortcuts){
    
    if($shell.createshortcut($shortcut).targetpath -eq 'target.exe'){
    
    $link = [pscustomobject]@{
    
    CompName = $env:computername
    
    IconName = $shortcut.name
    
    Location = $shortcut.fullname
    
    Target = $shell.createshortcut($shortcut).targetpath
    
    }
    
    Write-Output $link
    
    }
    
     
    
    }
    
    remove-psdrive -name X
    
    #   return $link
    
    }
    
    $output = GetShortcuts
    
     
    
    } | export-csv -path "X:\shortcuts.csv" -NoTypeInformation
    
    

    See, now the local computer is handling the CSV file. Notice that you don't accumulate results in $link as you were doing; you create one object, and output it to the pipeline (Write-Output). What you were doing before was going to result in a lot of duplicate output anyway.

    • #114348

      Participant
      Points: 0
      Rank: Member
      $computers = get-content -path 'c:\users\smip05\desktop\r5\computersonline.txt'
      $c=new-pssession -computername $computers
      
      icm -session $c{
              
              function GetShortcuts{
                  $shortcuts = get-childitem -recurse 'c:\users' -include *.lnk
                  $Shell = New-Object -ComObject WScript.Shell
                  $Link = @()
                          foreach ($shortcut in $shortcuts){
                          if($shell.createshortcut($shortcut).targetpath -eq '\\mdcoap100850\r5client\r5apps.exe'){
                          $link += [pscustomobject]@{
                              CompName = $env:computername
                              IconName = $shortcut.name
                              Location = $shortcut.fullname
                              Target = $shell.createshortcut($shortcut).targetpath
                              }
                          write-output $link
                          }
                   
                      }
                 
                  }
            $output = GetShortcuts
         
          } |export-csv -path 'c:\output\shortcuts.csv' -NoTypeInformation -append
      

      ok, so I've made the changes and this is where I am. It seems to run with no hitches however i'm getting a blank csv file. I have manually verified that at least 2 computers in the list i'm feeding it should be providing data, i.e. they have the shortcut specified. I removed all the creds and psdrive stuff because that was to make the machine able to talk back to mine which should be no longer needed as I am running the script as an elevated network account.

    • #114352

      Participant
      Points: 0
      Rank: Member

      I've also found with the code above that if I enter-pssession and run it piece by piece it works and when it write-output $link it performs as expected.  Would there be some reason that $link wouldn't get returned from the invoke-command?

      In addition, if I change write-output to write-host I get the results on my screen.  It seems that the write-output is just not doing what i would hope and sending the result down the pipeline

       

  • #114355

    Participant
    Points: 0
    Rank: Member

    I GOT IT!!!  I had to remove the $output=getshortcuts, it was sending me $output down the pipeline, not $link.  This is where I ended up:

     

    $computers = get-content -path 'c:\users\smip05\desktop\r5\computersonline.txt'
    $c=new-pssession -computername $computers
    
    icm -session $c {
            
            function GetShortcuts{
                $shortcuts = get-childitem -recurse 'c:\users' -include *.lnk
                $Shell = New-Object -ComObject WScript.Shell
                $Link = @()
                        foreach ($shortcut in $shortcuts){
                        if($shell.createshortcut($shortcut).targetpath -eq '\\mdcoap100850\r5client\r5apps.exe'){
                        $link += [pscustomobject]@{
                            CompName = $env:COMPUTERNAME
                            IconName = $shortcut.name
                            Location = $shortcut.fullname
                            Target = $shell.createshortcut($shortcut).targetpath
                            }
                         write-output $link 
                        }
                 
                  }
              
            }
          GetShortcuts
          
       
        } |export-csv -path 'c:\output\shortcuts.csv' -NoTypeInformation
    

    Thank you so much for your help!

You must be logged in to reply to this topic.