Getting the currently logged-in user to a Windows XP Pro system

1,031

Solution 1

%WINDIR%\System32\dllcache\query.exe session will give you a list of all the currently logged on users on WinXP.

For some reason, query.exe was not in my path environment variable on my WinXP test machine so that is why I specified the entire path.

query

If you need something that is capable of getting this information remotely over RPC/DCOM, then check out a couple of things I wrote:

http://myotherpcisacloud.com/post/2013/01/16/Usersexe-v1003.aspx

http://www.myotherpcisacloud.com/post/2013/01/13/Getting-RDP-Sessions-with-Client-Computer-Name.aspx

By the way, you need to get off of XP ASAP. It's very old.

Edit: OK, I am going to give you another alternative since none of this has helped you yet. You want to query this WinXP machine over the network using your Linux machine. You want to use WMI. You have found a WMI client for Linux. So far so good.

This will get you currently logged on users of a local or remote machine through WMI WQL queries. I wrote this in Powershell. Sorry, I won't (read: can't) convert it to Perl or Bash for you, but the concept is what is still the same as long as you can do WQL queries:

$Sessions = Get-WMIObject -Query "SELECT * FROM Win32_LogonSession WHERE LogonType=2 OR LogonType=10"
Foreach($Session In $Sessions)
{
    If($Session -AND $Session.PSObject.Properties.Match('LogonId').Count)
    {
        Get-WMIObject -Query "Associators Of {Win32_LogonSession.LogonId=$($Session.LogonId)} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent"
    }
}

LogonTypes of 2 and 10 cover both local and remote interactive sessions, but not service logons, network logons, or batch logons.

Yes, you do need permissions to access the WinXP machine. It's not just going to cough up all this data for an anonymous network process. The local groups on WinXP are not very granular, because WinXP is very old, and its security is far inferior to that of modern versions of Windows... my point being that putting your network monitoring user in the local Admins group of the WinXP machine may be your best option. But I commend you if you still want to go with the principle of least privilege, in which case, you can use the WMI Control Console, wmimgmt.msc, and set the permissions to exactly whatever account you want to assign the permissions to.

Solution 2

Thanks yo @Ryan Ries, here is the actual Perl script I'm using. Hopefully it proves useful to someone else. It appears to be working, please feel free to report any bugs. I'll try to remember to update this if I find any.

Also, I couldn't find any way to make this work on XP other than putting the monitoring user in Administrators. I think that's the only way to do it on XP.

#!/usr/bin/perl -w
use 5.010;
use IPC::Run qw(run);
use Nagios::Plugin;
use strict;

my $np = Nagios::Plugin->new(
    shortname => 'check_windows_user',
    version   => '0.01',
    license   => 'Copyright 2013 Customer Relationship Metrics, LC. Based on a Powerhell program by Ryan Ries. CC-BY-SA http://creativecommons.org/licenses/by-sa/3.0/',
    usage =>
        'Usage: %s -H <host> -A <authfile> -u <user>|-s <sid> -w <threshold> -c <threshold>',
    extra => <<EXTRA

Thresholds are in session counts.

See http://nagiosplug.sourceforge.net/developer-guidelines.html for a
description of the threshold format.
EXTRA
);

$np->add_arg(
    spec     => 'host|H=s',
    help     => '-H, --host=hostname',
    required => 1,
);
$np->add_arg(
    spec     => 'user|u=s',
    help     => '-u, --user=username',
    required => 0,
);
$np->add_arg(
    spec     => 'sid|s=s',
    help     => '-s, --sid=sid',
    required => 0,
);
$np->add_arg(
    spec     => 'authentication_file|authentication-file|A=s',
    help     => '-A, --authentication-file=FILE',
    required => 1,
);
$np->add_arg(
    spec     => 'warning|w=s',
    help     => '-w, --warning=INTEGER:INTEGER',
    required => 1,
);
$np->add_arg(
    spec     => 'critical|c=s',
    help     => '-c, --critical=INTEGER:INTEGER',
    required => 1,
);
$np->getopts;
$np->set_thresholds(
    warning  => $np->opts->warning,
    critical => $np->opts->critical
);

# setup
local $SIG{ALRM} = sub { die "alarm timed out\n" };
alarm 30;

my $target_user = defined $np->opts->user ? lc $np->opts->user : undef;
my $target_sid  = defined $np->opts->sid  ? lc $np->opts->sid  : undef;

my @wmic = (
    'wmic',
    -A => $np->opts->authentication_file,
    ('//' . $np->opts->host));
my $wmic_out;

# get all logon ids
my @all_logon_ids;
run [
    @wmic,
    q{SELECT LogonId FROM Win32_LogonSession WHERE LogonType = 2 or LogonType = 10}
    ],
    \undef, \$wmic_out;
@all_logon_ids = split("\n", $wmic_out);

$all_logon_ids[0] =~ /^CLASS: Win32_LogonSession$/
    or die "Unexpected wmic result: $wmic_out";
$all_logon_ids[1] =~ /^LogonId$/
    or die "Unexpected wmic result: $wmic_out";
splice @all_logon_ids, 0, 2;

# get user of each logon, check if matches
my $session_count = 0;
foreach my $logon_id (@all_logon_ids) {
    # does not seem to be a way to specify which fields we want, or
    # their order  :-(
    #
    # also, it only seems to do delimited data — pick a character that
    # isn't going to occur in the data. And unit separator is even for
    # that purpose!
    run [
        @wmic,
        '--delimiter' => "\x1F",
        qq{Associators Of {Win32_LogonSession.LogonId=$logon_id} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent}
        ],
        \undef, \$wmic_out;

    # sessions get left in Win32_LogonSession after log out (sometimes).
    next if '' eq $wmic_out;

    my @tmp = split("\n", $wmic_out);
    3 == @tmp && $tmp[0] =~ /^CLASS: Win32_UserAccount$/
        or die "Unexpected associator: $wmic_out";
    my %record;
    @record{map lc, split("\x1F", $tmp[1])} = map lc,
        split("\x1F", $tmp[2]);

    # try to disqualify
    defined $target_user && $target_user ne $record{caption}
        and next;
    defined $target_sid && $target_sid ne $record{sid}
        and next;

    # qualified
    ++$session_count;
}

$np->add_message($np->check_threshold($session_count),
    "$session_count sessions");

$np->nagios_exit($np->check_messages);

Changelog

  • Apparently, if you log out a session via remote desktop, and don't log in another user, the session gets left in Win32_LogonSession, but with nothing associated. Status is always null, so can't filter that way. Filter by lack of associations. Without this two-line fix, plugin would die (and thus return unknown).
Share:
1,031

Related videos on Youtube

Soggy
Author by

Soggy

Updated on September 18, 2022

Comments

  • Soggy
    Soggy almost 2 years

    I am trying to set up custom styles for a project whilst maintaining of the implicit UWP styles and maintaining a lot of the implicit UWP style properties.

    In this example I want to keep all of the default UWP button styles and set a key to reference. This allows me to make a custom style based on this default

    The default UWP style with key DefaultButtonStyle

    <Style TargetType="Button" x:Key="DefaultButtonStyle">
            <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
            <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
            <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundTransparentBrush}" />
            <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
            <Setter Property="Padding" Value="8,4,8,4" />
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
            <Setter Property="FontWeight" Value="Normal" />
            <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
            <Setter Property="UseSystemFocusVisuals" Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal">
                                        <Storyboard>
                                            <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="PointerOver">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPointerOver}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPointerOver}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPointerOver}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                                <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                            </Storyboard>
                                        </VisualState>
                                    <VisualState x:Name="Pressed">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPressed}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPressed}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPressed}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <PointerDownThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Disabled">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundDisabled}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushDisabled}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}"/>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ContentPresenter x:Name="ContentPresenter"
                                              BorderBrush="{TemplateBinding BorderBrush}"
                                              BorderThickness="{TemplateBinding BorderThickness}"
                                              Content="{TemplateBinding Content}"
                                              ContentTransitions="{TemplateBinding ContentTransitions}"
                                              ContentTemplate="{TemplateBinding ContentTemplate}"
                                              Padding="{TemplateBinding Padding}"
                                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                              AutomationProperties.AccessibilityView="Raw"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    I am then wanting to create a custom style based on this style, and only change the properties that are necessary (this allows me to keep track of the properties I am changing very easily)

    My custom style basedon the DefaultButtonStyle

            <Style TargetType="Button" x:Key="CustomButtonStyle" BasedOn="{StaticResource DefaultButtonStyle}">
            <Setter Property="Padding" Value="3,3,3,3"/>
            <Setter Property="FocusVisualMargin" Value="-3"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid CornerRadius="15">
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    My issue is that I want to change properties for the control template within the template property. However, as you would expect, in the code above when I try to set the CornerRadius of the grid to 15, this is the only property for my ControlTemplate (i.e. none of the default style properties are kept).

    At a guess I probably need another key reference somewhere for my control template or grid. I would preferably not like to copy and paste the controltemple in full as the purpose of setting it up this way is to make it very obvious which properties I'm changing.

    Any help much appreciated.

    Thanks,

    • TessellatingHeckler
      TessellatingHeckler almost 11 years
      Not directly applicable to your situation, but interesting and related, the idea of "the currently logged in user" is discussed in Raymond Chen's blog The Old New Thing, here: blogs.msdn.com/b/oldnewthing/archive/2006/08/22/712677.aspx
    • derobert
      derobert almost 11 years
      @TessellatingHeckler Hah, yep. Coming from a Unix background, I definitely understand that!
  • derobert
    derobert almost 11 years
    Hmmm... none of these seem easily doable from the non-Windows monitoring server. Though looking for WMI stuff, after looking at your second link, looks like there is a WMI client for Linux... Will see if that works. No idea if WMI is even supported on XP.
  • Ryan Ries
    Ryan Ries almost 11 years
    WMI is definitely supported in XP.
  • derobert
    derobert almost 11 years
    That query seems to give me the user that is logging in to do the WMI query, not the desktop user... select username from Win32_ComputerSystem seems to work, but only if run as an administrator (must be a permission I have to set somewhere)... it's giving null as non-admin.
  • derobert
    derobert almost 11 years
    Actually, with more testing, it only works if the querying account is the same as the logged in account. Otherwise, it always returns null. This is weird—and maybe a config error somewhere—but good enough to get this monitored...
  • Ryan Ries
    Ryan Ries almost 11 years
    Revised for you, OP.
  • MDMarra
    MDMarra almost 11 years
    @derobert you can use NRPE with NSClient++ to execute local commands on the monitored server and pass the output back to nagios for parsing. You don't need to hack together WMI support, just use the functionality built into NSClient++ along with any number of the solutions that Ryan has provided.
  • Keith
    Keith almost 11 years
    You might also want to consider nagios-wsc, if you're dealing with more than a handful of Windows boxes.
  • derobert
    derobert almost 11 years
    Trying the queries in your PowerShell script quickly by hand as administrator shows they work. Thank you! I'll figure out the permissions needed Monday.
  • Ryan Ries
    Ryan Ries almost 11 years
    +1 for giving back to the community. :)
  • Soggy
    Soggy over 5 years
    This is ideal! I've tried to understand the link you provided me, however, I'm still a little in the deep end. My code is all but working with exception of the template binding to my style property MyCornerRadius....I get the error "The member "MyCornerRadius" is not recognised or is not accessible"... I have no idea what I need to do
  • Soggy
    Soggy over 5 years
    Thanks! I've had a look through and looks pretty identical, with the exception that my MyCustomButton class is in my app.xaml.cs file and my styles are stored in the app.xaml file in <application.resources>. Does a UWP app have a theme folder and default.xaml file as a default? Or is this good practice and something I should use instead of the app.xaml file. Still working through to figure out where i've gone wrong....
  • Nico Zhu
    Nico Zhu over 5 years
    When you custom button, we need add Templated Control item, the project will create Generic.xaml file in the Themes folder. please write custom button style in there.
  • Soggy
    Soggy over 5 years
    Thanks Nico, got it all working now! :) one more question if you don't mind, i'm now trying to make a dependency property for my borderbrush (i.e. different buttons will have different colours). Is there a specific type I should be using for the dependency property? I can't seem to get it to work, I'm trying to set MyBorderBrush to #FF31BB23
  • Nico Zhu
    Nico Zhu over 5 years
    Greate, it is a better way for your new question that create a new thread. and I could post more detail info for you. the type of borderbrush is brush. And if the above answer solved your issue please consider accept it.