Help with Get-Item script

Hello,

I’ve been testing with the Get-Item command locally to retrieve the last modified date of a particular file for example Get-Item " C:\Logs\system.log" It gives me the LastWriteTime.

Now the tricky part, I need to use this information from multiple remote machines. I was hoping to use a text file to reference the names/IPs of the remote computers and produce a CSV showing:

IP/Name, Last Modified Date, Days since last updated

I have the username and password for each machine which I can add to the script (encrypted), but has anyone tried this before?

I imagine the start would be something like

$servers = Get-Content -Path C:\Scripts\Allservers.txt
$Result = ForEach ($server in $servers) 
           { invoke-command -computername $server {Get-Item " C:\Logs\system.log }}

Any help would be most appreciated

Thanks

Hi Turrican, welcome to the forum! :wave:

I am not trying to be mean here, but is this a real question? It seems like you are well past that since you mention encrypting username/password and it’s obvious you at least know the command to run scripts on remote machines. I assure you that since powershell has been out (17 years now) that at least a few people have tried something similar before. :wink:

So if you would be so kind as to let us know what kind of help you need with this. Have you tried running it? If so, did you get errors? Are you having issues getting the exact output you desire? Help us help you!

You should always read the entire help for any commands you are trying to use, including the examples. There are also many examples online including in this very forum.

I look forward to being able to assist you.

1 Like

I’m not at work now, I’ll try digging deeper on Monday when I’m in the office. I should be able to run this locally on a machine, but I’ve yet to work out how to use a text file as a source and then connect to a remote set of machines. Don’t worry I’ll persevere and crack this, I’ll Google around for some examples again. Thanks.

A few tips.

  1. If you treat the file as a CSV, you won’t get burned by errant white space at the beginning or end of a line.
  2. Invoke-Command takes a list of computer names and runs them concurrently (32 max by default) where putting Invoke-Command inside a loop will run them one at a time.
  3. You can also create powershell sessions and use those for Invoke-Command (benefit of knowing/running against online systems vs shooting blindly)

I have faith in you! Read the help (Get-Help some-command -Online/Detailed/Full) and look at examples. If you get stuck or have a specific question, we are here and willing to help.

2 Likes

Thanks for the tips, I will read up on those, I’ll try something like this where it uses a text file with the DNS/IPs in it and also some error handling if a machine in the list is down. It will prompt for a username and password, I’ll need to factor that in:

Set-ExecutionPolicy Unrestricted -Force
$ServerName = Get-Content "D:\Win10list\Servers.txt"
$Output = foreach ($Server in $ServerName) {

    if (Test-Connection -ComputerName $server -Count 1 -Quiet)
{
    Get-ChildItem -ComputerName $Server 'D:\temp\test.log' -ErrorAction SilentlyContinue
}
}
$Output | out-file D:\Output.csv

Made some progress running on a local machine with this:

Set-ExecutionPolicy Unrestricted -Force
$ServerName = Get-Content "c:\temp\Servers.txt"
$Output = foreach ($Server in $ServerName) {

    if (Test-Connection -ComputerName $server -Count 1 -Quiet)
{
    Get-ChildItem -Path "\\$Server\c$\temp\test.txt" -ErrorAction SilentlyContinue
}
}
$Output | out-file c:\temp\Output.csv

However I’d like the output to looklike:

servername1, date modified
servername2, date modified

Instead. I get:

Directory: \\servername1\c$\temp

Mode LastWriteTime Length Name


-a---- 31/07/2023 11:26 27 test.txt

Directory: \\servername2\c$\temp

Mode LastWriteTime Length Name


-a---- 31/07/2023 11:26 27 test.txt

How can I get it formatted in that simpler way?

EDIT - I think I need to change the output to Export-CSV and look into pipelines

That does not make any sense inside a script!! :point_up_2:t3: :smirk:

$ComputerNameList = Get-Content 'c:\temp\Servers.txt'
$Output = 
foreach ($ComputerName in $ComputerNameList) {
    if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet) {
        Invoke-Command -ComputerName $ComputerName -ScriptBlock {
            Get-ChildItem -Path 'c:\temp\test.txt' -ErrorAction SilentlyContinue
        } |
            Select-Object -Property PSComputerName, LastWriteTime
    }
}
$Output | 
    Export-Csv -Path 'c:\temp\Output.csv' -NoTypeInformation

Oops I forgot to remove that, thanks.

So that works thanks. To connect to a remote server I’ve had to add the creds pop up box to enter my creds to access that remote server. I guess I can add the username to the script and password to a file?

$ComputerNameList = Get-Content 'c:\temp\Servers.txt'
$creds = Get-Credential
$Output = 
foreach ($ComputerName in $ComputerNameList) {
    if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet) {
        Invoke-Command -ComputerName $ComputerName -Credential $creds -ScriptBlock {
            Get-ChildItem -Path 'c:\temp\test.txt' -ErrorAction SilentlyContinue
        } |
            Select-Object -Property PSComputerName, LastWriteTime, Name
    }
}
$Output | 
    Export-Csv -Path 'c:\temp\Output2.csv' -NoTypeInformation

If I can get that to work I can look to encrypt the password as I have found an article.

When I did try and run the script though it moaned:

[10.17.15.23] Connecting to remote server 10.17.15.23 failed with the following error message : The WinRM client cannot process the request. Default authentication may be used with an
IP address under the following conditions: the transport is HTTPS or the destination is in the TrustedHosts list, and explicit credentials are provided. Use winrm.cmd to configure
TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated

To fix I had to add the IP doing this, thing is I have many IPs to add that will go in the ‘servers.txt’ file any way round this?

set-item wsman:\localhost\client\trustedhosts -Concatenate -value '10.17.15.23'

Thanks

If you want to add all hosts, you can use:

Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*'

1 Like

If you want to leverage the Windows Credential manager there is a good module available called ‘CredentialManager’

Install-Module -Name CredentialManager

The best way around this would be to use the names of the remote servers in an AD domain network where you are admin on all remote servers already. When you run the script with this admin account you don’t have to mess with credentials at all. :man_shrugging:t3:

The second best way around would be to run the script with the proper account.

Unfortunately the server I need to run this from is on a Domain, but these Windows devices are not (long story). They all have an a local account that I can use though.

How can I run the script with that account though, can it be embedded into the script?

I’d have to run this as a scheduled task on the server. I’m noticed I need to open TCP 5985 for WinRm to work too.

Since they are not domain joined systems you will need to use HTTPS to connect as well as configure your trusted hosts. Detailed here pretty well. Remoting Week: Non-Domain Remoting - Scripting Blog

1 Like

Thanks for this. I’ve got to get the port open. I’ve added the password to an encrypted txt for now, but I still get the windows username and pop up box show, what do I need to remove to stop that prompt and use the username and password in the file instead?

$user = 'testuser'
$file = 'C:\temp\pwd.txt'
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, (Get-Content $file | ConvertTo-SecureString)
$ComputerNameList = Get-Content 'c:\temp\devices.txt'$credentials = Get-Credential
$Output = 
foreach ($ComputerName in $ComputerNameList) {
    if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet) {
        Invoke-Command -ComputerName $ComputerName -Credential $credentials -ScriptBlock {
            Get-ChildItem -Path '\\$ComputerName\c$\ProgramData\data.xml' -ErrorAction SilentlyContinue
        } |
            Select-Object -Property PSComputerName, LastWriteTime, Name
    }
}
$Output | 
    Export-Csv -Path 'c:\temp\dataxml.csv' -NoTypeInformation

This line seems wrong. I’d remove the “$credentials” part … :wink:

1 Like

Doh I’ll check that. I think the more I look at a script the harder it is to see a mistake :smiley: