草庐IT

windows - 从 Win32_NetworkLoginProfile 返回错误的 LastLogon

coder 2024-06-06 原文

使用 WMI Explorer(或任何其他工具),我用户的 LastLogon 时间戳显示的是过时值而不是当前日期(因为我目前正在使用这台 PC):

SELECT * FROM Win32_NetworkLoginProfile
--
LastLogon = 20150212180405.000000+120

同时,其他域用户被列为 LastLogon 作为当前日期,所以这只是我的用户的问题。

另一方面,NetUsers正在按预期报告当前日期:

DOMAIN\user    user name    2015/03/10 10:14

WMI错误结果的原因是什么?


环境:Win 7 x64,域用户添加到本地管理员组。

最佳答案

我很高兴收到来自 NetUsers.exe 的 Optimum X 开发人员的答复,非常专业且内容丰富。

他们用 c++ 编写程序,跟踪登录时间的最可靠方法是读取位于“HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList”下的每个配置文件的注册表项上的 LastWriteTime

在我用 WMI 亲自尝试了每个类之后,它们都让我失望了,所以我求助于 pInvoke 来使用 C# 读取隐藏的注册表属性“LastWriteTime”

这是您要在 HKLM RegistryKey 上调用的主要函数:

    private static DateTime GetHKLMRegistryKeyLastWriteTime(RegistryKey key, string RemoteComputer)
    {
        DateTime LastWriteTime = DateTime.MinValue;
        //set RegSAM access
        RegSAM desiredSAM = RegSAM.Read;
        //set key to same navigation (win32 vs win64)
        if (key.View == RegistryView.Registry32)
        {
            desiredSAM |= RegSAM.WOW64_32Key;
        }
        else if(key.View == RegistryView.Registry64)
        {
            desiredSAM |= RegSAM.WOW64_64Key;
        }

        //Get Registry Hive Key on RemoteComputer.
        UIntPtr computerRegHive = ConnectToRegistryHive(RemoteComputer, HKEY_LOCAL_MACHINE);

        if(computerRegHive != UIntPtr.Zero)
        {
            string keyPath = key.Name;
            int rootSeperatorIndex = keyPath.IndexOf(@"\");
            if (rootSeperatorIndex != -1)
            {
                keyPath = keyPath.Substring(rootSeperatorIndex + 1, keyPath.Length - (rootSeperatorIndex + 1));
            }

            UIntPtr computerRegKey = OpenRegistrySubKey(computerRegHive, keyPath, desiredSAM);
            //We no longer need computerRegHive, close!
            RegCloseKey(computerRegHive);
            if(computerRegKey != UIntPtr.Zero)
            {
                LastWriteTime = GetRegistryKeyLastWriteTime(computerRegKey);
                //We no longer need computerRegKey, close!
                RegCloseKey(computerRegKey);
            }
        }
        return LastWriteTime;
    }

下面是让它工作所需的东西:

public static uint HKEY_LOCAL_MACHINE = 0x80000002u;

[DllImport("advapi32.dll")]
private static extern int RegConnectRegistry(string lpmachineName, uint hKey, out UIntPtr phKResult);

[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
private static extern int RegOpenKeyEx(
        UIntPtr hKey,
        string subKey,
        int ulOptions, //Set to 0
        RegSAM samDesired, //Desired Access (win32/win64 & Read or ReadWrite)
        out UIntPtr hkResult);

[DllImport("advapi32.dll")]
private static extern int RegQueryInfoKey(
        UIntPtr hKey,
        StringBuilder lpClass,
        IntPtr lpcbClass,
        IntPtr lpReserved,
        IntPtr lpcSubKeys,
        IntPtr lpcbMaxSubKeyLen,
        IntPtr lpcbMaxClassLen,
        IntPtr lpcValues,
        IntPtr lpcbMaxValueNameLen,
        IntPtr lpcbMaxValueLen,
        IntPtr lpcbSecurityDescriptor,
        [Out][Optional]out FILETIME lpftLastWriteTime
    );

[DllImport("advapi32.dll")]
private static extern int RegCloseKey(UIntPtr hKey);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FileTimeToSystemTime([In] ref FILETIME lpFileTime, out SYSTEMTIME lpSystemTime);

[Flags]
public enum RegSAM
{
    QueryValue = 0x0001,
    SetValue = 0x0002,
    CreateSubKey = 0x0004,
    EnumerateSubKeys = 0x0008,
    Notify = 0x0010,
    CreateLink = 0x0020,
    WOW64_32Key = 0x0200,
    WOW64_64Key = 0x0100,
    WOW64_Res = 0x0300,
    Read = 0x00020019,
    Write = 0x00020006,
    Execute = 0x00020019,
    AllAccess = 0x000f003f
}

    [StructLayout(LayoutKind.Sequential)]
    public struct FILETIME
    {
        public uint LowPart;
        public uint HighPart;
    };

    [StructLayout(LayoutKind.Sequential, Pack = 2)]
    public struct SYSTEMTIME
    {
        public ushort Year;
        public ushort Month;
        public ushort DayOfWeek;
        public ushort Day;
        public ushort Hour;
        public ushort Minute;
        public ushort Second;
        public ushort Milliseconds;

        public SYSTEMTIME(DateTime dt)
        {
            dt = dt.ToUniversalTime();
            Year = Convert.ToUInt16(dt.Year);
            Month = Convert.ToUInt16(dt.Month);
            DayOfWeek = Convert.ToUInt16(dt.DayOfWeek);
            Day = Convert.ToUInt16(dt.Day);
            Hour = Convert.ToUInt16(dt.Hour);
            Minute = Convert.ToUInt16(dt.Minute);
            Second = Convert.ToUInt16(dt.Second);
            Milliseconds = Convert.ToUInt16(dt.Millisecond);
        }

        public SYSTEMTIME(ushort year, ushort month, ushort day, ushort hour = 0, ushort minute = 0, ushort second = 0, ushort millisecond = 0)
        {
            Year = year;
            Month = month;
            Day = day;
            Hour = hour;
            Minute = minute;
            Second = second;
            Milliseconds = millisecond;
            DayOfWeek = 0;
        }

        public static implicit operator DateTime(SYSTEMTIME st)
        {
            if (st.Year == 0 || st == MinValue)
                return DateTime.MinValue;
            if (st == MaxValue)
                return DateTime.MaxValue;
            return new DateTime(st.Year, st.Month, st.Day, st.Hour, st.Minute, st.Second, st.Milliseconds, DateTimeKind.Utc);
        }

        public static bool operator ==(SYSTEMTIME s1, SYSTEMTIME s2)
        {
            return (s1.Year == s2.Year && s1.Month == s2.Month && s1.Day == s2.Day && s1.Hour == s2.Hour && s1.Minute == s2.Minute && s1.Second == s2.Second && s1.Milliseconds == s2.Milliseconds);
        }

        public static bool operator !=(SYSTEMTIME s1, SYSTEMTIME s2)
        {
            return !(s1 == s2);
        }

        public static readonly SYSTEMTIME MinValue, MaxValue;

        static SYSTEMTIME()
        {
            MinValue = new SYSTEMTIME(1601, 1, 1);
            MaxValue = new SYSTEMTIME(30827, 12, 31, 23, 59, 59, 999);
        }

        public override bool Equals(object obj)
        {
            if (obj is SYSTEMTIME)
                return ((SYSTEMTIME)obj) == this;
            return base.Equals(obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }


    /// <summary>
    /// When a handle returned is no longer needed, it should be closed by calling RegCloseKey.
    /// </summary>
    private static UIntPtr ConnectToRegistryHive(string RemoteComputer, uint hKey)
    {
        UIntPtr computerRegHive = UIntPtr.Zero;
        RegConnectRegistry(@"\\" + RemoteComputer, hKey, out computerRegHive);
        return computerRegHive;
    }

    /// <summary>
    /// When a handle returned is no longer needed, it should be closed by calling RegCloseKey.
    /// </summary>
    private static UIntPtr OpenRegistrySubKey(UIntPtr CurrentHKey, string SubKeyName, RegSAM desiredSAM)
    {
        UIntPtr hRegKey = UIntPtr.Zero;
        RegOpenKeyEx(CurrentHKey, SubKeyName, 0, desiredSAM, out hRegKey);
        return hRegKey;
    }

    private static DateTime GetRegistryKeyLastWriteTime(UIntPtr hKey)
    {
        FILETIME ft = new FILETIME();

        int ret = RegQueryInfoKey(hKey, null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 
                                  IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, out ft);
        if(ret == 0)
        {
            SYSTEMTIME st = new SYSTEMTIME(DateTime.MinValue);
            FileTimeToSystemTime(ref ft, out st);
            //Thanks to a highly developed SYSTEMTIME struct which has a DateTime implicit operator .... it's like magic!
            DateTime LastWriteTime = st;
            return LastWriteTime.ToLocalTime();
        }
        return DateTime.MinValue;
    }

至于 Win32_NetworkLoginProfile 失败的原因,机器正在从域 Controller 中提取帐户的日期戳,因此对于机器上的实际本地登录是完全不准确的。

关于windows - 从 Win32_NetworkLoginProfile 返回错误的 LastLogon,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28959160/

有关windows - 从 Win32_NetworkLoginProfile 返回错误的 LastLogon的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  4. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  5. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  6. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  7. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  8. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

  9. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  10. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

随机推荐