Getting Confirmations

I am experimenting with simple tasks on remote servers with the code below. It simply goes to a list of remote servers and creates a new folder:

"Server1", "Server2" | ForEach-Object {INVOKE-COMMAND -ComputerName $_ -ScriptBlock{
New-Item -ItemType directory -Path C:\webs\www\TestFolder}}

This works well enough. The results include the names of the folder being created, the servers where these folders are created and the data and time the folders are created.

I then use the code below to remove the folders I have just created.

"Server1", "Server2" | ForEach-Object {INVOKE-COMMAND -ComputerName $_ -ScriptBlock{Remove-Item -Path C:\webs\www\TestFolder}}

It completed the task but does not provide any sort of confirmation. While I understand that no news is good news, what if I want to get some sort of confirmation on screen so I can choose to write it into an output file if needed? How would I do that? I tried adding “-verbose” at the end but it made no difference.

My goal is read in a list of servers from a text file or csv file and perform some tasks (such as simply creating a new directory or something far more complicated). At the end of the process, I would like the results of the process to be written back to the input file so I would have something like this:

Server1 success

Server2 error

Server3 success

 

You must add the -Verbose parameter inside the script block.

For example:

"Server1", "Server2" | ForEach-Object {
    INVOKE-COMMAND -ComputerName $_ -ScriptBlock{
        Remove-Item -Path C:\webs\www\TestFolder -Verbose
    }
}

Use the built-in transcript cmdlets to trap what is going on as well as the -verbose switch the Luc addresses.

# get function / cmdlet details
(Get-Command -Name Start-Transcript).Parameters
Get-help -Name Start-Transcript -Examples
Get-help -Name Start-Transcript -Full
Get-help -Name Start-Transcript -Online


(Get-Command -Name Stop-Transcript).Parameters
Get-help -Name Stop-Transcript -Examples
Get-help -Name Stop-Transcript -Full
Get-help -Name Stop-Transcript -Online

This is what I have come up so far. It is reading from the CSV file correctly but not updating the Status column correctly. The CSV file only has two columns: ServerName and Status.

Import-Csv -Path "C:\Users\thchen\Desktop\ServerList.csv" | ForEach-Object {
INVOKE-COMMAND -ComputerName $_.ServerName -ScriptBlock {
Try {
New-Item -ItemType Directory -Path C:\webs\www\TedTest
$_.Status = "Success"}
Catch {
$_.Status = "Error"
}}}

Thanks Luc, I tried

-ScriptBlock{Remove-Item -Path C:\webs\www\TedTest -Verbose}}

And it gave me the correct feedback. But now I am wrestling with writing process status into a csv file.

And thanks postanote, I learned something new.

Ted, in the future I’d recommend using standard formatting approaches to your script.
Formatting makes code much easier to troubleshoot, especially when others need to read your code to attempt to help.

[pre]
Import-Csv -Path “C:\Users\thchen\Desktop\ServerList.csv” | ForEach-Object {
INVOKE-COMMAND -ComputerName $.ServerName -ScriptBlock {
Try
{
New-Item -ItemType Directory -Path C:\webs\www\TedTest
$
.Status = “Success”
}
Catch
{
$_.Status = “Error”
}
}
}
[/pre]

The code inside the script block is executed in a new PSSession and cannot update any object of the calling session.

That’s why $_.Status doesn’t mean anything inside the script block because you are refering to an object outside.

Here is a suggestion of code (though I didn’t test it…)

$ServerList = Import-Csv -Path 'C:\Users\thchen\Desktop\ServerList.csv'

$StatusList = [System.Collections.Generic.List[PSCustomObject]]::new()

foreach($Server in $ServerList){
    
    $Status = Invoke-Command -ComputerName $ServerList.ServerName -ScriptBlock {
        
        try{
            $Null = New-Item -ItemType Directory -Path 'C:\webs\www\TedTest' -ErrorAction Stop
            'Success'
        }
        catch{
            'Error'
        }
    }
    
    $StatusElement = [PSCustomObject]@{
        ServerName = $ServerList.ServerName
        Status = $Status
    }
    
    $StatusList.Add($StatusElement)
}

$StatusList | Export-Csv -Path 'C:\Users\thchen\Desktop\ServerListWithStatus.csv'

Thanks Luc.

I ran the code and this is what I get in the ServerListWithStatus.csv file.

#TYPE System.Management.Automation.PSCustomObject
ServerName Status
System.Object[] System.Object[]
System.Object[] System.Object[]
System.Object[] System.Object[]
So it looks like we are now on the right trace. I have three rows of data and the script is writing three rows of data. Thinking I need to convert the object back to string, I modified the last line of code to this
$StatusList.ToString() | Export-Csv -Path 'C:\Users\thchen\Desktop\ServerListWithStatus.csv'
And now I am getting this in the CSV file
#TYPE System.String
Length
72

Use -NoTypeInformation switch of Export-Csv cmdlet to get rid of type name in the CSV.

I think I may have found the answer to get rid of System.Object in csv files. Let me play around some more with the code. Thanks everyone.