如何将 RTF 格式的日志文件转换为纯文本

问题描述

我需要将备份解决方案应用程序生成的日志文件从 RTF 格式连续转换为纯文本(如制作一个全新的日志,该日志是该日志的精确副本,并且始终是更新的副本)为了使用我从另一个用户那里得到的代码解析日志文件中的错误(请在下面找到它)。知道如何使用 powershell 使用代码执行此操作吗?

我可以搜索文本文件代码

$daysBack = 3
$refDate  = (Get-Date).AddDays(-$daysBack).Date  # set this to midnight
$log      = Get-Content -Path 'C:\Users\<User>\Documents\TheLog.log'

# find lines that start with what looks like a date and contains 'Errors:'
# capture the date part in backreference $matches[1] to parse into a real datetime object for comparison with $refDate
$errors = @($log | Where-Object { $_ -match '(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}).*Errors:' } |   
                   Where-Object { [datetime]::ParseExact($matches[1],'dd/MM/yyyy HH:mm:ss',$null) -ge $refDate }).Count

# if $errors not 0
if ($errors) {
    $count = if ($errors -eq 1) { "was an error" } else { "were $errors errors" }
    "There {0} in your back up solution in the last $daysBack days. Please check your log file." -f $count
}
else {
    "There were no errors in backing up your files in the last $daysBack days."
}

我已使用以下日志文​​件的纯文本文件版本进行了测试:

18/02/2021 08:57:37 - can not access C:\users\<username>\documents\ The network path was not found.
18/02/2021 08:57:37 - End: Documents... copied: 0,Errors: 1
21/02/2021 08:57:37 - can not access C:\users\<username>\documents\ The network path was not found.
21/02/2021 08:57:37 - End: Documents... copied: 0,Errors: 1
22/02/2021 17:27:33 - Begin: Documents=======================================
22/02/2021 17:27:33 - copied Notes.docx from C:\users\<username>\documents\ to D:\users\<username>\documents\
22/02/2021 17:27:33 - End: Documents...copied 1
22/02/2021 17:27:33 - End: Documents...copied 1,Deleted: 1

以上代码不适用于 RTF。任何帮助或任何想法如何更改上述代码以适合我的 RTF 格式的日志文件

@THEO 使用以下代码 :)

Cannot invoke method. Method invocation is supported only on core types in this language mode.

At line:41 char:13

+             $word.Quit()

+             ~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [],RuntimeException

    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

 

Cannot invoke method. Method invocation is supported only on core types in this language mode.

At line:42 char:13

+             $null = [System.Runtime.InteropServices.Marshal]::Release ...

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [],RuntimeException

    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

 

Cannot invoke method. Method invocation is supported only on core types in this language mode.

At line:43 char:13

+             $null = [System.Runtime.InteropServices.Marshal]::Release ...

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [],RuntimeException

    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

 

Cannot invoke method. Method invocation is supported only on core types in this language mode.

At line:44 char:13

+             [System.GC]::Collect()

+             ~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [],RuntimeException

    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

 

Cannot invoke method. Method invocation is supported only on core types in this language mode.

At line:45 char:13

+             [System.GC]::WaitForPendingFinalizers()

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [],RuntimeException

    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

 

Cannot set property. Property setting is supported only on core types in this language mode.

At line:17 char:9

+         $word.Visible = $false

+         ~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [],RuntimeException

    + FullyQualifiedErrorId : PropertySetterNotSupportedInConstrainedLanguage

 

Get-Content : Cannot bind argument to parameter 'Path' because it is null.

At line:55 char:31

+ $log      = Get-Content -Path $plainTextLog

+                               ~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-Content],ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterargumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentC

   ommand

解决方法

要从 RTF 文件转换为纯文本文件,您可以使用以下辅助函数:

function ConvertFrom-RTF {
  [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true,ValueFromPipeline = $true,ValueFromPipelineByPropertyName = $true)]
        [Alias('FullName')]
        [string]$Path
    )

    # this is the output format
    # see:  https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.word.wdsaveformat?view=word-pia
    $WdSaveFormat = 3   # wdFormatTextLineBreaks

    try {
        $word = New-Object -ComObject Word.Application
        $word.Visible = $false
        $doc = $word.Documents.Open($Path)
        # Replace the source file extenson with the appropriate target file extension 
        $fileOut = [System.IO.Path]::ChangeExtension($Path,'.txt')

        if (Test-Path -Path $fileOut -PathType Leaf) {
            # Delete existing file
            Remove-Item -Path $fileOut -Force -Confirm:$false
        }
        # Check Version of Office Installed. Pre 2010 versions need [ref] on the parameters
        if ($word.Version -gt '14.0') {
            $doc.SaveAs($fileOut,$WdSaveFormat)
        }
        else {
            $doc.SaveAs([ref]$fileOut,[ref]$WdSaveFormat)
        }
        $doc.Close($false)

        # return the filename of the converted file
        return $fileOut
    }
    finally {
        # cleanup code
        if ($word) {
            $word.Quit()
            $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($doc)
            $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($word)
            [System.GC]::Collect()
            [System.GC]::WaitForPendingFinalizers()
        }
    }
}

# the returned value is the full path and filename of the converted text file
$plainTextLog = ConvertFrom-RTF -Path 'C:\Users\<User>\Documents\TheLog.rtf'

在其下方,添加您在 here 中已有的代码以解析日志:

$daysBack = 3
$refDate  = (Get-Date).AddDays(-$daysBack).Date  # set this to midnight
$log      = Get-Content -Path $plainTextLog

# find lines that start with what looks like a date and contains 'Errors:'
# capture the date part in backreference $matches[1] to parse into a real datetime object for comparison with $refDate
$errors = @($log | Where-Object { $_ -match '(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}).*Errors:' } |   
                   Where-Object { [datetime]::ParseExact($matches[1],'dd/MM/yyyy HH:mm:ss',$null) -ge $refDate }).Count

# if $errors not 0
if ($errors) {
    $count = if ($errors -eq 1) { "was an error" } else { "were $errors errors" }
    "There {0} in your back up solution in the last $daysBack days. Please check your log file." -f $count
}
else {
    "There were no errors in backing up your files in the last $daysBack days."
}