Member 14545110 Ответов: 3

Хотите получить уведомление от ИБП(источника бесперебойного питания) в моем приложении C# window


Я работаю над тем, где мне нужно получить уведомление, когда источник питания прерван. несколько кодов, которые используют Win32_Battry и Win32_PowerSupplySatus dll - файл для отображения состояния источника питания. но это работает только для портативного компьютера. Потому что у них есть аккумулятор. Но в настольном компьютере нет никакой батареи. Поэтому я не получаю никакого ответа на рабочий стол. Кроме всего прочего, мне нужен код на C# для получения уведомления, когда основной источник питания выключен и настольная система работает на ИБП. Пожалуйста, помогите мне..

Что я уже пробовал:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Runtime.InteropServices;

public enum ACLineStatus : byte
	{
	Offline = 0,
	Online = 1,
	Unknown = 255,
	}

public enum BatteryFlag : byte
	{
	High = 1,
	Low = 2,
	Critical = 4,
	Charging = 9,
	NoSystemBattery = 128,
	Unknown = 255
	}

// mirrors the unmanaged counterpart
[StructLayout(LayoutKind.Sequential)]
public class SystemPowerStatus
	{
	public ACLineStatus ACLineStatus;
	public BatteryFlag BatteryFlag;
	public Byte BatteryLifePercent;
	public Byte Reserved1;
	public Int32 BatteryLifeTime;
	public Int32 BatteryFullLifeTime;
	}

class Win32PowerManager
	{
	[DllImport("Kernel32")]
	private static extern Boolean GetSystemPowerStatus(SystemPowerStatus sps);

	public static SystemPowerStatus GetSystemPowerStatus()
		{
		SystemPowerStatus sps = new SystemPowerStatus();
		GetSystemPowerStatus(sps);
		return sps;
		}

	[Flags]
	public enum ExitWindowsBits : uint
		{
		// ONE of the following five:
		LogOff = 0x00,
		ShutDown = 0x01,
		Reboot = 0x02,
		PowerOff = 0x08,
		RestartApps = 0x40,
		// plus AT MOST ONE of the following two:
		Force = 0x04,
		ForceIfHung = 0x10,
		}

	[Flags]
	public enum ShutdownReasonBits : uint
		{
		MajorApplication = 0x00040000,
		MajorHardware = 0x00010000,
		MajorLegacyApi = 0x00070000,
		MajorOperatingSystem = 0x00020000,
		MajorOther = 0x00000000,
		MajorPower = 0x00060000,
		MajorSoftware = 0x00030000,
		MajorSystem = 0x00050000,

		MinorBlueScreen = 0x0000000F,
		MinorCordUnplugged = 0x0000000b,
		MinorDisk = 0x00000007,
		MinorEnvironment = 0x0000000c,
		MinorHardwareDriver = 0x0000000d,
		MinorHotfix = 0x00000011,
		MinorHung = 0x00000005,
		MinorInstallation = 0x00000002,
		MinorMaintenance = 0x00000001,
		MinorMMC = 0x00000019,
		MinorNetworkConnectivity = 0x00000014,
		MinorNetworkCard = 0x00000009,
		MinorOther = 0x00000000,
		MinorOtherDriver = 0x0000000e,
		MinorPowerSupply = 0x0000000a,
		MinorProcessor = 0x00000008,
		MinorReconfig = 0x00000004,
		MinorSecurity = 0x00000013,
		MinorSecurityFix = 0x00000012,
		MinorSecurityFixUninstall = 0x00000018,
		MinorServicePack = 0x00000010,
		MinorServicePackUninstall = 0x00000016,
		MinorTermSrv = 0x00000020,
		MinorUnstable = 0x00000006,
		MinorUpgrade = 0x00000003,
		MinorWMI = 0x00000015,

		FlagUserDefined = 0x40000000,
		FlagPlanned = 0x80000000
		}

	[DllImport("user32.dll")]
	static extern bool ExitWindowsEx(ExitWindowsBits uFlags, ShutdownReasonBits dwReason);

	[STAThread]
	public static bool ShutDown()
		{
		return ExitWindowsEx(ExitWindowsBits.PowerOff | ExitWindowsBits.Force,
						ShutdownReasonBits.MajorPower | ShutdownReasonBits.MinorCordUnplugged);
		}
	}


Но приведенный выше код работает для laptop.it не работайте на настольном компьютере. я хочу, когда я выключаю основной источник питания и мой рабочий стол работает от ИБП. затем он показывает в автономном режиме.

3 Ответов

Рейтинг:
20

RickZeeland

Это сложный вопрос, вы можете посмотреть в журнал событий Windows если есть какие-либо предупреждения от ИБП и триггера по этому поводу.

EventLog eventLogSource = new EventLog("System");

Вот вам фрагмент кода, который вы можете попробовать в консольном приложении, боюсь, он немного загадочен:
namespace EventLogCheck
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;

    class Program
    {
        private const string EventSource = "MyProgramName";

        private static bool Running = true;

        /// <summary>
        /// The windows event log to watch, e.g. "System".
        /// </summary>
        private static EventLog eventLogSource;

        /// <summary>
        /// The event log warning type(s) to watch, e.g. "Warning,Error".
        /// </summary>
        private static string eventlogWarningType;

        /// <summary>
        /// The last eventlog warning or error number (as filtered by EventlogSource and EventlogWarningType settings).
        /// </summary>
        private static volatile int lastEventlogWarning;

        /// <summary>
        /// Disk strings to check in EventLog, e.g. "Disk"
        /// </summary>
        private static volatile string diskEventCheck;

        /// <summary>
        /// Disk strings to check in EventLog, e.g. "Disk"
        /// </summary>
        private static List<string> diskEventCheckList = new List<string>();

        /// <summary>
        /// PSU strings to check in EventLog, e.g. "power supply, power supplies".
        /// </summary>
        private static volatile string psuEventCheck;

        /// <summary>
        /// PSU strings List to check in EventLog, e.g. "power supply, power supplies".
        /// </summary>
        private static List<string> psuEventCheckList = new List<string>();

        private static bool psuEventError;

        private static bool diskEventError;

        static void Main(string[] args)
        {
            Check();
        }

        private static void Check()
        {
            Task checkEventlog = null;
            psuEventCheck = "power supply, power supplies";
            eventLogSource = new EventLog("System");
            eventlogWarningType = "Error";
            CheckEventlogInit(eventLogSource, eventlogWarningType);
            checkEventlog = Task.Factory.StartNew(() => CheckEventlog(eventLogSource, eventlogWarningType));

            // Enter the loop and wait 10 seconds between tests.
            // When a task has finished, start a new one.
            while (Running)
            {
                if (checkEventlog != null)
                {
                    if (checkEventlog.IsCompleted)
                    {
                        checkEventlog.Dispose();
                        checkEventlog = Task.Factory.StartNew(() => CheckEventlog(eventLogSource, eventlogWarningType));
                    }
                }

                var stopwatch = new Stopwatch();
                stopwatch.Reset();
                stopwatch.Start();

                while ((stopwatch.ElapsedMilliseconds < 10000) && Running)
                {
                    // Avoid high CPU usage by tight loop.
                    Thread.CurrentThread.Join(100);
                }

                stopwatch.Stop();
            }
        }

        /// <summary>
        /// Find the index number of the last eventlog warning or error,
        /// and set the <see cref="lastEventlogWarning"/> index number.
        /// </summary>
        /// <param name="eventLogSource1">The event Log Source to monitor, e.g. EventLog("Application")</param>
        /// <param name="eventlogWarningType1">The eventlog Warning Type(s), e.g. "Warning,Error".</param>
        private static void CheckEventlogInit(EventLog eventLogSource1, string eventlogWarningType1)
        {
            int count = eventLogSource1.Entries.Count;
            int count2 = 0;
            lastEventlogWarning = 0;

            try
            {
                if (count < 1)
                {
                    return;
                }

                count2 = Math.Max(0, count - 20);
                lastEventlogWarning = eventLogSource1.Entries[count - 1].Index;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in CheckEventlogInit() " + ex.Message);
                return;
            }

            // Search only the top 20 entries.
            for (int i = count - 1; i >= count2; i--)
            {
                try
                {
                    var warningType = eventLogSource1.Entries[i].EntryType.ToString();

                    // Filter the wanted warning type(s).
                    if (eventlogWarningType1.ToLower().Contains(warningType.ToLower()))
                    {
                        if (!eventLogSource1.Entries[i].Source.Equals(EventSource))
                        {
                            ////Debug.Print(eventLogSource1.Entries[i].Message);
                            lastEventlogWarning = eventLogSource1.Entries[i].Index;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error in CheckEventlogInit() for " + ex.Message);
                }
            }

            psuEventCheckList.Clear();
            diskEventCheckList.Clear();

            // Add the PSU event error strings to check
            if (!string.IsNullOrEmpty(psuEventCheck))
            {
                var psuArr = psuEventCheck.Split(',');

                foreach (var extra in psuArr)
                {
                    psuEventCheckList.Add(extra.Trim());
                }
            }

            // Add the disk event error strings to check
            if (!string.IsNullOrEmpty(diskEventCheck))
            {
                var diskArr = diskEventCheck.Split(',');

                foreach (var extra in diskArr)
                {
                    diskEventCheckList.Add(extra.Trim());
                }
            }
        }

        /// <summary>
        /// Check the Windows event log for new warnings and/or errors.
        /// Skip 'Client Application exit'.
        /// </summary>
        /// <param name="eventLogSource1">The event Log Source to monitor, e.g. EventLog("Application")</param>
        /// <param name="eventlogWarningType1">The eventlog Warning Type(s), e.g. "Warning,Error".</param>
        private static void CheckEventlog(EventLog eventLogSource1, string eventlogWarningType1)
        {
            try
            {
                int count = eventLogSource1.Entries.Count;
                int count2 = Math.Max(0, count - 20);
                bool psuEventCleared = false;
                diskEventError = false;

                for (int i = count - 1; i >= count2; i--)
                {
                    if (lastEventlogWarning >= eventLogSource1.Entries[i].Index)
                    {
                        // Show new warnings up to last warning.
                        break;
                    }

                    var warningType = eventLogSource1.Entries[i].EntryType.ToString();
                    var message = eventLogSource1.Entries[i].Message;

                    // Check if PSU error message has to be cleared.
                    if (psuEventError)
                    {
                        if (message.ToLower().Contains(@"power supply") && (message.ToLower().Contains(@"operating correctly") || warningType.Equals("Information")))
                        {
                            // Clear the error status
                            psuEventError = false;
                            psuEventCleared = true;
                        }
                    }

                    // Filter the wanted warning type(s).
                    if (eventlogWarningType1.ToLower().Contains(warningType.ToLower()))
                    {
                        // Skip "MyProgram" warnings.
                        if (!eventLogSource1.Entries[i].Source.Equals(EventSource))
                        {
                            // Check for disk error messages
                            foreach (var diskString in diskEventCheckList)
                            {
                                if (message.Contains(diskString))
                                {
                                    diskEventError = true;
                                }
                            }

                            // Check if PSU error message has to be sent
                            if (!psuEventError && !psuEventCleared)
                            {
                                foreach (var psuString in psuEventCheckList)
                                {
                                    if (message.Contains(psuString))
                                    {
                                        psuEventError = true;
                                        Console.WriteLine(message);
                                    }
                                }
                            }

                            lastEventlogWarning = eventLogSource1.Entries[i].Index;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in CheckEventlog() " + ex.Message);
            }
        }
    }
}


Member 14545110

публичный статический пустота главный()
{
// проверьте наличие источника журнала событий на указанной машине
// источник журнала событий приложения на MCBcomputer
если (!EventLog.Exists("Application", "Intel"))
{
Приставка.WriteLine("журнал не существует!");
вернуть;
}
EventLog myLog = новый журнал событий();
мой_журнал.Log = "Приложение";
мой_журнал.Имякомпьютера = "Интел";
Приставка.WriteLine("есть" + myLog.Записи.Count + " entr[y|ies] в журнале приложений:");
по каждому элементу (записи, EventLogEntry в мой_журнал.Записи)
{
Приставка.WriteLine("\tEntry: "+ entry.Message);
}
// проверьте наличие источника демо-журнала событий
// создайте его, если он не существует
если (!Журнал событий.SourceExists("Демо"))
{
Журнал событий.CreateEventSource("Демо", "Демо");
}
Журнал событий.WriteEntry("AnySource", "ошибка записи в демо-журнал.",
EventLogEntryType.Error);
Приставка.WriteLine("мониторинг журнала событий приложения начался...");
Приставка.WriteLine(@"нажмите "q" и "Enter", чтобы выйти");
в то время как (консоль.Read() != 'q')
{
/ Теперь мы будем следить за новыми записями, которые будут написаны.
// При создании делегата EntryWrittenEventHandler
// вы определяете метод, который будет обрабатывать событие.
мой_журнал.EntryWritten += новый EntryWrittenEventHandler(OnEntryWritten);
// EnableRaisingEvents получает или задает значение, указывающее, является ли
// Журнал экземпляр получает EntryWritten уведомления о событиях.
мой_журнал.EnableRaisingEvents = true;
}
}
общественная статический недействительным OnEntryWritten(источник, объект, EntryWrittenEventArgs е)
{
Приставка.WriteLine("письменная запись:" + e.Entry.Message);
}
я попробовал это сделать, но все это дает массовый результат. как можно получить уведомление журнала прерывания питания.. Пожалуйста, помогите мне, если у вас есть какой-либо код

Member 14545110

checkEventlog = задача.Factory.StartNew(() => this.CheckEventlog(eventLogSource, eventlogWarningType));
-----------------------------
что такое "CheckEventlog" . это дает ошибку
-------

на ходу)
{
if (checkEventlog != null)
{
if (checkEventlog.IsCompleted)
{
checkEventlog.Располагать();
checkEventlog = задача.Factory.StartNew(() => this.CheckEventlog(eventLogSource, eventlogWarningType));
}
}

var stopwatch = новый секундомер();
секундомер.Сброс();
секундомер.Начать();

в то время как ((секундомер.ElapsedMilliseconds < 10000) && работает)
{
// Избегайте высокой загрузки процессора с помощью плотного цикла.
Нить.CurrentThread.Присоединяйтесь(100);
#если отладка
Приложение.Функция doevents();
#endif
секундомер.Стоп();
}
}
---------------------
во время (бега) . Что такое бег.. это дает ошибку

RickZeeland

Running-это логическая переменная, которую я использую для остановки приложения, вы можете заменить ее на True. checkEventlog-это задача.

RickZeeland

Линейный секундомер.Stop(); должен был быть вне цикла, обновил решение :)

Member 14545110

Одна последняя вещь, сэр
private const string EventSource = "MyProgramName";
в этой строке какое имя MyProgramName?

RickZeeland

Имя, которое вы дали своему приложению, необходимо, если ваше приложение также регистрирует события в журнале событий Windows, в данном примере оно бесполезно.

Member 14545110

Ваш код работает нормально. Но это не дает муравью выйти наружу. Просто покажите пустой экран CMD. Хотя я выключаю основной источник питания и мой рабочий стол работает на ИБП Power Supply

RickZeeland

Вы должны изменить строки в: psuEventCheck = "источник питания, источники питания";
Сначала найдите строки, сгенерированные ИБП в журнале событий Windows, но, к сожалению, это отличается для каждого производителя.

Рейтинг:
2

Member 14545110

PBT_APMPOWERSTATUSCHANGE эта функция работает при зарядке ноутбука и неизменна. как я получаю идентификатор события EventLog для питания ИБП. и главный идентификатор события поставки.

Richard MacCutchan

Извините, я не знаю. Вам необходимо изучить документацию MSDN для всех сообщений power notification

Member 14545110

нет проблем, братан ... ответь мне, если у тебя есть какой-то другой способ решить эту проблему.

Рейтинг:
1

Member 12797106

Пожалуйста, загляните по ссылке ниже.
WinMust - простой монитор состояния ИБП[^]