Powershell - Output to screen AND logfile - powershell

I am trying to write ALL the output to a logfile, and I seem to be doing something wrong. I also need the output on the screen.
Here is what I have so far:
# Log file time stamp:
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
# Log file name:
$LogFile = "EXPORTLOG_"+$LogTime+".log"
$database = "DB"
$schema = "dbo"
$table = "TableName"
foreach($line in Get-Content .\Alltables.txt) {
if($line -match $regex){
$bcp = "bcp $($database).$($schema).$($line) out $line.dat -T -c"
Invoke-Expression $bcp | Out-File $LogFile -Append -Force
}
}
When I want to write out the command to the logfile so I know which table is processed, I get an error:
Here is the code:
# Log file time stamp:
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
# Log file name:
$LogFile = "EXPORTLOG_"+$LogTime+".log"
$database = "DB"
$schema = "dbo"
$table = "TableName"
foreach($line in Get-Content .\Alltables.txt) {
if($line -match $regex){
$bcp = "bcp $($database).$($schema).$($line) out $line.dat -T -c" | Out-File $LogFile -Append -Force
Invoke-Expression $bcp | Out-File $LogFile -Append -Force
}
}
And the error:
Invoke-Expression : Cannot bind argument to parameter 'Command' because it is null.
At C:\Temp\AFLAC\export.ps1:16 char:21
+ Invoke-Expression $bcp | Out-File $LogFile -Append -Force
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-Expression], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand
I am obviously not very good with Powershell and I please need your advise on how I should code this the best possible way.
Maybe the above way is completely wrong, I do appreciate your guidance.
Thank you

Try modifying your code to something like this:
foreach($line in Get-Content .\Alltables.txt) {
if($line -match $regex) {
$bcp_command = "bcp $database" + '.' + $schema '.' + $line + ' out ' + $line + '.dat -T -c')
Tee-Object -FilePath $LogFile -InputObject $bcp_command -Append
$bcp_results = Invoke-Expression $bcp_command
Tee-Object -FilePath $LogFile -InputObject $bcp_results -Append
}
}

Related

For loop with list not working as expected Powershell

I'm trying to create a powershell script which checks a log file for lines of text and if the line exists restarts a service and resets/archives the log. I got it working before with 1 "checkstring" if you will, but I've been struggling to get it to work with a list of strings. Could anyone help me figure out where I'm going wrong?
This is the code I'm currently using:
$serviceName = "MySQL80"
$file = "test.txt"
$pwd = "C:\tmp\"
$checkStrings = New-Object System.Collections.ArrayList
# Add amount of checkstrings
$checkStrings.add("Unhandled error. Error message: Error retrieving response.")
$checkStrings.add("Unhandled error. Error message: Error retrieving response. Second")
$logName = "ServiceCheck.log"
$backupFolder = "Archive"
$logString = (Get-Date).ToString("ddMMyyyyHHmmss"), " - The service has been reset and the log moved to backup" -Join ""
Set-Location -Path $pwd
if(Test-Path -Path $file) {
if(Test-Path -Path $backupFolder) {
} else {
New-Item -Path $pwd -Name $backupFolder -ItemType "director"
}
foreach ($element in $checkStrings) {
$containsWord = $fileContent | %{$_ -match $element}
if ($containsWord -contains $true) {
Restart-Service -Name $serviceName
$backupPath = $pwd, "\", $backupFolder, "\", $date, ".log" -join ""
$currentFile = $pwd, "\", $file -join ""
Copy-Item $currentFile -Destination $backupPath
Get-Content $currentFile | select-string -pattern $checkString -notmatch | Out-File $currentFile
if(Test-Path -Path $logName) {
Add-Content $logName $logString
} else {
$logString | Out-File -FilePath $logName
}
}
}
}

move multiple local folder and their content to remote server through sftp protocol with powershell

I want to move specific files from a local directory to a folder of a remote server.
The files are generated in folders inside the main directory.
The names of the folders are the actual dates and inside them there are files.
In some cases the names of the files are the same but they are in separate folders.
For example:
\main\
\201809271020\a20180927.txt
\201809271120\a20180927.txt
\201809271220\a20180927.txt
I have to move all of the folders and files under the main folder to the remote location.
I've tried it with WinSCP powershell module, but it works on files only. I couldn't move folders with it.
Any helps appreciated.
Regards
wolfnlight
Ok, I create a script, I hope it will not so bad. :)
[xml]$config = Get-Content "C:\Script\config.xml" -ErrorAction Stop
[string]$serverName = $config.Configuration.HostName
[string]$UserName = $config.Configuration.UserName
[string]$localPath = $config.Configuration.LocalPath
[string]$remotePath = $config.Configuration.RemotePath
[string]$logFile = $config.Configuration.LogFile
[string]$SshHostKeyFingerprint = $config.Configuration.SshHostKeyFingerprint
[string]$SshPrivateKeyPath = $config.Configuration.SshPrivateKeyPath
[string]$wildcard = $config.Configuration.WildCard
Import-Module -Name "C:\Program Files (x86)\WindowsPowerShell\Modules\WinSCP" -Force
############# functions for log ##########################################
function InfoToLog {
return "$(get-date -Format "yyyy.MM.dd HH:mm:ss") - [INFO] - "
}
function WarningToLog {
return "$(get-date -Format "yyyy.MM.dd HH:mm:ss") - [WARNING] - "
}
function ErrorToLog {
return "$(get-date -Format "yyyy.MM.dd HH:mm:ss") - [ERROR] - "
}
############ Uploader ####################################################
function Data-Uploader {
param (
$i = 0
)
foreach ($localFile in $localFiles) {
$localDirName = $localFiles[$i].FullName.Substring(38,15)
$localDir = $localPath + $localDirName
$remoteDir = $remotePath + $localDirName
$GetLocalDir = Get-ChildItem -Path $localDir -Recurse -Include "export.end" -ErrorAction Stop
if (($GetLocalDir)) {
# target directory query
if (!(Test-WinSCPPath $session -Path $remoteDir)) {
$(InfoToLog) + $remoteDir + " not exist...creating" | Out-File $logFile -Append
New-WinSCPItem -WinSCPSession $session -Path $remoteDir -ItemType "directory" -Verbose -ErrorAction Stop
$(InfoToLog) + $remoteDir + " created" | Out-File $logFile -Append
}
else {
$(InfoToLog) + $remoteDir + " exists!" | Out-File $logFile -Append
}
$localFileName = $localFiles[$i].FullName
$remotefileName = $localFiles[$i].Name
# put files from local directory to remote directory - same name
if ($localFileName -like "*$localDir*") {
$localFile = "FileName: " + $localFile.Name + " - CreationTime: " + $localFile.CreationTime.GetDateTimeFormats('u') + "- Length(kB): " + $localFile.Length
$(InfoToLog) + $localFile | Out-File $logFile -Append
$(InfoToLog) + "Transfering $remotefileName ..." | Out-File $logFile -Append
Send-WinSCPItem -TransferOptions $TransferOptions `
-WinSCPSession $session `
-LocalPath "$localDir\$wildcard" `
-RemotePath $remoteDir -ErrorAction Stop -Verbose
$(InfoToLog) + "$remotefileName transfered." | Out-File $logFile -Append
$(InfoToLog) + "Archiving files..." | Out-File $logFile -Append
Move-Item -Path $localDir -Destination "C:\Script\Archive\" -Force -ErrorAction Stop -Verbose
$(InfoToLog) + "Archiving completed." | Out-File $logFile -Append
}
else {
$(InfoToLog) + "No file for transfer." | Out-File $logFile -Append
}
}
else {
$(WarningToLog) + "$localFile - waiting for export ended!" | Out-File $logFile -Append
}
$i++
}
}
################# process ######################################
try {
$(InfoToLog) + "Data_Uploader - version 1.2 - Starting script..." | Out-File $logFile -Append
# set user
$MyCredential = New-Object System.Management.Automation.PSCredential ($UserName, (new-object System.Security.SecureString))
# set session
$sessionOption = New-WinSCPSessionOption -Credential $MyCredential -HostName $serverName -Protocol sftp -SshHostKeyFingerprint $SshHostKeyFingerprint -SshPrivateKeyPath $SshPrivateKeyPath
$TransferOptions = New-WinSCPTransferOption -FileMask $wildcard -TransferMode Binary
# connecting
$session = New-WinSCPSession -SessionOption $sessionOption -ErrorAction Stop -SessionLogPath "C:\Script\MUK\Log\Muk_Uploader_session.log"
# session available
if ($session.Opened -eq $true) {
$(InfoToLog) + "Connected to $servername..." | Out-File $logFile -Append
# get local files
$localFiles = Get-ChildItem -Path $localPath -Recurse -ErrorAction Stop -Verbose -Attributes !Directory -Exclude "riport.end"
# existing files in local dir
if ($localFiles.Count -gt 0) {
$(InfoToLog) + $localFiles.Count +" files in $localPath :" | Out-File $logFile -Append
# upload files
Data-Uploader
}
else {
$(InfoToLog) + "No files in $localPath" | Out-File $logFile -Append
}
}
else {
$(ErrorToLog) + "$($_.Exception.Message)" | Out-File $logFile -Append
}
} # try
catch {
Write-Host -ForegroundColor Green "Error: $($_.Exception.Message)"
$(ErrorToLog) + "Message: $($_.Exception.Message)" | Out-File $logFile -Append
# session close
Remove-WinSCPSession -WinSCPSession $session -ErrorAction Stop
}
finally {
$(InfoToLog) + "End script!" | Out-File $logFile -Append
"$(get-date -Format "yyyy.MM.dd HH:mm:ss") - ***************************************************************************************************" | Out-File $logFile -Append
# session close
Remove-WinSCPSession -WinSCPSession $session -ErrorAction Stop
}
Any suggestions?

Reading 2 variables from a text file and looping

I have a script which I'd like to use PowerShell to bcp out data. I need to kick off multiple bcp commands and want to read 1. table name and 2. field name from a text file to populate the bcp command string.
Currently this doesn't work, but I'm not sure how to incorporate the 2 variables.
The text file looks like:
table: table1
table: table2
field: field1
field: field2
# Log file time stamp:
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
# Log file name:
$LogFile = "C:\Administration\Logs\BCPEXPORTLOG_" + $LogTime + ".log"
$database = "database"
$schema = "dbo"
$table = "TableName"
$tablename = Get-Content 'C:\Administration\Scheduled Tasks\CUBTableList.txt' |
? { $_ -match '^\s*table:\s*' } |
select -First 1 |
% { ($_ -split ':\s*', 2)[1] }
$fieldname = Get-Content 'C:\Administration\Scheduled Tasks\CUBTableList.txt' |
? { $_ -match '^\s*field:\s*' } |
select -First 1 |
% { ($_ -split ':\s*', 2)[1] }
foreach ($line in Get-Content 'C:\Administration\Scheduled Tasks\CUBTableList.txt') {
$bcp_command = "bcp 'SELECT * FROM $database.$schema.$tablename WHERE ($fieldname <= DATEADD(ms, -3, GETDATE()))' QUERYOUT 'D:\BCPOut\$database`_$tablename.txt' -c -U 'user' -P 'password'"
Tee-Object -FilePath $LogFile -InputObject $bcp_command -Append
$bcp_results = Invoke-Expression $bcp_command
Tee-Object -FilePath $LogFile -InputObject $bcp_results -Append
}
I've fixed up my dodgy script.
Used import-csv instead.
# Log file time stamp:
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
# Log file name:
$LogFile = "C:\Administration\Logs\BCPEXPORTLOG_"+$LogTime+".log"
$database = "database"
$schema = "dbo"
$table = "TableName"
Import-CSV 'C:\Administration\Scheduled Tasks\CUBList.csv' | ForEach{
$bcp_command = "bcp 'SELECT * FROM $database.$schema." + $_.tablename + " WHERE (" + $_.fieldname + " <= DATEADD(ms, -3, GETDATE()))' QUERYOUT 'D:\BCPOut\$database`_" + $_.tablename + ".txt' -c -U 'user' -P 'password'"
Tee-Object -FilePath $LogFile -InputObject $bcp_command -Append
$bcp_results = Invoke-Expression $bcp_command
Tee-Object -FilePath $LogFile -InputObject $bcp_results -Append
}
Try with this code:
$LogFile = "c:\temp\BCPEXPORTLOG_{0:MM-dd-yyyy_hh-mm-ss}.log" -f (Get-Date)
$database = "database"
$schema = "dbo"
#split with 'table:'
$Split1=(Get-Content c:\temp\CUBTableList.txt) -split 'table:'
#split fields and take only tablename <>'' and table have field
$Elements=$Split1 | %{
$Split2=$_ -split 'field:'
$table=$Split2[0];
[pscustomobject]#{TableName=$Split2[0].Trim(); Fields=$Split2[1..$($Split2.Length)] | %{$_.Trim()}} | where {$_.TableName -ne '' -and $_.Fields -ne $null}
}
$bcp_command=#()
#build bcp commands
$Elements | %{
$TableName=$_.TableName
$_.Fields | %{
$bcp_command+="bcp 'SELECT * FROM {0}.{1}.{2} WHERE {3} <= DATEADD(ms, -3, GETDATE())' QUERYOUT 'D:\BCPOut\{0}_{2}_{3}.txt' -c -U 'user' -P 'password'" -f $database, $schema, $TableName, $_
}
}
#run commands
$bcp_command | %{
$_ | out-file $LogFile -Append
try
{
$result=Invoke-Expression $_
}
catch
{
$result=$_.Exception.Message
}
finally
{
$result | Out-File $LogFile -Append
}
}

PowerShell script - Converting PDFs to TIFs using Ghostscript

What am I missing here?
I'm getting this error:
ERROR converting File
E:\DocuTA\TIFs\06fef98e-e1c5-405e-93ea-c684ee7a856d.tif
nvoke-Expression : You must provide a value expression on the
right-hand side of the '-' operator. At E:\DocuTA\ConvPDFtoTIF.ps1:31
char:26 + $ret = invoke-expression <<<< -command $cmdline +
CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException +
FullyQualifiedErrorId :
ExpectedValueExpression,Microsoft.PowerShell.Commands.InvokeExpressionCommand
when running this script:
#recursively crawls the directory tree and converts pdf files to tif files
#compresses the images to a smaller file size.
$Now = get-date
$Days = "14"
$LastWrite = $Now.AddDays(-$Days)
$srcfolder = "E:\DocuTA\PDFs\"
$destfolder = "E:\DocuTA\TIFs\"
$convert = "& C:\Program Files (x86)\gs\gs9.16\bin\gswin32c.exe"
$filter = "*.pdf"
$dest_ext = "tif"
$arg1 = #(" -dNOPAUSE -dQUIET -r300x300 -sDEVICE=tiffg4 -dBATCH ")
$lfpath = "E:\DocuTA\Logs\"
$logfile = new-item -type file -name "PDF2TIFLog$(get-date -uformat '%Y%m%d%H%M%S').log" -path "$lfpath"
$elogfile = "E:\DocuTA\Logs\PDF2TIFErrorLog.log"
#-------------------------------------------------------------------
$count = 0
Write-Output "`nStarting ... ($Now)" | Out-File -Append $logfile
Try
{
foreach ($srcitem in $(Get-ChildItem $srcfolder -Include $filter -Recurse | Where-Object {$_.LastWriteTime -gt "$LastWrite"}))
{
$count++
$srcname = $srcitem.FullName
$partial = $srcitem.FullName.Substring($srcfolder.Length)
$destname = $destfolder+$partial
$destname = [System.IO.Path]::ChangeExtension($destname,$dest_ext)
$destpath = [System.IO.Path]::GetDirectoryName($destname)
$cmdline = "'"+$convert+"'"+"'"+$srcname+"'"+$arg1+ "'"+$destname+"'"
Write-Output "[$count] $cmdline" | Out-File -Append $logfile
$ret = invoke-expression -command $cmdline
Write-Output "[$count] OUTPUT: $ret" | Out-File -Append $logfile
Write-Output "[$count] processed file." | Out-File -Append $logfile
}
}
Catch
{
$Now | out-file -Append $elogfile
write-output "ERROR converting File $destname" | out-file -Append $elogfile
Write-Output $Error[0] | out-file -Append $elogfile
}
Finally
{
Write-Output "Finished processing files. Total: $count`n" | Out-File -Append $logfile
}
Looks like PowerShell doesn't like using - for switches, try using # instead

File Output issue in PowerShell

Trying to write to a log file assigned to a variable in PowerShell, like so-
Code:
$Time = Get-Date
$FileTimeStamp = (Get-Date -f MM-dd-yyyy_HH.mm.ss)
$ErrorLog | out-file $(".\Logs\" + $FileTimeStamp + "_PushLog.log") -append
"Script started at $Time" | out-file $ErrorLog -append
Compile error-
Out-File : Cannot bind argument to parameter 'FilePath' because it is null.
At C:\OSM\Scripts\FilePush\FilePush.ps1:56 char:37
+ "Script started at $Time" | out-file <<<< $ErrorLog -append
+ CategoryInfo : InvalidData: ( [Out-File], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.OutFileCommand
What am I doing wrong? Am I getting there? It's now correctly writing one file instead of two, but the log doesn't contain the string "Session started at $Time".
Code:
$Time = Get-Date
$FileTimeStamp = (Get-Date -f HH.mm.ss_MM-dd-yyyy)
$ErrorLog = out-file $(".\Logs\" + $FileTimeStamp + "_PushLog.log") -append
$ErrorLog = [io.path]::GetFileName("$ErrorLog.FullName")
"Session started at $Time" | out-file $ErrorLog -append
The whole point of what I'm trying to do is create a variable for an error file that I can reference when I want to output text to it. I only want log each time the script runs, but that seems to be an issue when I;'m appending the time to the file name. How do I work past this?
Bob answered the question but really didn't help provide a solution, so I'll add an answer.
The issue is that when you try to define your $ErrorLog variable you're overthinking it. You just need to create a string that defines where the file is located, not have all the Out-File and -Append on that line.
$Time = Get-Date
$FileTimeStamp = (Get-Date -f MM-dd-yyyy_HH.mm.ss)
$ErrorLog = ".\Logs\$FileTimeStamp_PushLog.log"
"Script started at $Time" | out-file $ErrorLog -append
You haven't defined $ErrorLog.