Что нового

[Время, дата] Время работы системы (Uptime)

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Простенькие примеры по определению времени работы системы с использованием встроенных в саму систему функции systeminfo и в язык AutoIt - TimerDiff(0).

Через systeminfo
Код:
#include <Encoding.au3>
Uptime()

Func Uptime()
	If StringInStr("0409 0809 0c09 1009 1409 1809 1c09 2009 2409 2809 2c09 3009 3409", @OSLang) Then
		$sCommand = '"System Up Time"'
		$sPattern = '(?s).+\s(\d+\sDays.*)\r\n'
		$sMessage = 'System Up Time is '
	ElseIf StringInStr('0419', @OSLang) Then
		$sCommand = '"Время работы системы"'
		$sPattern = '(?s).+\s(\d+\sдн\..*)\r\n'
		$sMessage = 'Время работы системы '
	EndIf
	$hGUI = GUICreate('')
	$pid = Run(@ComSpec & ' /c systeminfo | find ' & $sCommand, '', @SW_HIDE, 0x2)
	$s = ''
	While 1
		$line = StdoutRead($pid)
		If @error Then ExitLoop
		If StringLen($line) > 0 Then $s &= $line
	Wend
	$s = StringRegExpReplace(_Encoding_866To1251($s), $sPattern, '\1')
	MsgBox(64, 'System uptime', $sMessage & $s, 0, $hGUI)
	GUIDelete($hGUI)
EndFunc
Для работы скрипта потребуется библиотека http://autoit-script.ru/index.php?topic=510.0

Через TimerDiff
Код:
MsgBox(48, 'System Up Time', 'System UP Time is ' & _UpTime())
Func _UpTime()
	$iMSec = Int(TimerDiff(0))
	$iSec = Int($iMSec/1000)
	$iMSecDev = Mod($iMSec, 1000)
	$sTime = $iSec & 'secs ' & $iMSecDev & 'msecs'
	If $iSec >= 60 Then
		$iMin = Int($iSec/60)
		$iSecDev = Mod($iSec, 60)
		$sTime = $iMin & 'mins ' & $iSecDev & 'secs ' & $iMSecDev & 'msecs'
		If $iMin >= 60 Then
			$iHr = Int($iMin/60)
			$iMinDev = Mod($iMin, 60)
			$sTime = $iHr & 'hrs ' & $iMinDev & 'mins ' & $iSecDev & 'secs ' & $iMSecDev & 'msecs'
			If $iHr >= 24 Then
				$iDay = Int($iHr/24)
				$iHrDev = Mod($iHr, 24)
				$sTime = $iDay & 'days ' & $iHrDev & 'hrs ' & $iMinDev & 'mins ' & $iSecDev & 'secs ' & $iMSecDev & 'msecs'
				If $iDay >= 30 Then
					$iMon = Int($iDay/30)
					$iDayDev = Mod($iDay, 30)
					$sTime = $iMon & 'months ' & $iDayDev & 'days ' & $iHrDev & 'hrs ' & $iMinDev & 'mins ' & $iSecDev & 'secs ' & $iMSecDev & 'msecs'
					If $iMon >= 12 Then
						$iYear = Int($iMon/12)
						$iMonDev = Mod($iMon, 12)
						$sTime = $iYear & 'yrs ' & $iMonDev & 'months ' & $iDayDev & 'days ' & $iHrDev & 'hrs ' & $iMinDev & 'mins ' & $iSecDev & 'secs ' & $iMSecDev & 'msecs'
					EndIf
				EndIf
			EndIf
		EndIf
	EndIF
	Return $sTime
EndFunc

Через WMI (автор - ynbIpb)
Код:
#include <Date.au3>
$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"
$Output = ""
$Output &= "Computer: " & $strComputer & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_PerfFormattedData_PerfOS_System", "WQL", _
        $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
If IsObj($colItems) Then
    For $objItem In $colItems
        $SystemUptime = ($objItem.SystemUpTime / 60)
        Dim $SystemUptimeDay
        Dim $SystemUptimeHour
        Dim $SystemUptimeMin
        Dim $SystemUptimeSec
        $SystemUptimeDay = Int($objItem.SystemUpTime / 86400)
        $SystemUptimeHour = Int($objItem.SystemUpTime / 3600) - ($SystemUptimeDay * 24)
        $SystemUptimeMin = Int($objItem.SystemUpTime / 60) - ($SystemUptimeHour * 60) - ($SystemUptimeDay * 24 * 60)
        $SystemUptimeSec = Int($objItem.SystemUpTime) - ($SystemUptimeMin * 60) - ($SystemUptimeHour * 60 * 60) - ($SystemUptimeDay * 24 * 60 * 60)
        MsgBox(0, "Uptime: ", "Дней: " & $SystemUptimeDay & " Часов: " & $SystemUptimeHour & " Минут: " & $SystemUptimeMin & " Секунд: " & $SystemUptimeSec)
    Next
Else
    MsgBox(0, "Uptime", "No WMI Objects Found for class: " & "Win32_PerfFormattedData_PerfOS_System")
EndIf
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Хороший пример работы, с использованием возможностей системы.
Kaster [?]
Есть, конечно, более изящные методы, типа включения простейшего скрипта в автозагрузку, которая запишет время своего включения в файл или реестр, а в последствии выполнения TimerDiff, но это, как говорится, открыто для желающих
А зачем изобретать велосипед, для того, чтобы узнать то, что в системе уже предусмотрено. :smile:



Добавлено:
Сообщение автоматически объединено:

OffTopic:

Моя система работает уже 3 года и 4 месяца без сбоев и переустановок [восстановление системы отключено] ;D
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Хороший пример, но слишком сложный...

:smile:

_WinAPI_GetTickCount() или _Date_Time_GetTickCount() - возвращают тоже самое, только в миллисекундах.
_WinAPI_GetIdleTime() - возвращает время неактивности.
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Garrett [?]
А зачем изобретать велосипед
Ну, мало ли, у кого какие потребности :smile: Для кого-то использование внешних приложений является чем-то некошерным, для кого-то медленно и т.д.
Странно, что в винде не предусмотрена функция чистого Uptime, как в *nix. Приходится вот так вот извращ парсить


Добавлено:
Сообщение автоматически объединено:

Yashied
:D Пристыдил
Чет я проглядел эту функцию в справке ;D


Добавлено:
Сообщение автоматически объединено:

Garrett [?]
Моя система работает уже 3 года и 4 месяца
Боюсь, тогда мой пример не определит время работы твоей системы ;D
В силу шаблона регвыра
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Kaster сказал(а):
Боюсь, тогда мой пример не определит время работы твоей системы...

Максимально 49.7 дней, потом все по новой.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Yashied [?]
_WinAPI_GetTickCount() или _Date_Time_GetTickCount() - возвращают тоже самое, только в миллисекундах._WinAPI_GetIdleTime - возвращает время неактивности.
По поводу функций не спорю.
Но, пример хорош тем, что любой новичок видит, как можно использовать Avtoit и возможности самой системы.
Уверен, что на форуме возникнет ещё подобный вопрос! А вот справки по UDF, из вопрошающих мало кто сразу читает. Но зато начальные азы программирования IF, For и т. д. все мало-мальки знают.


Добавлено:
Сообщение автоматически объединено:

Kaster [?]
Боюсь, тогда мой пример не определит время работы твоей системы В силу шаблона регвыра
Yashied [?]
Максимально 49.7 дней, потом все по новой.
Это, я уже по дате последней установки OS посчитал ;D
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
OffTopic:
Да, не спорю, я когда-то тоже поленился проштудировать справку, в результате потратил кучу времени на решение не помню уже какой задачи. И каково же было мое разочарование, когда выяснилось, что это делается вызовом всего лишь одной стандартной функцией... Пришлось срочно идти за пивом...

Хотя IMHO здесь как раз и набираешся опыта, и не только в кодинге...

:smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
Хороший пример, но слишком сложный
А вот посложнее :laugh:, но при этом базируется на GetTickCount:

Код:
$sOSUpTime = _OSUpTime(", ", 0)

ConsoleWrite("Ticks:	" & @extended & @LF & "Time:	" & $sOSUpTime & @LF)

Func _OSUpTime($sDelim=", ", $iFlag=0)
	Local $aTicks = DllCall("kernel32.dll", "dword", "GetTickCount")
	If @error Then Return SetError(@error, @extended, 0)
	
	Local $iSeconds = $aTicks[0] / 1000
	
	If StringInStr('0419', @OSLang) Then
		Local $sYear = 'Год', $sYears = 'Года', $s5Years = 'Лет'
		Local $sDay = 'День', $sDays = 'Дня', $s5Days = 'Дней'
		Local $sHour = 'Час', $sHours = 'Часа', $s5Hours = 'Часов'
		Local $sMin = 'Минута', $sMins = 'Минуты', $s5Mins = 'Минут'
		Local $sSec = 'Секунда', $sSecs = 'Секунды', $s5Secs = 'Секунд'
	Else
		Local $sYear = 'Year', $sYears = 'Years', $s5Years = 'Years'
		Local $sDay = 'Day', $sDays = 'Days', $s5Days = 'Days'
		Local $sHour = 'Hour', $sHours = 'Hours', $s5Hours = 'Hours'
		Local $sMin = 'Second', $sSecs = 'Seconds', $s5Secs = 'Seconds'
	EndIf
	
	If Number($iSeconds) >= 0 Then
		Local $iTicks = Int($iSeconds / 3600), $iDays, $iYears
		Local $iHours = Mod($iTicks, 24)
		
		If $iTicks >= 24 Then $iDays = ($iTicks - $iHours) / 24
		
		If $iDays >= 365 Then
			$iYears = Int($iDays / 365)
			
			If ($iYears >= 20 And StringRight($iYears, 1) >= 2) Or ($iYears < 20 And $iYears >= 2) Then $sYear = $sYears
			If ($iYears >= 20 And (StringRight($iYears, 1) >= 5 Or StringRight($iYears, 1) < 1)) Or ($iYears < 20 And $iYears >= 5) Then $sYear = $s5Years
			
			$iYears &= " " & $sYear & $sDelim
		EndIf
		
		If $iDays > 0 Then
			$iDays = Mod($iDays, 365)
			
			If ($iDays >= 20 And StringRight($iDays, 1) >= 2) Or ($iDays < 20 And $iDays >= 2) Then $sDay = $sDays
			If ($iDays >= 20 And (StringRight($iDays, 1) >= 5) Or StringRight($iDays, 1) < 1) Or ($iDays < 20 And $iDays >= 5) Then $sDay = $s5Days
			
			$iDays &= " " & $sDay & $sDelim
		EndIf
		
		$iTicks = Mod($iSeconds, 3600)
		
		Local $iMins = Int($iTicks / 60)
		Local $iSecs = Round(Mod($iTicks, 60))
		
		If $iFlag = 1 Then
			If StringLen($iHours) = 1 Then $iHours = "0" & $iHours
			If StringLen($iMins) = 1 Then $iMins = "0" & $iMins
			If StringLen($iSecs) = 1 Then $iSecs = "0" & $iSecs
		EndIf
		
		If ($iHours >= 20 And StringRight($iHours, 1) >= 2) Or ($iHours < 20 And $iHours >= 2) Then $sHour = $sHours
		If ($iHours >= 20 And (StringRight($iHours, 1) >= 5 Or StringRight($iHours, 1) < 1)) Or ($iHours < 20 And $iHours >= 5) Then $sHour = $s5Hours
		
		If ($iMins >= 20 And StringRight($iMins, 1) >= 2) Or ($iMins < 20 And $iMins >= 2) Then $sMin = $sMins
		If ($iMins >= 20 And (StringRight($iMins, 1) >= 5 Or StringRight($iMins, 1) < 1)) Or ($iMins < 20 And $iMins >= 5) Then $sMin = $s5Mins
		
		If ($iSecs >= 20 And StringRight($iSecs, 1) >= 2) Or ($iSecs < 20 And $iSecs >= 2) Then $sSec = $sSecs
		If ($iSecs >= 20 And (StringRight($iSecs, 1) >= 5 Or StringRight($iSecs, 1) < 1)) Or ($iSecs < 20 And $iSecs >= 5) Then $sSec = $s5Secs
		
		$iHours &= " " & $sHour
		$iMins &= " " & $sMin
		$iSecs &= " " & $sSec
		
		SetExtended($aTicks[0])
		Return $iYears & $iDays & $iHours & $sDelim & $iMins & $sDelim & $iSecs
	EndIf
	
	Return SetError(2, $aTicks[0], 0)
EndFunc


P.S
Данная форма “извращения”, очень хорошо показывает, насколько велик наш могучий русский язык!
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
Я же написал выше, что максимальное значение 49.7 дней.
Это выдержка из другой функций, где просто конвертируются секунды в строковое представление времени. Я немного подкорректировав использовал её в целях данной темы.

P.S
А это ограничение никак не обойти?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Это значение в пределах DWORD, можно отслеживать переполнение (обнуление). Видимо Microsoft не предполагала, что ее система может беспроблемно работать больше этого срока.

:smile:

P.S

Для Vist'ы сделали GetTickCount64(), но теряется универсальность.
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
я конечно не проверял, но systeminfo Тоже будет показывать в пределах 50 дней?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
В XP по идее должен тоже.
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
OffTopic:
просто работаю ведь серваки годами и под управлением винды в том числе, пусть хоть win2k3. неужели там не предусмотрено что-то большее чем 50 дней...
мой работает уже дней 20. проверю на досуге :smile:
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
Вот нашёл на англ. форуме (не помню точно где)
Код:
#include <Date.au3>
$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"
$Output = ""
$Output &= "Computer: " & $strComputer & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_PerfFormattedData_PerfOS_System", "WQL", _
        $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
If IsObj($colItems) Then
    For $objItem In $colItems
        $SystemUptime = ($objItem.SystemUpTime / 60)
        Dim $SystemUptimeDay
        Dim $SystemUptimeHour
        Dim $SystemUptimeMin
        Dim $SystemUptimeSec
        $SystemUptimeDay = Int($objItem.SystemUpTime / 86400)
        $SystemUptimeHour = Int($objItem.SystemUpTime / 3600) - ($SystemUptimeDay * 24)
        $SystemUptimeMin = Int($objItem.SystemUpTime / 60) - ($SystemUptimeHour * 60) - ($SystemUptimeDay * 24 * 60)
        $SystemUptimeSec = Int($objItem.SystemUpTime) - ($SystemUptimeMin * 60) - ($SystemUptimeHour * 60 * 60) - ($SystemUptimeDay * 24 * 60 * 60)
        MsgBox(0, "Uptime: ", "Дней: " & $SystemUptimeDay & " Часов: " & $SystemUptimeHour & " Минут: " & $SystemUptimeMin & " Секунд: " & $SystemUptimeSec)
    Next
Else
    MsgBox(0, "Uptime", "No WMI Objects Found for class: " & "Win32_PerfFormattedData_PerfOS_System")
EndIf
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Да, это должно работать, но смущает одно:

Microsoft сказал(а):
SystemUpTime

Data type: uint64

Elapsed time, in seconds, that the computer has been running after it was last started. This property displays the difference between the start time and the current time.

Что значит разница между временем запуска и текущем?



Добавлено:
Сообщение автоматически объединено:

Да, проверил, это не счетчик. Если я изменю время на компьютере, то изменится и результат в SystemUpTime. Так что польза от этого резко стремится к 0.

:(
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Кстати, TimerDiff(0) возвращает тоже самое что и GetTickCount :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А где ты это откопал?
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Как и обещал, прошло уже 51 дней с работы моей машины. systeminfo исправно возвратил это значение.
 
Верх