Powershell 从文件中提取文件名和数据

Powershell 从文件中提取文件名和数据,powershell,mschart,Powershell,Mschart,我有过去几个月的每小时日志文件,我想将数据导出到MS Charts 我已经设法把数据拿出来了,但是在图表的x轴上找不到日期 日志文件的文件名包含日期,我已尝试使用创建日期或上次写入时间。我得到的最接近的方法是计算日志数,然后除以24,但它生成的日期与数据不匹配 有什么想法吗 一切正常,但我无法让X轴显示正确的日期。理论上,应该以6月11日为开始日期,以昨天为结束日期。 它从中读取的文件的格式为 HealthCheck 2014年9月10日星期三上午5:00 理想情况下,我希望从文件名中获取日期。

我有过去几个月的每小时日志文件,我想将数据导出到MS Charts

我已经设法把数据拿出来了,但是在图表的x轴上找不到日期

日志文件的文件名包含日期,我已尝试使用创建日期或上次写入时间。我得到的最接近的方法是计算日志数,然后除以24,但它生成的日期与数据不匹配

有什么想法吗

一切正常,但我无法让X轴显示正确的日期。理论上,应该以6月11日为开始日期,以昨天为结束日期。 它从中读取的文件的格式为 HealthCheck 2014年9月10日星期三上午5:00

理想情况下,我希望从文件名中获取日期。我不想依赖于文件编写时的计算,因为这很容易出错

[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")
$Farm = "XAccess"

#gets files from yesterday
$Date = Get-Date #-Uformat %x
$Date = ($Date).adddays(-1)
$Date = $Date.ToString("M/d/yyyy")
$files = get-childitem "c:\$Farm*.log" | Where{$_.LastWriteTime -lt $date}

$ActiveSessions = Select-String -path $files '(?<=^"*Total Active Sessions: )\d+(?=)'|

 ForEach-Object {$_.Matches[0].Value}


#Calculates numbers of days 
$datapoints = $ActiveSessions.count/24

#== Creates Chart ==#

# create chart object 
$Chart = New-object System.Windows.Forms.DataVisualization.Charting.Chart 
$Chart.Width = 1600
$Chart.Height = 800

# create a chartarea to draw on and add to chart 
$ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea 
$Chart.ChartAreas.Add($ChartArea) 
[void]$Chart.Series.Add("Data")
$Chart.ChartAreas["ChartArea1"].AxisX.Interval = 24
$Chart.ChartAreas["ChartArea1"].AxisX.LabelStyle.Angle = -40
$Chart.ChartAreas["ChartArea1"].AxisY.Interval = 5
$Chart.ChartAreas["ChartArea1"].AxisY.title = "Active Sessions"
$chart.Series.Add('ChartArea1')

# add a data point for each server 

foreach ($session in $ActiveSessions) 
{ 
$dp1 = new-object System.Windows.Forms.DataVisualization.Charting.DataPoint(0, $session) 
$dp1.AxisLabel = (get-date).adddays(-"$datapoints").tostring("ddd dd MMM")
$datapoints = $datapoints - 0.0416666666666667 
$Chart.Series["Data"].Points.Add($dp1)
} 


# set the title to the date and time 
$title = new-object System.Windows.Forms.DataVisualization.Charting.Title 
$Chart.Titles.Add( $title )
$Chart.Titles[0].Font = "Arial,13pt" 
$Chart.Titles[0].Text = "Year to Date sessions for $Farm" 

# save the chart to a file 
$Chart.SaveImage("C:\$Farm Farm.png","png")

好的,那么您需要文件中的日期。没问题,我们可以做到。让我们从如何最好地做到这一点开始。。。我们像往常一样有选择的余地。等等,我有点过头了。我们想在哪里定义它?好吧,我能想到的最简单的地方是任何你正在循环通过有问题的文件并获取其他数据的地方,这样我们就可以把所有东西都正确地关联起来。因此,看起来您分配$ActiveSessions的行将是我们的最佳选择

现在,回到如何获得日期。我们可以使用SubString方法,但当我们为文本定义了格式时,这对我来说似乎很混乱。就我个人而言,我宁愿做一个正则表达式匹配。所以我在文件名中看到的是一个三个字母的日缩写,然后是一个1-2位数的日,一个三个字母的月,还有一个四位数的年。之后是连字符、两位数的小时、句点、两位数的分钟和AM/PM指示器

所以,就[datetime]格式而言,它是ddd MMM yyy-hh.mm tt。我们会继续讨论的。如何提取日期?哦,对了,正则表达式。下面是我如何得到的:

([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value
它将模式声明为regex对象,然后使用其Matches方法,并获取匹配的值。所以我们有了日期,现在可以实际使用了。这是我们回到DateTime格式的地方。我们可以使用[DateTime]::ParseExact方法来获取日期时间,即使格式很奇怪。现在我们将在ForEach循环中获取它,并从selectstring提供给循环的对象的FileName属性中提取日期。下面是它的外观:

[datetime]::ParseExact(([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value,"ddd d MMM yyyy - hh.mm tt",$null)
$ActiveSessions = Select-String -path $files '(?<=^"*Total Active Sessions: )\d+(?=)'|
 ForEach-Object {[PSCustomObject][Ordered]@{
    'Sessions'=$_.Matches[0].Value
    'Date'=[datetime]::ParseExact(([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value,"ddd d MMM yyyy - hh.mm tt",$null)
    }
}
好的,这实际上给了我们一个很好的可用datetime对象。因此,ForEach循环已经在回吐活动会话,$ActiveSessions是一个字符串数组。让我们稍微改变一下,将它变成一个对象数组,现在每个对象都有两个属性,会话和日期。因此,ForEach循环的内部必须生成具有这些属性的对象。使用PowerShell v3或更高版本最简单的方法,如果您正在运行旧版本的PowerShell,并且需要我执行以下操作,我将向您展示最困难的方法:

[PSCustomObject][Ordered]@{
    'Sessions'=$_.Matches[0].Value
    'Date'=[datetime]::ParseExact(([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value,"ddd d MMM yyyy - hh.mm tt",$null)
}
这使得整个$ActiveSessions=行看起来像:

[datetime]::ParseExact(([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value,"ddd d MMM yyyy - hh.mm tt",$null)
$ActiveSessions = Select-String -path $files '(?<=^"*Total Active Sessions: )\d+(?=)'|
 ForEach-Object {[PSCustomObject][Ordered]@{
    'Sessions'=$_.Matches[0].Value
    'Date'=[datetime]::ParseExact(([regex]"\w{3} \d{1,2} \w{3} \d{4} - \d{2}\.\d{2} (?:AM|PM)").matches($_.Filename).value,"ddd d MMM yyyy - hh.mm tt",$null)
    }
}

这应该可以帮到你。

我尝试使用regex,但无法通过我提到的错误

因此,在进一步研究之后,我决定将文件的创建日期和所需数据导出到CSV文件中,然后根据该文件创建图表。这是我用来将数据导入csv的代码:

$files = get-childitem "c:\$farm*.log" | sort CreationTime    
Foreach ($file in $files)
{
    $FileCreation = $file.CreationTime.Date.ToString('ddd dd MMM yyyy')
    $ActiveSessions = Select-String -path $file '(?<=^"*Total Active Sessions: )\d+(?=)' | ForEach-Object {$_.Matches[0].Value}
   Add-Content d:\licInUse.csv "$FileCreation,$ActiveSessions"
}
    # processing the Data
    $Processes = Import-Csv -path d:\licInUse.csv -Delimiter ',' -Header "Date","Count"
    $DateNames = @(foreach($Date in $Processes){$Date.Date}) 
    $SessionCount = @(foreach($Date in $Processes){$Date.Count})

欢迎来到堆栈溢出!不清楚您的要求是什么,请提供一个最低限度的代码示例,解释您期望的行为,并提供错误消息(如果有)?我明白您的要求,但您仍然需要提供您正在使用的相关代码,以及文件名和格式的示例,以便我们能够帮助您。@Kayasax代码已附加。非常感谢,如果明天早上没有人能比我更好的回答我,我会发布一个答案。快凌晨1点了,所以先睡觉,然后编码。谢谢你的反馈。我读了又读了你的文章,它确实有道理。但是,调用带有3个参数的ParseExact时出现以下错误异常:String未被识别为有效的DateTime。在D:\Citrix\WIP XAccessYeartoDatesessions.ps1:19 char:34+'Date'=[datetime]::ParseExact我能想到的唯一原因是,您的文件名与示例中给出的文件名不完全相同。他们之间有差异吗?