Windows 7 사용자 로그인 시간 측정 모든 부팅을 기록하기

클라이언트가 컴퓨터와 사용자의 평균 로그인 시간을 계산하라는 요청을 받았습니다. 지금까지 이벤트에서 발견 된 키에 의해 설정된 임계 값보다 오래 걸리는 일부 부트를 기록하는 것으로 나타났습니다.

HKLM\Software\Microsoft\Windows\CurrentVersion\Diagnostics\Performance\Boot

그러나 키가 잠겨있는 것처럼 보이므로 모든 부팅을 기록하기 위해 임계 값을 낮추도록 편집 할 수 없습니다. 각 로그온에 대한 로그인 시간을 찾는 방법이 있으며 사용자에게 로그인 중임을 알리기에 더 자세한 정보를 제공 할 수 있습니까? 또한 모든 로그인에서 실행할 수있을 정도로 가벼워 야하며 사용자에게 눈에 띄는 영향을 미치지 않아야합니다. .



답변

최근에 비슷한 작업을 수행하도록 요청했지만 부팅 및 로그온 시간을 포함하고 기록 참조를 허용했습니다. 따라서 powershell 스크립트는 다음을 수행합니다.

  1. 일부 환경 변수를 가져옵니다
  2. 4 개의 다른 이벤트 로그 항목에 대한 시간 / 날짜 스탬프를 가져옵니다. 이 중 두 번째와 네 번째는 정확한 측정은 아니지만 상당히 광범위한 연구, 문제 해결 및 테스트를 거친 후 내가 본 것 중에서 가장 좋은 옵션입니다.
  3. 이 4 가지 이벤트의 차이를 계산합니다
  4. 모든 숫자를 간단한 SQL 테이블에 채 웁니다 [물론 원하는 숫자를 파이프에 적용 할 수 있습니다]

따라서 스크립트는 예약 된 작업을 통해 또는 SCCM이있는 경우 일정에 따라 실행되도록되어 있습니다 (로그온 중에 전혀 로그온하지 않도록). 좋은 점은 PC 이름을 다른 PC로 변경하여 자신의 PC에서 실행하고 원격 컴퓨터에서 사용자 이름을 표시하더라도 원격 컴퓨터에서 데이터를 가져와 문제를 해결하고 번호를 확인할 수 있다는 것입니다.

나는 또 다른 단계를 밟고 SharePoint를 사용하여 외부 데이터 목록 (BCS 사용)을 작성하여 멋진 프론트 엔드 GUI를 갖도록했습니다. 아래 스크립트는 내가 쓰는 동안 사용한 주석 행의 대부분을 남겼습니다.

$USER = $env:username.ToUpper()
$COMPUTER = $env:computername.ToUpper()
$Current_Time = Get-Date
$PCname = ''
$addedtime = 0

#1. get event time of last OS load
$filterXML = @'
<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">*[System[Provider[@Name='Microsoft-Windows-Kernel-General'] and (Level=4 or Level=0) and (EventID=12)]]</Select>
  </Query>
</QueryList>
'@
$OSLoadTime=(Get-WinEvent -ComputerName $PCname -MaxEvents 1 -FilterXml $filterXML).timecreated
#Write-Host $PCname
#Write-Host "1. Last System Boot @ " $OSLoadTime

#2. Get event time of Time-Service [pre-Ctrl+Alt-Del] after latest OS load
$filterXML = @'
<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">*[System[Provider[@Name='Microsoft-Windows-Time-Service'] and (Level=4 or Level=0) and (EventID=35)]]</Select>
  </Query>
</QueryList>
'@
$CtrlAltDelTime=(Get-WinEvent -ComputerName $PCname -MaxEvents 1 -FilterXml $filterXML).timecreated
#Write-Host "2. Time-sync after Boot @ " $CtrlAltDelTime
#get minutes (rounded to 1 decimal) between OS load time and 1st load of GPOs
$BootDuration = "{0:N1}" -f ((($CtrlAltDelTime - $OSLoadTime).TotalSeconds + $addedtime)/60)

#3. get event time of 1st successful logon
$filterXML = @'
<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">*[System[Provider[@Name='Microsoft-Windows-Winlogon'] and (Level=4 or Level=0) and (EventID=7001)]]</Select>
  </Query>
</QueryList>
'@
$LogonDateTime=(Get-WinEvent -ComputerName $PCname -MaxEvents 1 -FilterXml $filterXML -ErrorAction SilentlyContinue).timecreated

If ($LogonDateTime) {
    #Write-Host "3. Successful Logon @ " $LogonDateTime
    }
    Else {
    #Write-Host "Duration of Bootup = " $BootDuration "minutes" -foregroundcolor blue -BackgroundColor white
    #Write-Host $PCname "has not logged back in." -foregroundcolor red -BackgroundColor white
    Exit
    }
#Write-Host "Duration of Bootup = " $BootDuration "minutes" -foregroundcolor blue -BackgroundColor white

#4. Get Win License validated after logon (about same time as explorer loads)
$filterXML = @'
<QueryList>
  <Query Id="0" Path="Application">
    <Select Path="Application">*[System[Provider[@Name='Microsoft-Windows-Winlogon'] and (Level=4 or Level=0) and (EventID=4101)]]</Select>
  </Query>
</QueryList>
'@
$DesktopTime=(Get-WinEvent -ComputerName $PCname -MaxEvents 1 -FilterXml $filterXML).timecreated
$LogonDuration = "{0:N1}" -f ((($DesktopTime - $LogonDateTime).TotalSeconds + $addedtime)/60)
#Write-Host "4. WinLicVal after Logon @ " $DesktopTime
#Write-Host "Duration of Logon = " $LogonDuration "minutes" -foregroundcolor blue -BackgroundColor white

#START SQL Injection Section
[void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")

$sqlServer = "SQLserver01"
$dbName = "BootUpTimes"
$tbl = "tblBootUpTimes"
#$srv = New-Object Microsoft.SqlServer.Management.Smo.Server $sqlServer
#$db = $srv.databases[$dbName]
#$conn = New-Object System.Data.SqlClient.SqlConnection("Data Source=$sqlServer;Initial Catalog=$dbName; Integrated Security=SSPI")
$conn = New-Object System.Data.SqlClient.SqlConnection("server=$sqlServer;database=$dbName;Password=plaintext;User Id=BootUpTimes")
$conn.Open()
$cmd = $conn.CreateCommand()
$cmd.CommandText = "INSERT INTO $tbl VALUES ('$Current_Time','$USER','$COMPUTER','$OSLoadTime','$CtrlAltDelTime','$BootDuration','$LogonDateTime','$DesktopTime','$LogonDuration')"
Try
{
$null = $cmd.ExecuteNonQuery()
}
Catch
{
}
$conn.Close()

이 마지막 SQL 섹션에는 일반 텍스트로 된 암호없이 SQL에 입력 할 수있는 다른 방법 (보안 기반)을 제공하는 주석 처리 된 몇 줄이 있습니다.


답변

누군가 스크립트가 로그온 시간을 결정하는 데 도움이된다고 생각하는 이유를 잘 모르겠습니다. (누군가 로그온 할 때까지 스크립트를 실행할 수없고 시간이 흐르면 ​​시간이 오래 걸리기 때문에 도움이되지 않습니다. 시작할 때까지 수정되지 않았습니다. 사용할 것을 제안하는 도구는 성능 툴킷의 xperf 도구입니다. 총 로그온 시간은 explorerinit 시간을 확인하십시오. 자세한 내용은 Windows On / Off 전환 성능 분석 을 참조하십시오. 부팅에서 데스크톱으로 발생하는 상황 적절한 위치에서 xperf 및 xbootmgr을 가져 오려면 Windows 성능 분석 도구 를 참조하십시오 .


답변

/superuser/250267/how-to-diagnose-slow-booting-or-logon-in-windows-7

이 스레드는 Windows 성능 분석 도구를 사용한 “Microsoft”부팅 진단 방법을 보여줍니다.

“켜기 / 끄기 전환 성능”에 대한 Microsoft의 문서화 된 절차 (Windows 켜기 / 끄기) : http://msdn.microsoft.com/en-us/windows/hardware/gg463386.aspx

이러한 공식 도구를 사용하여 고객에게 신뢰할만한 답변을 제공 할 수 있습니다. 제 생각에는 스크립팅을 사용하는 것보다 훨씬 뛰어납니다. 당신의 요구가 기본이라면 약간 과잉 일 수 있습니다.

또한 귀하의 요구가 매우 기본적이라면 그 스레드에서 Soluto의 웹 사이트를 놓치지 마십시오 🙂


답변

로그온 스크립트로 실행 된 다음 배치 파일은 인증에서 준비중인 셸까지 걸리는 시간을 알려줍니다.

set logfile=\\server\share\%computername%-%username%.log
net user /domain %username% | find /I "Last logon" > %logfile%
net time %logonserver% >> %logfile%

나는 이것을 테스트하지 않았으며 몇 가지 가정을했습니다.

  1. 로그온 시간 net user은 DC가 인증을 수행 한 시간입니다. 나는 이것이 사실이라고 생각하지만 그것을 뒷받침 할 구체적인 것을 찾을 수는 없습니다.
  2. 로그온 스크립트는 사용자 셸이로드 될 때 실행됩니다. 그룹 정책에 의해 정의 된 로그온 스크립트와 달리 이전 레거시 NT4 로그온 스크립트를 사용하는 경우에는 확실하지만 GPO 로그온 스크립트가 사용자에게 숨겨져 실행되는 경우 (기본적으로) 그들은 처형된다.
  3. 사용자 이름에 공백이 포함되어 있지 않은 %username%경우 따옴표로 묶어야합니다.
  4. 데이터가 기록 될 월드 쓰기 가능 공유가 있습니다 ( \\server\share위 예에서). 개별 머신에 로컬로 기록 할 수 있지만 결과를 조사하기가 더 어려워집니다.

편집하다:

Jim이 걱정하는 시간 편차를 처리하기 위해 스크립트를 업데이트했습니다. net use명령 의 로그온 시작 시간 은 인증 도메인 컨트롤러의 시계에서 가져옵니다. 이 net time명령은 이제 동일한 서버에서 시간이 걸립니다.


답변