Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Событие и код перехода на питание от батареи (http://forum.oszone.net/showthread.php?t=301445)

n_i_x 21-06-2015 08:57 2520628

[решено] Событие и код перехода на питание от батареи
 
Здравствуйте! Есть одна задумка. Хочу создать определённые задания в планировщике задач, которые бы запускались при переходе на питание от батареи. Не могу определить тригер для этого. То есть запуск задачи при событии, а вот журнал, источник и код события не могу найти. Бродил на TechNet, но ничего подходящего не смог найти. Может быть есть какой-то альтернативный вариант, то есть запуск задания по какому-то другому условию, которое в свою очередь всегда выполняется системой при переходе на питание от батареи?

Blast 21-06-2015 09:36 2520638

Говорят, что 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 2520646

а как с помощью этого скрипта добавить журналирование?

Blast 21-06-2015 10:44 2520654

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

На GitHub есть другой скрипт, который основан на этом: Get and Log Battery and Power Levels using Powershell
Правда он развесистый и мониторит не только подключение/отключение, при желании можете его отредактировать под себя, благо он с комментариями.

Попробуйте, расскажите как и что :)
Код:

#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 2520687

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

Iska 21-06-2015 12:14 2520691

Цитата:

Цитата Blast
Если получится записывать в журнал состояние отключения питания от сети, сможете и триггер по событию из журнала настроить, »

Тут, наверное, и писать в журнал не обязательно, а можно сразу в том же скрипте:
Цитата:

Цитата n_i_x
определённые задания … которые бы запускались при переходе на питание от батареи. »


Blast 21-06-2015 12:48 2520707

Цитата:

Цитата n_i_x
работал нормально до перезагрузки, после не работает, так как не может зарегистрировать себя в журнале, ругается на то, что такое уже существует »

Он не ругается, а сообщает :) Но продолжает отслеживать и помещать события в журнал. Если хотите, можете просто удалить первую строку из скрипта. Вы же запуск правильно делаете?
Код:

powershell -file <путь к файлу>\имя_файла.ps1
Если путь с кириллицей или пробелами, то в кавычки.
Цитата:

Цитата n_i_x
второй работает, но слегка чудит »

Ну да, там же каждую секунду отслеживается куча всего, что вам не нужно, надо править под себя, но... оно вам не надо.
Цитата:

Цитата Iska
Тут, наверное, и писать в журнал не обязательно »

Здраво, так наверное проще даже.

n_i_x 21-06-2015 13:40 2520722

да запускаю именно так.
а во втором 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 2520738

Цитата:

Цитата n_i_x
да запускаю именно так »

Добавьте проверку по примеру второго
Код:

$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 (;;) {}

.
Цитата:

Цитата n_i_x
а во втором 2 одинаковых кода на разные события »

А второй мне лень смотреть :) коды - да, события - нет.

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

n_i_x 21-06-2015 15:13 2520756

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

Blast 21-06-2015 16:25 2520773

Цитата:

Цитата n_i_x
как разделить сообщение с одинаковыми кодами, но разными событиями »

Зачем? Сделайте разные коды (та часть, которую вы приводили выше):
Код:

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 2520813

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

n_i_x 21-06-2015 18:41 2520816

Блин! Огромное человеческое спасибо!!!!!

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

Blast 21-06-2015 20:24 2520838

В таком случае можно опять же обойтись без записей в журналы событий (незачем их загаживать чем попало).

Примерно так (требуется проверка, спешил, мог напортачить):
Код:

$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 2581658

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


Время: 05:37.

Время: 05:37.
© OSzone.net 2001-