【问题标题】:WQL request working in console application but not in Windows serviceWQL 请求在控制台应用程序中工作,但不在 Windows 服务中
【发布时间】:2015-12-24 10:20:17
【问题描述】:

我目前正在研究“监控”解决方案。这个想法是关注远程资源并在可用磁盘空间低于定义的阈值时提醒用户。

该应用是一项 Windows 服务。启动计时器并每隔 x 秒发出一次 WQL 请求。该请求包含我在代码中进一步使用的指标(例如总磁盘大小、可用空间)。

我一直在控制台应用程序中测试整个事情,它工作得很好。但是当我在我的 Win 服务中实现它时,WQL 请求变得疯狂并返回一个 null 元素。

怎么会?我错过了什么吗?

这是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;

namespace DatafactMonitoring
{
    public partial class DatafactMonitoring : ServiceBase
    {
        public DatafactMonitoring()
        {
            InitializeComponent();
            //Creating the event log entry
            eventLog1 = new System.Diagnostics.EventLog();
            if (!System.Diagnostics.EventLog.SourceExists("ServiceMonitoringDatafact"))
            {
                System.Diagnostics.EventLog.CreateEventSource("ServiceMonitoringDatafact", "Événements Monitoring Datafact");
            }
            eventLog1.Source = "ServiceMonitoringDatafact";
            eventLog1.Log = "Événements Monitoring Datafact";
        }

    //Parameters
    protected static int threshold = 10;
    //Declarations
    private static int indexLog = 0;
    protected static float diskUsage;

    protected override void OnStart(string[] args)
    {
        eventLog1.WriteEntry("Starting the Datafact monitoring service...");
        // Timer that triggers OnTimer function every 60 seconds
        System.Timers.Timer timer = new System.Timers.Timer();
        timer.Interval = 10000; // 10 seconds, to be changed
        timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
        timer.Start();
    }

    public ManagementObject GetMetrics()
    {
        ConnectionOptions options = new ConnectionOptions();
        ManagementScope scope = new ManagementScope("\\\\ad", options);
        scope.Connect();
        SelectQuery query1 = new SelectQuery("Select Name, Size, FreeSpace from Win32_LogicalDisk Where DeviceID = 'P:'");
        eventLog1.WriteEntry("Requete...");
        ManagementObjectSearcher searcher1 = new ManagementObjectSearcher(scope, query1);
        ManagementObjectCollection queryCollection1 = searcher1.Get();
        ManagementObject mo = queryCollection1.OfType<ManagementObject>().First();
        return mo;
    }

    public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
    {
        ManagementObject datafactMetrics = GetMetrics();

        //Metrics parsing
        string diskName = datafactMetrics["Name"].ToString();
        eventLog1.WriteEntry(diskName);
        float diskSize = float.Parse(datafactMetrics["Size"].ToString());
        float freeSpace = float.Parse(datafactMetrics["FreeSpace"].ToString());
        diskUsage = (freeSpace / diskSize) * 100;

        indexLog += 1;

        eventLog1.WriteEntry("Log n°" + indexLog + " - Monitoring Datafact server - Space avaiable : " + freeSpace + "Go", EventLogEntryType.Information);

        if (diskUsage >= threshold)
        {
            try
            {
                //TODO: Change url to SMS sender
                System.Diagnostics.Process.Start("http://www.google.com");
                eventLog1.WriteEntry("Space avaiable below " + threshold + "% (Disk usage : " + diskUsage + "%) - Mail & SMS sent to the team", EventLogEntryType.Warning);
            }

            catch (Exception ex)
            {
                eventLog1.WriteEntry("Error : " + ex.ToString(), EventLogEntryType.Error);
            }
        }
        else
        {
            eventLog1.WriteEntry("Disk usage : " + diskUsage + "%", EventLogEntryType.Information);
        }
    }

    protected override void OnStop()
    {
        eventLog1.WriteEntry("Datafact monitoring service stopped.");
    }
}
}

【问题讨论】:

  • “WQL 请求变得疯狂并返回一个空元素”是什么意思?
  • 我的意思是在我的控制台应用程序中,请求有效并返回一个 ManagementObjectCollection,其中包含我正在寻找的元素,但是一旦在 Windows 服务中,返回的 ManagementObjectCollection 为空。
  • 你试过管理员权限吗?
  • 我对权限管理不是很熟悉。但是在创建服务时,我将 serviceProcessInstaller 的帐户从“用户”更改为“本地系统”。这还不够吗?

标签: c# .net windows-services wmi wql


【解决方案1】:

无法使用 WMI 找到合适的解决方案。 使用 Win32API 中的 GetDiskFreeSpace 找到解决方法。

//Starting with the function's import...
[DllImport("kernel32")]
public static extern int GetDiskFreeSpace(
    string lpRootPathName,
    out int lpSectorsPerCluster,
    out int lpBytesPerSector,
    out int lpNumberOfFreeClusters,
    out int lpTotalNumberOfClusters
);
.
.
.

//... which I then use in my OnTimer function
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
    string lpRootPathName = @"\\ServerName\SharedFolder";
    int lpSectorsPerCluster;
    int lpBytesPerSector;
    int lpNumberOfFreeClusters;
    int lpTotalNumberOfClusters;

    int bRC = GetDiskFreeSpace(
        lpRootPathName,
        out lpSectorsPerCluster,
        out lpBytesPerSector,
        out lpNumberOfFreeClusters,
        out lpTotalNumberOfClusters
    );

    .
    .
    .

    eventLog1.WriteEntry("Root : "+ lpRootPathName + "Sectors : "+ lpSectorsPerCluster +"Bytes : "+ lpBytesPerSector +"FreeClusters : "+ lpNumberOfFreeClusters + "TotalClusters : "+ lpTotalNumberOfClusters);

【讨论】:

    【解决方案2】:

    如果 LogicalDrive P 是网络驱动器,则您无法从 Windows 服务访问它,至少在默认设置下不能访问,因为它具有最低权限:

    msdn local service account

    如果您无法控制网络驱动器的权限,则必须将 Windows 服务配置为以特定用户身份运行:

    impersonating codeproject example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-07
      • 1970-01-01
      相关资源
      最近更新 更多