This question already has answers here:
Export-Csv emits Length and not values
(2 answers)
Closed 5 years ago.
When I run the code below the data I get in the csv doesn't have the server names I'm expecting.
Instead this is what I get in the .csv file
Length
204
Why is this?
$varoutfile = "\\unc_path\server $(get-date -f yyyy-MM).csv"
$varDOW = (get-date).DayOfWeek
$varservertoreboot = "server1" , "server2" , "server1" ,
if ($varDOW -eq "Sunday") {
foreach ($server in $varservertoreboot) {
Restart-Computer $varservertoreboot -Force
"$(get-date -f yyyy-MM-dd-HH-mm-ss) Today is $vardow, The system
$varservertoreboot is rebooting" | Export-Csv $varoutfile -Append -NoClobber -NoTypeInformation
}
}
else {}
if ($varDOW -eq "Wednesday") {
foreach ($server in $varservertoreboot) {
Restart-Computer $varservertoreboot -Force
"$(get-date -f yyyy-MM-dd-HH-mm-ss) Today is $vardow, The system $varservertoreboot is rebooting" | Export-Csv $varoutfile -Append -NoClobber
}
}
I'd replace:
"$varservertoreboot is rebooting" | Export-Csv $varoutfile -Append -NoClobber -NoTypeInformation
"$(get-date -f yyyy-MM-dd-HH-mm-ss) Today is $vardow, The system $varservertoreboot is rebooting" | Export-Csv $varoutfile
With:
Add-Content -Value "$varservertoreboot is rebooting" -Path $varoutfile
Add-Content -Value "$(get-date -f yyyy-MM-dd-HH-mm-ss) Today is $vardow, The system $varservertoreboot is rebooting" -Path $varoutfile
Related
This question already has an answer here:
Parameter interpretation when running jobs
(1 answer)
Closed 3 years ago.
I have a running PS1-script (start-webserver.ps1) running as a "web server" that is listening for http calls that executes a script (example: script2.ps1) executed in the call to the "web server".
I am executing the script with Start-Job. How can I in the executed script (script2.ps1) access variables in start-webserver.ps1?
Start-WebServer.ps1
$allObjects = #()
foreach ($item in $items) {
$objectUID = $item.Attributes.Value
$propertiesHash = [ordered]#{UID = $objectUID}
$properties = $items.ChildNodes
foreach ($property in $properties.ChildNodes) {
$propertyName = $property.Attributes.Value
$propertyValue = $property.innerText
$propertiesHash.Add($propertyName, $propertyValue)
}
$object = New-Object PSObject -Property $propertiesHash
$allObjects += $object
}
$job = Start-Job -Name "$identifier" -FilePath "Path\To\ScriptToExecute.ps1" -InputObject $allObjects -ArgumentList $propertiesHash
ScriptToExecute.ps1
'Script executed!' | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$propertiesHash | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$allObjects | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
I end up with an "output.txt" with the following content:
Script executed!
Empty line
You need to define in ScriptToExecute that you are receiving params
By default it is set in the $args variable.
In your case, simply using $args[0] will be sufficient.
i.e.:
'Script executed!' | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$args[0] | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
If you want to also receive $allObjects, you need to modify Start-WebServer to this:
$job = Start-Job -Name "$identifier" -FilePath "Path\To\ScriptToExecute.ps1" -InputObject $allObjects -ArgumentList #($propertiesHash,$allObjects)
then do this:
'Script executed!' | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$args[0] | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$args[1] | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
Nicer way of doing this is to specify the param in ScriptToExecute
i.e.:
param($propertiesHash, $allObjects)
'Script executed!' | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$propertiesHash | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
$allObjects | Get-Member | Out-File -Path ".\output.txt" -Encoding UTF8 -Append
I currently have a CSV file that has 2,440 lines of data. The data looks something like:
server1:NT:Y:N:N:00:N
server2:NT:Y:N:n:33:N
This is what I have so far:
$newCsvPath = Get-Content .\sever.csv |
Where-Object { $_ -notmatch '^#|^$|^"#' }
[int]$windows = 0
[int]$totalsever = 0
$Results = #()
$date = Get-Date -Format g
Clear-Content .\results.csv -Force
foreach ($thing in $newCsvPath) {
$totalsever++
$split = $thing -split ":"
if ($split[1] -contains "NT") {
$windows++
$thing | Out-File results.csv -Append -Force
} else {
continue
}
}
Clear-Content .\real.csv -Force
$servers = Get-Content results.csv
foreach ($server in $servers) {
$server.Split(':')[0] | Out-File real.csv -Append -Force
}
My issue is that when the script gets to the $server.Split(':')[0] | Out-File real.csv -Append -Force part, for some reason it only outputs 1,264 lines instead of all 2,440 to "real.csv". However, when I remove | Out-File real.csv -Append -Force, $server stores ALL 2,400 names of servers.
Does anyone have any idea of why this is happening?
I am new to PowerShell and I get a lot done using this forum along with other internet searched answers but this one is getting the better of me. I have a script that compares two folders and the part where I'm having problems I cannot get the BitsTransfer source to work. $Differences identifies files from the source folder that are not in the target folder by modified date. I want the BitsTransfer to move the files identified by $Differences but I'm not having any luck getting that behavior. The operation works when I use "Copy-Item -Path $Differences -Destination $Local –Force" instead but i want the progress bar BitsTransfer Uses. The code i am using is as follows
$Local = 'c:\test\local\'
$Remote = 'c:\test\server\'
$Target = Get-ChildItem -Path $Local -File
$Source = Get-ChildItem -Path $Remote -File
Import-Module BitsTransfer
Set-Location $Remote
filter timestamp {"$(Get-Date -Format g): $_"}
if ($Target -eq $null) {
$bitsjob = Start-BitsTransfer -Source $Remote\*.* -Destination $Local
Write-Output "$Local Folder Empty" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Rename-Item -Path "D:\Mitek\DCS Stuff\Display PC Scripts\test\RemoteComplete.bat" -NewName "Remote.bat"
Exit
} Else {
if ($Target -ne $null){
Compare-Object $Source $Target -Property Name -PassThru | Where-Object {$_.SideIndicator -eq "=>"} | % {
if(-not $_.FullName.PSIsContainer) {
Write-Output "Removed From $Local" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue}}}}
$Differences = Compare-Object -ReferenceObject $Source -DifferenceObject $Target -Property LastWriteTime -PassThru
$Differences | Group-Object Name | Select -ExpandProperty Group | Sort-Object LastWriteTime | Select-Object -Last 1
if ($Differences -ne $null) {
foreach ($file in $Differences) {
#Copy-Item -Path $Differences -Destination $Local –Force
Start-BitsTransfer -Source $Differences -Destination $Local
Write-Output "Copied to $Local" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Rename-Item -Path "D:\Mitek\DCS Stuff\Display PC Scripts\test\RemoteComplete.bat" -NewName "Remote.bat"}
} Else {
Write-Output "$Local and $Remote are Equal" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"}`
I got the issue figured out with some looping behavior the code used to resolve the issue is bellow for those who may find this helpful in the future...
$Local = 'C:\test\local\'
$Remote = 'C:\test\server\'
$Target = Get-ChildItem -Path $Local -File
$Source = Get-ChildItem -Path $Remote -File
$One = 1
Set-Location $Remote
filter timestamp {"$(Get-Date -Format g): $_"}
if ($Target -eq $null) {
$TotalA = $Source | Measure | Select-Object -ExpandProperty Count
echo "Total Number of Files to be Copied= $TotalA"
echo "---------------------------------------------------------------"
Write-Output "$Local Folder Empty" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Start-BitsTransfer -Source $Remote\*.* -Destination $Local -Description "Copying $TotalA Files"
Rename-Item -Path "C:\test\RemoteComplete.bat" -NewName "Remote.bat"
exit
} Else {
if ($Target -ne $null){
Compare-Object $Source $Target -Property Name -PassThru | Where-Object {$_.SideIndicator -eq "=>"} | % {
if(-not $_.FullName.PSIsContainer) {
Write-Output "Removed From $Local" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue}}}}
$Differences = Compare-Object -ReferenceObject $Source -DifferenceObject $Target -Property LastWriteTime -PassThru
if ($Differences -ne $null) {
$TotalB=$Differences | Group-Object Name | Select -ExpandProperty Group | Sort-Object Name | Measure | Select-Object -ExpandProperty Count
echo "Total Number of Files to be Copied= $TotalB"
Write-Output "Copied to $Local" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"
do {
$Tar = Get-ChildItem -Path $Local -File
$Src = Get-ChildItem -Path $Remote -File
$Diffs = Compare-Object -ReferenceObject $Src -DifferenceObject $Tar -Property LastWriteTime -PassThru
$ListB=$Diffs | Group-Object Name | Select -ExpandProperty Group | Sort-Object Name | Select-Object -First 1
if ($ListB -ne $null) {
echo "---------------------------------------------------------------"
$Rmn=$Diffs | Group-Object Name | Select -ExpandProperty Group | Sort-Object Name | Measure | Select-Object -ExpandProperty Count
$RemainB = $Rmn - $One
Start-BitsTransfer -Source $ListB -Destination $Local -Description "$RemainB Files Remain Copying - $List" }}
Until ($ListB -eq $null)
Rename-Item -Path "C:\test\RemoteComplete.bat" -NewName "Remote.bat"
} Else {
Write-Output "$Local and $Remote are Equal" | timestamp | Out-File -Encoding Ascii -append "D:\Mitek\DCS Stuff\Display PC Scripts\test\log.txt"}
The InstallDate property used in the below code -
$InstalledProgram | Select-Object DisplayName, DisplayVersion, Publisher,
InstallDate | Format-Table –AutoSize
$logDisplayName = $InstalledProgram.DisplayName
$logPublisher = $InstalledProgram.Publisher
$logVersion = $InstalledProgram.DisplayVersion
$logInstallDate= $InstalledProgram.InstallDate
It displays the date of an installed application in this format 20170921 but i want it to be displayed in 21/09/2017 i.e DD/MM/YYYY format. How can i format it?
Below is the Entire Code which is used to copy the output to log file:-
Clear-Host
$scriptPath = $PSScriptRoot
$logFilePath= Join-path $scriptPath "POCTestResults.log"
# If log file exists, then clear its contents
if (Test-Path $logFilePath)
{
clear-content -Path $logFilePath
}
# It displays the date and time of execution of powershell script in log file.
$log = "Date Of Testing: {0} " -f (Get-Date)
$logString = "Process Started."
add-content -Path $logFilePath -Value $log -Force
add-content -Path $logFilePath -Value $logString -Force
add-content -Path $logFilePath -Value "`n" -Force
# Validate ADD/Remove Program list
# FUNCTION DEFINITIONS
function Log-InstalledProgram($InstalledProgram, $LogFilePath)
{
#$InstalledProgram | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate |
#Format-Table –AutoSize
$InstalledProgram | Select-Object DisplayName, DisplayVersion, Publisher, #{Name="InstallDate"; Expression={([datetime]::ParseExact($_.InstallDate, 'yyyyMMdd', $null)).toshortdatestring()}} | Format-Table –AutoSize
$logDisplayName = $InstalledProgram.DisplayName
$logPublisher = $InstalledProgram.Publisher
$logVersion = $InstalledProgram.DisplayVersion
$logInstallDate= $InstalledProgram.InstallDate
add-content -Path $LogFilePath -Value "Product Name: $logDisplayName" -Force
add-content -Path $LogFilePath -Value "Publisher: $logPublisher" -Force
add-content -Path $LogFilePath -Value "Version: $logVersion" -Force
add-content -Path $LogFilePath -Value "InstallDate: $logInstallDate" -Force
add-content -Path $LogFilePath -Value "`n" -Force
}
add-content -Path $logFilePath -Value "`n" -Force
add-content -Path $logFilePath -Value "Add/Remove Programs :" -Force
add-content -Path $logFilePath -Value "`n" -Force
$InstalledPrograms = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
foreach ($InstalledProgram in $InstalledPrograms )
{
foreach ($displayName in "IntelliMatch Operational Control","intelliSuite Management Studio", "SunGard System Analyzer", "STeP")
{
if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains($displayName)))
{
Log-InstalledProgram $InstalledProgram $logFilePath
}
}
}
This is script i have used.
Use [datetime]::ParseExact() method and calculated properties to retrieve a datetime format in the Select-Object and format it in a short date string with .toshortdatestring() :
$InstalledProgram | Select-Object DisplayName, DisplayVersion, Publisher, #{Name="InstallDate"; Expression={([datetime]::ParseExact($_.InstallDate, 'yyyyMMdd', $null)).toshortdatestring()}} | Format-Table –AutoSize
$logDisplayName = $InstalledProgram.DisplayName
$logPublisher = $InstalledProgram.Publisher
$logVersion = $InstalledProgram.DisplayVersion
$logInstallDate= $InstalledProgram.InstallDate
I'm fairly new to Powershell but manged so far to pull together a script that deletes files older than a defined Created Date and excluding certain file types. However, I'm struggling to incorporate both verbose and file logging output. I've tried various methods I've found online and I think Out-File is the most appropriate however I simply can't make it work. Hoping someone can help!
Set-StrictMode -Version Latest
# $Logfile = "C:\Temp\Log.log"
function Remove-Files([parameter(Mandatory=$true)][ValidateScript({Test-Path $_})][string] $Path, [parameter(Mandatory=$true)][DateTime] $DateTime, [switch] $WhatIf)
{
Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $DateTime -and ($_.Name -notlike "*.txt"-and $_.Name -notlike "*.log")} |
# Out-File -filepath $logfile -append
ForEach-Object { Remove-Item -Path $_.FullName -Force -WhatIf:$WhatIf}
}
Remove-Files -Path "C:\Temp" -DateTime ((Get-Date).AddDays(-10)) # -whatif
You are not sending any content to the log file.
Uncomment the $logfile declaration, and use this for instance:
ForEach-Object {
Remove-Item -Path $_.FullName -Force -WhatIf:$WhatIf
"Removed $($_.FullName)" | Out-File -FilePath $logfile -Append
}
What you want to do is just Tee-Object the files before you remove them. Like, literally just replace your Out-File with Tee-Object:
function Remove-Files {
[CmdletBinding()]
param(
[parameter(Mandatory=$true)]
[ValidateScript({Test-Path $_})]
[string]$Path,
[parameter(Mandatory=$true)]
[DateTime]$DateTime,
# Personally, I would pass the log file as a parameter
# [string]$LogFile,
[switch]$WhatIf
)
Get-ChildItem -Path $Path -Recurse -Force |
Where-Object {
!$_.PSIsContainer -and
$_.CreationTime -lt $DateTime -and
($_.lName -notlike "*.txt" -and $_.Name -notlike "*.log")
} |
Tee-Object -Filepath $LogFile -Append |
Remove-Item -Force -WhatIf:$WhatIf
}
Remove-Files -Path "C:\Temp" -Log "C:\Temp\Rm.log" -DateTime ((Get-Date).AddDays(-10))
The only problem is that:
The output in the log would be formatted the same as if you output to the console, so it's not quite what you'd normally log ...
The log will be the same whether you remove or not (i.e.: -Whatif makes it not delete, but doesn't stop the log)
Here's my updated code to get the logging working..
function Remove-FilesCreatedBeforeDate([parameter(Mandatory=$true)][ValidateScript({Test-Path $_})][string] $Path, [parameter(Mandatory=$true)][DateTime] $DateTime, [string]$LogFile = "C:\Temp\Log.log", [switch] $WhatIf)
{
"LOG START $(Get-Date –f "yyyy-MM-dd HH:mm:ss")" | Out-File -FilePath $logfile -Append
Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $DateTime -and ($_.Name -notlike "*.txt"-and $_.Name -notlike "*.log")} |
ForEach-Object { Remove-Item -Path $_.FullName -Force -WhatIf:$WhatIf
"$(Get-Date –f o) Removed $($_.FullName)" | Out-File -FilePath $logfile -Append | Write-host "Removed $($_.FullName)"}
"LOG END $(Get-Date –f "yyyy-MM-dd HH:mm:ss")" | Out-File -FilePath $logfile -Append
}
Remove-FilesCreatedBeforeDate -Path "C:\Temp" -DateTime ((Get-Date).AddDays(-0))
A while ago I have created a Log-Entry framework where you can do inline logging like:
Remove-Item -Path (Log "Removing:" $_.FullName ?) -Force -WhatIf:$WhatIf