Войти

Показать полную графическую версию : [решено] Событие и код перехода на питание от батареи


n_i_x
21-06-2015, 08:57
Здравствуйте! Есть одна задумка. Хочу создать определённые задания в планировщике задач, которые бы запускались при переходе на питание от батареи. Не могу определить тригер для этого. То есть запуск задачи при событии, а вот журнал, источник и код события не могу найти. Бродил на TechNet, но ничего подходящего не смог найти. Может быть есть какой-то альтернативный вариант, то есть запуск задания по какому-то другому условию, которое в свою очередь всегда выполняется системой при переходе на питание от батареи?

Blast
21-06-2015, 09:36
Говорят, что Windows не пишет в журнал событие подключения/отключения питания, предлагают писать его при помощи PS:New-EventLog -Source BatteryStatusMonitor -LogName Application

Function OnBatteryStatusChange ($NewStatus) {
If ($NewStatus -eq 1) {
$EventID = 5001
$Message = "The computer was unplugged."
} ElseIf ($NewStatus -eq 2) {
$EventID = 5002
$Message = "The computer was plugged in."
} Else {
$EventID = 5000
$Message = "Battery status changed to $NewStatus"
}
Write-EventLog -LogName Application -Source BatteryStatusMonitor -EventID $EventID -Message $Message
}

$Query = "select * from __instancemodificationevent within 3 where targetinstance isa 'win32_battery' and targetinstance.batterystatus <> previousinstance.batterystatus"

Register-WmiEvent -Query $Query -Action {OnBatteryStatusChange $Event.SourceEventArgs.NewEvent.TargetInstance.BatteryStatus} -SourceIdentifier "BatteryStatusChange"

For (;;) {}
Если получится записывать в журнал состояние отключения питания от сети, сможете и триггер по событию из журнала настроить, в данном примере по событию с кодом 5001.

Источник: http://superuser.com/a/389853

n_i_x
21-06-2015, 10:21
а как с помощью этого скрипта добавить журналирование?

Blast
21-06-2015, 10:44
n_i_x, сохранить его как .ps1 и запустить, полагаю. Для ежедневного использования поместить в автозапуск или лучше в планировщик. Потом смотрите события в журнале Приложение - найдите событие с кодом 5001 и источником BatteryStatusMonitor - по правой кнопке мыши на нем - Привязать задачу к событию...

На GitHub есть другой скрипт, который основан на этом: Get and Log Battery and Power Levels using Powershell (http://www.rivnet.ro/2010/05/log-battery-and-power-levels-using-powershell.html)
Правда он развесистый и мониторит не только подключение/отключение, при желании можете его отредактировать под себя, благо он с комментариями.

Попробуйте, расскажите как и что :)
#Battery Monitor Script 0.2
# based on http://www.rivnet.ro/2010/05/log-battery-and-power-levels-using-powershell.html


#-------------------------------
# You can modify the following settings to fit your needs

# Check interval to detect power changes
$checkInterval = 1
# Log interval in seconds when on battery power.
$batteryLogInterval = 60
# Log interval in seconds when on AC power.
$acLogInterval = 3600

# Log warning instead of info if battery power below given percentage
$batteryLogWarn = 15

#-------------------------------



#create custom event-log if it doesn't exist already
$condition = ((get-wmiobject -class "Win32_NTEventlogFile" | where {$_.LogFileName -like 'BatteryMonitor'} | measure-object ).count -eq '0')
if($condition) {
'create event log'
New-EventLog -Source BattMon -LogName BatteryMonitor
}

#signal script execution start
Write-EventLog -LogName BatteryMonitor -Source BattMon -EventID 0 -Message 'Starting new Execution of BatteryCharge Monitor Script' -EntryType Information -ComputerName $env:computername -ErrorAction:SilentlyContinue

$prevBatteryStatus = 2
$prevLogTime = 0

do {
#clear any previous values
$PowstatMsg = $null
$ChargeRemMsg = $null
$ChargeRem = $null
$RemTimeMsg = $null

#create a Message object that we can add values to
$Message = ''
$Message = $Message | select-object *,PowStatMsg,ChargeRemMsg,RemTimeMsg


$batt = Get-WmiObject -Class Win32_Battery
#1 means on battery, 2 on ac power
If ($batt.BatteryStatus -like '1') {
$Message.PowstatMsg = 'On_Battery'
'PowerStatus: On_Battery' }
elseif ($batt.BatteryStatus -like '2') {
$Message.PowstatMsg = 'AC_Power'
'PowerStatus: AC_Power' }


#If charge is larger than 100, it means it is full/on ac power
if ($batt.EstimatedChargeRemaining -lt '100') {
'EstimatedChargeRemaining: ' + $batt.EstimatedChargeRemaining + '%'
$Message.ChargeRemMsg = "{0:P0}" -f ($batt.EstimatedChargeRemaining/100)
$ChargeRem = $batt.EstimatedChargeRemaining
} else {
'EstimatedChargeRemaining: 100%'
$Message.ChargeRemMsg = "{0:P0}" -f 1
$ChargeRem = 100
}

#If estimated minutes is an absurdly high value, it means we are on AC power
if ($batt.EstimatedRUntime -lt '9999') {
'EstimatedRunTime: ' + $batt.EstimatedRunTime + 'min'
$Message.RemTimeMsg = $batt.EstimatedRunTime }
else {
$Message.RemTimeMsg = 'N/A' }

If ($batt.BatteryStatus -ne $prevBatteryStatus) {
if ($prevBatteryStatus -like '2') {
$EventMsg = "Switched to Battery Power! $($Message.ChargeRemMsg), Minutes: $($Message.RemTimeMsg)"
} else {
$EventMsg = "Switched back to AC Power! $($Message.ChargeRemMsg), Minutes: $($Message.RemTimeMsg)"
}
Write-EventLog -LogName BatteryMonitor -Source BattMon -EventID 10 -Message $EventMsg -EntryType Warning -ComputerName $env:computername -ErrorAction:SilentlyContinue
$prevLogTime = New-TimeSpan "01 January 1970 00:00:00" $(Get-Date)
}
$prevBatteryStatus = $batt.BatteryStatus

$currLogTime = New-TimeSpan "01 January 1970 00:00:00" $(Get-Date)
$diff = $currLogTime.TotalSeconds - $prevLogTime.TotalSeconds

if ($prevBatteryStatus -like '2') {
#AC Power
if ($diff -ge $acLogInterval) {
$EventMsg = "$($Message.PowStatMsg), $($Message.ChargeRemMsg), $($Message.RemTimeMsg)"
Write-EventLog -LogName BatteryMonitor -Source BattMon -EventID 100 -Message $EventMsg -EntryType Information -ComputerName $env:computername -ErrorAction:SilentlyContinue
$prevLogTime = New-TimeSpan "01 January 1970 00:00:00" $(Get-Date)
}
} elseif ($prevBatteryStatus -like '1') {
# Battery power
if ($diff -ge $batteryLogInterval) {
$EventMsg = "$($Message.PowStatMsg), $($Message.ChargeRemMsg), $($Message.RemTimeMsg)"
if ($ChargeRem -le $batteryLogWarn) {
Write-EventLog -LogName BatteryMonitor -Source BattMon -EventID 200 -Message $EventMsg -EntryType Warning -ComputerName $env:computername -ErrorAction:SilentlyContinue
} else {
Write-EventLog -LogName BatteryMonitor -Source BattMon -EventID 200 -Message $EventMsg -EntryType Information -ComputerName $env:computername -ErrorAction:SilentlyContinue
}
$prevLogTime = New-TimeSpan "01 January 1970 00:00:00" $(Get-Date)
}
}

Sleep $checkInterval
}
while (1)

n_i_x
21-06-2015, 12:08
первый скрипт запустился, и работал нормально до перезагрузки, после не работает, так как не может зарегистрировать себя в журнале, ругается на то, что такое уже существует. второй работает, но слегка чудит с логами)
если выдернуть шнур то кидает сообщение, о том что переключено питание на батарею, если воткнуть шнур обратно, то выдаёт что переключен на питание от батареи или на питание от сети, всегда по разному, но номер события один и тот же 10))

Iska
21-06-2015, 12:14
Если получится записывать в журнал состояние отключения питания от сети, сможете и триггер по событию из журнала настроить, »
Тут, наверное, и писать в журнал не обязательно, а можно сразу в том же скрипте:
определённые задания … которые бы запускались при переходе на питание от батареи. »

Blast
21-06-2015, 12:48
работал нормально до перезагрузки, после не работает, так как не может зарегистрировать себя в журнале, ругается на то, что такое уже существует »
Он не ругается, а сообщает :) Но продолжает отслеживать и помещать события в журнал. Если хотите, можете просто удалить первую строку из скрипта. Вы же запуск правильно делаете?powershell -file <путь к файлу>\имя_файла.ps1Если путь с кириллицей или пробелами, то в кавычки.
второй работает, но слегка чудит »
Ну да, там же каждую секунду отслеживается куча всего, что вам не нужно, надо править под себя, но... оно вам не надо.
Тут, наверное, и писать в журнал не обязательно »
Здраво, так наверное проще даже.

n_i_x
21-06-2015, 13:40
да запускаю именно так.
а во втором 2 одинаковых кода на разные события

If ($batt.BatteryStatus -ne $prevBatteryStatus) {
if ($prevBatteryStatus -like '2') {
$EventMsg = "Switched to Battery Power! $($Message.ChargeRemMsg), Minutes: $($Message.RemTimeMsg)"
} else {
$EventMsg = "Switched back to AC Power! $($Message.ChargeRemMsg), Minutes: $($Message.RemTimeMsg)"
}
Write-EventLog -LogName BatteryMonitor -Source BattMon -EventID 10 -Message $EventMsg -EntryType Warning -ComputerName $env:computername -ErrorAction:SilentlyContinue

стоит ли удалять второе сообщение?

Blast
21-06-2015, 14:10
да запускаю именно так »
Добавьте проверку по примеру второго$condition = ((get-wmiobject -class "Win32_NTEventlogFile" | where {$_.LogFileName -like 'Application'} | measure-object ).count -eq '0')
if($condition) {
'create event log'
New-EventLog -Source BatteryStatusMonitor -LogName Application
}

Function OnBatteryStatusChange ($NewStatus) {
If ($NewStatus -eq 1) {
$EventID = 5001
$Message = "The computer was unplugged."
} ElseIf ($NewStatus -eq 2) {
$EventID = 5002
$Message = "The computer was plugged in."
} Else {
$EventID = 5000
$Message = "Battery status changed to $NewStatus"
}
Write-EventLog -LogName Application -Source BatteryStatusMonitor -EventID $EventID -Message $Message
}

$Query = "select * from __instancemodificationevent within 3 where targetinstance isa 'win32_battery' and targetinstance.batterystatus <> previousinstance.batterystatus"

Register-WmiEvent -Query $Query -Action {OnBatteryStatusChange $Event.SourceEventArgs.NewEvent.TargetInstance.BatteryStatus} -SourceIdentifier "BatteryStatusChange"

For (;;) {}.а во втором 2 одинаковых кода на разные события »А второй мне лень смотреть :) коды - да, события - нет.

Первый я проверял, все нормально работает, в том числе и через планировщик скрывая окно PS. События регистрируются, поставленная вами задача выполняется, что еще надо? :)

n_i_x
21-06-2015, 15:13
1 вариант простой и более подходящий, но когда этот скрипт активен, то нагрузка на систему возрастает сильно, аж вентилятор сильней крутится начинает)
остановился на 2 варианте, пытаюсь в нём разобраться сейчас, как разделить сообщение с одинаковыми кодами, но разными событиями

Blast
21-06-2015, 16:25
как разделить сообщение с одинаковыми кодами, но разными событиями »
Зачем? Сделайте разные коды (та часть, которую вы приводили выше):If ($batt.BatteryStatus -ne $prevBatteryStatus) {
if ($prevBatteryStatus -like '2') {
$EventID = 10
$EventMsg = "Switched to Battery Power! $($Message.ChargeRemMsg), Minutes: $($Message.RemTimeMsg)"
} else {
$EventID = 11
$EventMsg = "Switched back to AC Power! $($Message.ChargeRemMsg), Minutes: $($Message.RemTimeMsg)"
}
Write-EventLog -LogName BatteryMonitor -Source BattMon -EventID $EventID -Message $EventMsg -EntryType Warning -ComputerName $env:computername -ErrorAction:SilentlyContinue

Blast
21-06-2015, 18:26
А в принципе, по первоначальной постановке вопроса я понял, что вам вам не нужно ежесекундный отчет в консоли, запись в журнал событий о запуске скрипта, о низком заряде батареи и т.д. Вам ведь нужно только, чтобы в журнал записывалось событие при отключении от сети и переход на питание от батареи? Если так, то скрипт можно существенно сократить - batterylog_0.zip
А если целью был просто запуск приложения при переходе на питание от батареи, то берите batterylog_1.zip и поправьте в нем путь к запуску программы в строке 12. Если программу нужно запускать с параметрами, то параметры указывайте за кавычками. Вместо C:\Program Files\ можете использовать переменную $env:ProgramFiles
Скрипт спокойно запускается из планировщика и при соответствующей настройке задачи не показывает свое окно.

n_i_x
21-06-2015, 18:41
Блин! Огромное человеческое спасибо!!!!!

Изначально у меня была задумка, что бы при переходе на питание от батареи, автоматически менялась тема оформления с заставки на чёрный фон, закрытие определённых приложений и тому подобное, а при переходе на питание от электросети возвращалось всё обратно. Всё подготовил для этого, но вот с событиями батареи запнулся)

Blast
21-06-2015, 20:24
В таком случае можно опять же обойтись без записей в журналы событий (незачем их загаживать чем попало).

Примерно так (требуется проверка, спешил, мог напортачить):
$checkInterval = 1
$prevBatteryStatus = 2
$prevLogTime = 0

do {
$batt = Get-WmiObject -Class Win32_Battery

If ($batt.BatteryStatus -ne $prevBatteryStatus) {
if ($prevBatteryStatus -like '2') {
& "<путь к батнику, который меняет настройки при работе от батареи>"
} else {

& "<путь к батнику, который меняет настройки при работе от сети>"
}

}
$prevBatteryStatus = $batt.BatteryStatus

$currLogTime = New-TimeSpan "01 January 1970 00:00:00" $(Get-Date)
$diff = $currLogTime.TotalSeconds - $prevLogTime.TotalSeconds

Sleep $checkInterval
}
while (1)

bonderlogin
05-12-2015, 12:40
Здравствуйте. Последний скрипт хорош, и мне подходит для одной из задач. Но я так понял, что он не просто проверяет состояние питания, а сравнивает его с предыдущим, работая циклически? А для второй моей задачи нужно просто единоразово запустить подобный скрипт, чтобы он, в свою очередь, выполнил действия в зависимости от типа питания (как и в предыдущем примере) и завершился. Как его отредактировать для этих целей?




© OSzone.net 2001-2012