Out-File not working with Invoke-Command

Welcome Forums General PowerShell Q&A Out-File not working with Invoke-Command

This topic contains 10 replies, has 4 voices, and was last updated by

 
Moderator
2 years, 2 months ago.

  • Author
    Posts
  • #54269

    Participant
    Points: 0
    Rank: Member

    I have the following ScriptBlock:

    $ScriptBlock =  { ForEach($WebSite in $(get-website))
                {
                    $ReportFile = "\\FileShare\WebLogs\FreeSpaceReport.csv"
                    $LogLocation="$($Website.logFile.directory)\w3svc$($website.id)".replace("%SystemDrive%",$env:SystemDrive)
                    $LogDrive = (get-item $LogLocation).psdrive.name
                    $LogDriveFreeSpace = (get-psdrive $LogDrive).free/1gb
                    $LogDriveFreeSpace = "{0:N2}" -f $LogDriveFreeSpace
                    $Output = "$server $($WebSite.name) [$LogLocation] $LogDriveFreeSpace"
                    $Output | Out-File $ReportFile -append
                }
    
                }

    When I run this directly from $server, $ReportFile gets generated correctly.

    However, when I run:

    Invoke-Command -ComputerName $server  -ScriptBlock {$ScriptBlock}

    , from a different server the report file does not get generated.

    I tried replacing $ScriptBlock with just "get-website," and this works, so I know I can invoke commands remotely.

    I thought this might be a credential issue (on the file share) or double-hop issue, so I tried:

    Invoke-Command -ComputerName $server  -ScriptBlock {$ScriptBlock} -Authentication CredSSP -Credential $Credential

    , but this doesn't generate $ReportFile either.

    Any ideas why $ReportFile isn't getting created when using Invoke-Command to run $ScriptBlock on a remote system?

  • #54270

    Participant
    Points: 21
    Rank: Member

    Put your get-website function in the scriptblock

  • #54271

    Participant
    Points: 0
    Rank: Member

    I don't follow. It's already in the scriptblock?

  • #54273

    Participant
    Points: 316
    Helping Hand
    Rank: Contributor

    Where does the Get-Website function reside? Is it available on the remote machine? Dan is saying that you need to place the function to be accessible in the scriptblock to ensure it's available in the remote call session:

    $ScriptBlock =  { 
        function Get-WebSite {
            #function code
        }
    
        ForEach($WebSite in $(get-website)) {
            $ReportFile = "\\FileShare\WebLogs\FreeSpaceReport.csv"
            $LogLocation="$($Website.logFile.directory)\w3svc$($website.id)".replace("%SystemDrive%",$env:SystemDrive)
            $LogDrive = (get-item $LogLocation).psdrive.name
            $LogDriveFreeSpace = (get-psdrive $LogDrive).free/1gb
            $LogDriveFreeSpace = "{0:N2}" -f $LogDriveFreeSpace
            $Output = "$server $($WebSite.name) [$LogLocation] $LogDriveFreeSpace"
            $Output | Out-File $ReportFile -append
        }
    }
    
  • #54274

    Moderator
    Points: 24
    Team Member
    Rank: Member

    I still think you're facing a double-hop problem because CredSSP needs to be properly enabled on the client and server to work and it is unsafe in my opinion because your credentials will be cached on the remote server for quite some time.

    I wouldn't attempt to write to a share from a remote server. My approach as outlined in below example is to gather all the required information from the remote sessions through objects being returned and process them in the session and on the machine that invoked the remote commands.

    $Servers = @( 'Server1', 'Server2' )
    $ReportFile = '\\FileShare\WebLogs\FreeSpaceReport.csv'
    
    $ScriptBlock =  
    {
        Import-Module -Name WebAdministration -Force -ErrorAction Stop
        
        foreach ($Website in $(Get-Website))
        {
            $LogLocation = "$($Website.LogFile.Directory)\w3svc$($Website.Id)".Replace('%SystemDrive%', $env:SystemDrive)
            $LogDrive = (Get-Item $LogLocation).PSDrive.Name
            $LogDriveFreeSpace = '{0:N2}' -f ((Get-PSDrive $LogDrive).Free / 1gb)
    
            [PSCustomObject]@{
                ComputerName = $env:COMPUTERNAME
                SiteName = $Website.Name
                LogLocation = $LogLocation
                LogDriveFreeSpace = $LogDriveFreeSpace
            }
        }
    }
    
    $Results = Invoke-Command -ComputerName $Servers -ScriptBlock $ScriptBlock
    
    $Results | Select-Object -Property ComputerName, SiteName, LogLocation, LogDriveFreeSpace |
        Out-File $ReportFile -Append
    
    • #54328

      Participant
      Points: 0
      Rank: Member

      Daniel,

      Does this line

      $Results = Invoke-Command -ComputerName $Servers -ScriptBlock $ScriptBlock

      execute the ScriptBlock on all of the servers in $Servers simultaneously, or does it loop through them one at a time?

  • #54276

    Participant
    Points: 21
    Rank: Member

    =D get-website certainly sounds like a user defined function. Good catch.

  • #54277

    Moderator
    Points: 24
    Team Member
    Rank: Member

    I don't believe that Get-Website is a user-defined function because the WebAdministration PowerShell module installed on every web server exports this function.

    https://technet.microsoft.com/library/ee807832.aspx

  • #54278

    Participant
    Points: 21
    Rank: Member

    I was saying it sounded like one, I didn't even think to look it up=D

  • #54325

    Participant
    Points: 0
    Rank: Member

    Nice catch guys...I did indeed need to define the Get-Website function inside the scriptblock.

    Worked by adding "Import-Module -Name WebAdministration -Force -ErrorAction Stop."

    Thank you!

  • #54376

    Moderator
    Points: 24
    Team Member
    Rank: Member

    Yes, Invoke-Command will execute the script block concurrently. The default limit is 32 but you can reduce or increase it with the -ThrottleLimit parameter. You can provide thousands of computer names and Invoke-Command will loop through them for you.

    Check out the description of the ThrottleLimit parameter in the official documentation of the command.
    https://technet.microsoft.com/en-us/library/hh849719.aspx

The topic ‘Out-File not working with Invoke-Command’ is closed to new replies.