If I get rid of the last line Out-File "HDDresults.txt" then the output shows on the screen in the correct format, just a long list of all the computers and their serial numbers. If I try to output to a file, each computer entry overwrites the previous entry, so when the script finishes executing there is only the last entry in the file. How do I get the file output to look exactly like the console output?
I don't know how to script. I just copied and pasted from multiple sources until I got something that works.
Import-Module ActiveDirectory
Get-ADComputer -filter * | Foreach-Object {
Get-WmiObject Win32_PhysicalMedia -computer $_.name |
Format-Table __server, Tag, SerialNumber |
Out-File "HDDresults.txt"
}
You simply need to set the -Append flag:
Out-File "HDDresults.txt" -Append
By default, Out-File overwrites the content of the file for each write operation. This will cause it to add text to the end of the file instead.
While adding the -Append argument makes the script function, I think a better fix to this is to move the Select statement and all that follows it outside of the ForEach loop so that the file is written once with all of the information once it is processed, and not having to open the file, write to it, close it, open it again, write to it, close it again, for each system.
Import-Module ActiveDirectory
Get-ADComputer -filter * |
Foreach-Object { Get-WmiObject Win32_PhysicalMedia -computer $_.name } |
Format-Table __server, Tag, SerialNumber |
Out-File "HDDresults.txt"
Related
I have an array and need to mapping a string inside a file by using the array then output the matched string to a file.
I tried it but when I found 2 match string in the file, in the output file only has 1 string.
$ArrayString = "Network controller TPX","Network controller SXCM", "Adapter controller CNA"
$GetFile = Get-Content .\File
foreach($string in $ArrayString ){
$GetFile | Select-String -Pattern $string | Out-File .\result.txt -Force
}
The content inside the file looks like this:
Network controller SXCM
Disable
*Enable
Admin Passwordfrom Startup Menu
*Disable
Enable
Adapter controller CNA
Disable
*Enable
Verify on every boot
*Disable
Enable
in some case the string in $ArrayString will matched 1 in the $Getfile and also matched 2 string.
Anyone can help me please. Thank you so much
The main issue with your code is that Out-File is inside the loop and without an -Append switch so each loop iteration is overwriting the file. Unfortunately, even if there is no match, the file would be overwritten due to the way Out-File was coded, seems like it opens the file stream in it's begin block which, shouldn't be the case and is one of many reasons why Set-Content should be the go to cmdlet when writing to a plain text file.
To explain the issue with Out-File visually:
# Create a temp file and write some content to it:
$file = New-TemporaryFile
'content' | Set-Content $file.FullName
Get-Content $file.FullName # => content
# `Process` block doesn't run on `AutomationNull.Value`,
# so, the expected would be, if nothing is received from pipeline,
# don't touch the file:
& { } | Set-Content $file.FullName
Get-Content $file.FullName # => 'content' // as expected
# Trying the same with `Out-File`
& { } | Out-File $file.FullName
Get-Content $file.FullName # => null // file was replaced
# dispose the file after testing...
$file | Remove-Item
A few considerations, Select-String can read files so Get-Content is not needed, and -Pattern can take an array of patterns to match. Here is the simplified version of your code.
$ArrayString = "Network controller TPX", "Network controller SXCM", "Adapter controller CNA"
Select-String -Path .\file.txt -Pattern $ArrayString |
ForEach-Object { $_.Matches.Value } | Set-Content result.txt
I have put together the below PowerShell script which scripts out all the USPs on a server.
Is there an option to split the output into individual files (instead of saving as one whole/large file)?
Get-ChildItem -Path SQLSERVER:\SQL\myserver\Default\Databases\mydb\StoredProcedures\ | %{$_.script() | out-file -Filepath "myfilelocation.sql"}
Try the following; it should append the procedure name to the file.
Get-ChildItem -Path SQLSERVER:\SQL\myserver\Default\Databases\mydb\StoredProcedures\ |
%{
#Deal with invalid chars in Procedure name i.e. [Customers\Remove]
$SProc = "$($_.name -replace '\\', '_')"
# $Sproc | Out-Host # Uncomment this to check the procedure names...
$_.script() |
out-file -Filepath "myfilelocation_$SProc.sql"
}
This should make the file name unique per database and not have the file over-written each time. That is what is currently happening with your script.
I have a script that examines a folder and finds the oldest file (by LastWrittenTime) and writes the found file's LastWriteTime to a log file.
If I run this script again I would like it to find the next oldest file, which has LastWriteTime greater than the one previously written to the log file.
But there is a problem. My scipt can find only the oldest file in the folder each time and ignores the one in the log file.
My script:
$programdir = "C:\Data\PowerShell\Learning"
$folder = "C:\Data\PowerShell\Learning\folder" #there is the files
$TimeLog = "$programdir\LastFileDate.log" #this file contains the last found file's LastWriteTime attribute
$LastWriteTime = Get-Content $TimeLog
$File = Get-ChildItem -Path $folder | Sort-Object LastWriteTime -Descending | Select-Object -Last 1 | Where-Object {$_.LastWriteTime -gt $LastWriteTime}
Clear-Content $TimeLog
$File.LastWriteTime | Set-Content $TimeLog
You immediately cripple your selection set with this line. Specifically where you have Select-Object -Last 1:
$File = Get-ChildItem -Path $folder | Sort-Object LastWriteTime -Descending | Select-Object -Last 1 | Where-Object {$_.LastWriteTime -gt $LastWriteTime}
In the second last pipe statement you limit your selection set to 1 file. Then afterwards you apply your date logic. You need to filter on your dates first then grab the appropriate entry.
Get-ChildItem -Path $folder -File |
Sort-Object LastWriteTime -Descending |
Where-Object {$_.LastWriteTime -lt $LastWriteTime} |
Select-Object -First 1
There are other similar approaches that would work as well.
Also...
Clear-Content $TimeLog
$File.LastWriteTime | Set-Content $TimeLog
That is redundant since Set-Content will overwrite by default. You can remove the Clear-Content.
While this is not an issue in your code be aware that $LastWriteTime, as returned by Get-Content, is a string and not a datetime object. Since it is on the RHS of the statement in your where clause is cast as a [datetime] for the purpose of evaluating the clause.
Also be careful that your code could act differently if there is more than one line in your $timelog
I am running to an issue with a Powershell command line I'm attempting to run. What we are needing is to get the PC Name and LastLogonDate from PC's in a list of text files with Powershell.
Here is the code I'm attempting to run:
Get-Content C:\Hosts.txt | ForEach-Object{Get-ADComputer $_ -Properties Name,LastLogonDate | Select-Object Name,LastLogonDate | Export-Csv C:\Output.csv}
When I run that code I get an error stating: "Cannot find a object with identity: 'ComputerName'" despite the fact that the PC is truly in AD. What is confusing me is that everything after the ForEach-Object runs great if you run it by itself. When you add the Get-Content and ForEach-Object the errors begin. I can see from the error messages that each individual computer name is being read from the text file, but I wonder if it is passing it in a way the Get-ADComputer doesn't like.
A couple things. First is to see what's in the hosts.txt file. Second thing is to move the Export-Csv command outside of the ForEach-Object statement. If you leave it how it is, it will only return the last object it processed in the csv file. I've posted an example of how it should be.
Get-Content C:\Hosts.txt | ForEach-Object {Get-ADComputer $_ -Properties Name,LastLogonDate | Select-Object Name,LastLogonDate} | Export-Csv C:\Output.csv
I'm not able to replicate your problem and the only thing different is the contents of the hosts.txt file so it would be helpful to see it.
I hope someone can help me. I am pretty new to PowerShell and can't really script it myself with the exception of looking at existing code and modifying it.
I have found a PowerShell script that reports file share permissions for a specific share and recurses through the subfolders returning their permissions as well.
My problem is I need to do this with a lot of shares so would like to be able to provide the script with a text file containing the share names. I know I need to do a for each loop and read the names of the shares in a text file into an array but I don't know how to do this. I guess it's pretty simple for someone with more experience.
This is the script i have used with single entry.
http://mywinsysadm.wordpress.com/2011/08/17/powershell-reporting-ntfs-permissions-of-windows-file-shares/
#Set variables
$path = Read-Host "Enter the path you wish to check"
$filename = Read-Host "Enter Output File Name"
$date = Get-Date
#Place Headers on out-put file
$list = "Permissions for directories in: $Path"
$list | format-table | Out-File "C:\scripts\$filename"
$datelist = "Report Run Time: $date"
$datelist | format-table | Out-File -append "C:\scripts\$filename"
$spacelist = " "
$spacelist | format-table | Out-File -append "C:\scripts\$filename"
#Populate Folders & Files Array
[Array] $files = Get-ChildItem -path $path -force -recurse
#Process data in array
ForEach ($file in [Array] $files)
{
#Convert Powershell Provider Folder Path to standard folder path
$PSPath = (Convert-Path $file.pspath)
$list = ("Path: $PSPath")
$list | format-table | Out-File -append "C:\scripts\$filename"
Get-Acl -path $PSPath | Format-List -property AccessToString | Out-File -append "C:\scripts\$filename"
} #end ForEach
Sorry for the noob question. I plan to learn more when I have a bit more time but any help now would be massively appreciated.
Thanks in advance.
If you have a share name on each line within your text file can put all the shares into an array like this:
$path = "C:\ShareNames.txt"
$shareArray = gc $path
To access the first share you can use this syntax:
$shareArray[0]