EventLogQuery: Search by attribute and value - c#

I have attempted using a somewhat complex XPath syntax in the EventLogQuery to no avail. I have looked through all Microsoft docs I found by myself and through other posts here. I have primarily looked through these two posts:
EventLogQuery: How to form query string?
EventLogQuery time format expected?
Here are the queries, first one grabs all logon events with the LogonType attribute within a data node. This is redundant as all logon events will have this node, so I was going to further narrow the query to only type 11 for testing:
// This works fine
*[System/EventID=4624 and EventData/Data[#Name='LogonType']]
// This is considered invalid
*[System/EventID=4624 and EventData/Data[#Name='LogonType' and text()='11']]
What is wrong with this query and how could I fix it? I would prefer not to have to retrieve every single logon event and then filter again (i.e. loop through returns and only act on those with an 11) as this seems inefficient. I will be querying against domain controllers with millions of events currently on them.

For those still searching, I have likely found what the issue is. Microsoft did not fully implement XPath 1.0 for EventLogQuery. They half implemented it and twisted it into what they saw "useful" for querying events. text() is not a useable function. In order to achieve what I was trying, you have to use extremely long, ugly queries such as the following:
*[System/EventID=4624 and (EventData/Data[#Name='LogonType']='2' or EventData/Data[#Name='LogonType']='3' or EventData/Data[#Name='LogonType']='11')]

Related

MSGraph set query page size (instead of using skip token)

How would I go about fetching all users from a company, the following query still only returns 100 items:
https://graph.microsoft.com/v1.0/users?$pageSize=200
Though this might be because the documentation says:
Paging is not supported for link searches, such as for querying group members.
I assume this applies to the users query. Though I don't fully understand why, nor do I understand how else I would fetch the rest of the users.
Any help would be appreciated.
edit: Okay so I found out every page gives you a skiptoken, which is an url to the next page of users. This makes things a lot more complicated than they need to be. I'll rephrase this question to; is there an easier way to fetch all users?
Haven't used pageSize param myself but I've used $top which should behave similarly. Using top you can tell graph to return up to 999 results, which is enough hopefully.
Skip tokens make stuff more complicated, however they do provide you with access to paging/infinite scroll (however you wish to implement your logic). And if you do not need that, you can just do $top=999 for how many times do you need and return the aggregated results.

MVC: Timeout issue

I'm trying to extract the results of a SQL server view in MVC. The view itself is relatively straightforward and UNIONs a couple of tables together - when run it takes around 2 seconds to return its rows. I've added the view to my model in MVC.
In my controller I have the following code, which is designed to return in JSON format the values from the SQL view:-
public JsonResult GetActivity(string LocalIdentifier)
{
return Json(db.Activities.Where(r => r.LocalIdentifier== LocalIdentifier).ToList(), JsonRequestBehavior.AllowGet);
}
When I try to run this, supplying a valid LocalIdentifier nothing happens for a while and then I get an exception (unhandled in user code) in Visual Studio. For reference, this would generally only return between 30 and 50 rows of data from SQL.
Looking at the Inner Exception I get this error:-
"Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."
I've done something similar elsewhere in my application and it works fine - I can't see anything wrong with my code in MVC. Is there anything else I could look at to help diagnose and fix this issue?
Update
Interestingly I've just changed the code to extract just one row (just to see what happens - see below) and it runs instantly...could this be a problem with ToList()?? Is there another way of achieving what I'm trying to do that I could try?
public JsonResult GetActivity(string LocalIdentifier)
{
return Json(db.Activities.First(r => r.LocalIdentifier== LocalIdentifier), JsonRequestBehavior.AllowGet);
}
you should try running the resulting query directly on the sql server. I expect that the query runs for more then 30s, resulting in a timeout. The default timeout value is 30s, so the behaviour you're seeing is expected.
2 ways to deal with it:
speed up the query (maybe you're missing an index?)
change the default timeout (but this is not the preferred option in my opinion)
It depends on how db.Activities is defined. If it has properties for other entities (meaning other tables in the database) then these could also be loaded by EF, even though you did not specify so explicitly, because JSON is serializing each object and its properties. Half your database or more could end up being loaded, even from a simple statement like this.
This SO question has several answers that may help you understand better what is going on behind the scenes, and then fix it.
Enable profiling and see the query inside
Launch this query in SSMS and build the query execution plan
Analyse the plan and make the updates to the database - change structure, build index, change query
If the query runs fine in DB then it seems something wrong with your ORM side part and you should search for the problem there

How can I get "Search Queries" data from Google WMT?

I'm triyng to get data from the Search Queries section in Google WMT. I'm using a simple console app in C# .net 4.5. Thanks to this source, I instanciated the connexion but now I have a service which I can't use as I want.
Here is my working code for now, which get my websites :
var service = Authentication.AuthenticateOauth(client_id, client_secret, user);
if (DaimtoWebMasterSitesHelper.list(service).SiteEntry != null)
{
foreach (var site in DaimtoWebMasterSitesHelper.list(service).SiteEntry)
{
Console.WriteLine("Site: " + site.SiteUrl);
}
}
I would like to get "CTR", "Impressions" and "Clicks" for web & mobile but I have no idea how to ... I'm stuck with this for way too much time, I was happy this morning when I found this piece of code but now i'm stuck again ...
In fact my question is: Is it even possible ?
Can someone help me ?
Thanks!
The Search Queries API is currently in limited mode, meaning we're (Google) testing it with people who showed interest and subscribed when we announced we'll launch it in limited beta. Once testing is done, we'll very likely launch it for the general public, but I don't have a timeframe for that.
You can find the currently supported methods and more information about them in the API Explorer for Search Console (former Webmaster Tools)
For webmasters.searchanalytics.query it currently says:
[LIMITED ACCESS] Query your data with filters and parameters that you define. Returns zero or more rows grouped by the row keys that you define. You must define a date range of one or more days. When date is one of the group by values, any days without data are omitted from the result list. If you need to know which days have data, issue a broad date range query grouped by date for any metric, and see which day rows are returned.

In .Net 4.0, can DirectorySearch return LDAP results in a way that allows me to page through them?

I am working in C#, and am trying to use DirectorySearch to query the groups of an extremely large Microsoft ActiveDirectory LDAP server.
So, in my application, I'm going to have a paged list of groups, with searching capability. Naturally, I don't want to hammer my LDAP server with passing me the entire result set for these queries every time I hit "Next Page".
Is there a way, using DirectorySearch, to retrieve ONLY a single arbitrary page's results, rather than returning the entire result-set in one method call?
Similar questions:
DirectorySearch.PageSize = 2 doesn't work
c# Active Directory Services findAll() returns only 1000 entries
Many questions like these exist, where someone asks about paging (meaning from LDAP server to app server), and gets responses involving PageSize and SizeLimit. However, those properties only affect paging between the C# server and the LDAP server, and in the end, the only relevant methods that DirectorySearch has are FindOne() and FindAll().
What I'm looking for is basically "FindPaged(pageSize, pageNumber)" (the pageNumber being the really important bit. I don't just want the first 1000 results, I want (for example) the 100'th set of 1000 results. The app can't wait for 100,000 records to be passed from the LDAP server to the app server, even if they are broken up into 1,000-record chunks.
I understand that DirectoryServices.Protocols has SearchRequest, which (I think?) allows you to use a "PageResultRequestControl", which looks like it has what I'm looking for (although it looks like the paging information comes in "cookies", which I'm not sure how I'd be supposed to retrieve). But if there's a way to do this without rewriting the entire thing to use Protocols instead, I'd rather not have to do so.
I just can't imagine there's no way to do this... Even SQL has Row_Number.
UPDATE:
The PageResultRequestControl does not help - It's forward-only and sequential (You must call and get the first N results before you can get the "cookie" token necessary to make a call to get result N+1).
However, the cookie does appear to have some sort of reproducible ordering... On a result set I was working on, I iterated one by one through the results, and each time the cookie came out thusly:
1: {8, 0, 0, 0}
2: {11, 0, 0, 0}
3: {12, 0, 0, 0}
4: {16, 0, 0, 0}
When I iterated through two by two, I got the same numbers (11, 16).
This makes me think that if I could figure out the code of how those numbers are generated, I could create a cookie ad-hoc, which would give me exactly the paging I'm looking for.
The PageResultRequestControl is indeed the way to do this, it's part of the LDAP protocol. You'll just have to figure out what that implies for your code, sorry. There should be a way to use it from where you are, but, having said that, I'm working in Java and I've just had to write a dozen or so request controls and extended-operation classes for use with JNDI so you might be out of luck ... or you might have to do like I did. Warning, ASN.1 parsing follows not that far behind :-|
Sadly, it appears there may not be a way to do this given current C# libraries.
All of the standard C#4.0 LDAP libraries return Top-N results (As in, FindAll(), which returns every result, FindOne(), which returns the first result, or SearchResult with PageResultRequestControl, which returns results N through N+M but requires you to retrieve results 1 through N-1 before you'll have a cookie token that you can pass with the request in order to get the next set.
I haven't been able to find any third-party LDAP libraries that allow this, either.
Unless a better solution is found, my path forward will be to modify the interface to instead display the top X results, with no client paging capabilities (obviously still using server-side paging as appropriate).
I may pursue a forward-only paging system at a later date, by passing the updated cookie to the client with the response, and passing it back with a click of a "More Results" type of button.
It might be worth pursuing at a later date, whether or not these cookies can be hand-crafted.
UPDATE:
I spoke with Microsoft Support and confirmed this - There is no way to do dynamic paging with LDAP servers. This is a limitation of LDAP servers themselves.
You can use Protocols and the Paging control (if your LDAP server supports it) to step forward at will, but there is no cross-server (or even cross-version) standard for the cookie, so you can't reasonably craft your own, and there's no guarantee that the cookie can be reused for repeated queries.
A full solution involves using Protocols (with Paging as above) to pull your pageable result set into SQL, whether into a temp table or a permanent storage table, and allow your user to page and sort through THAT result set in the traditional manner. Bear in mind your results won't be precisely up to date, but with some smart cache updating you can minimize that risk.
Maybe you want to iterate through your "pages" using the range-attribute accordingly:
----copy & paste----
This sample retrieves entries 0-500, inclusively.
DirectoryEntry group = new DirectoryEntry("LDAP://CN=Sales,DC=Fabrikam,DC=COM");
DirectorySearcher groupMember = new DirectorySearcher
(group,"(objectClass=*)",new string[]{"member;Range=0-500"},SearchScope.Base);
SearchResult result = groupMember.FindOne();
// Each entry contains a property name and the path (ADsPath).
// The following code returns the property name from the PropertyCollection.
String propName=String.Empty;
foreach(string s in result.Properties.PropertyNames)
{
if ( s.ToLower() != "adspath")
{
propName = s;
break;
}
}
foreach(string member in result.Properties[propName])
{
Console.WriteLine(member);
}
----copy & paste----
for more Information see:
Enumerating Members in a Large Group
https://msdn.microsoft.com/en-us/library/ms180907.aspx
Range Retrieval of Attribute Values
https://msdn.microsoft.com/en-us/library/cc223242.aspx
Searching Using Range Retrieval
https://msdn.microsoft.com/en-us/library/aa367017.aspx

C#, multicore solr, Lucene, shards, case insensitive "contains" searching, and one giant migraine

I am having one heck of a time with my implementation.
We have a solr server running. We have 3 cores, and for simplicty let's call them "Members", "Businesses", and "Products"
I was attempting to use solrnet, but it does not support sharding. So, I am dreading that I will have to build the url myself.
So, I used the admin tool to build a few sample url's for queries when I noticed a problem. Solr does an "equals" not a "contains" and it is case sensitive. I know I'm probably going about this all wrong.
So, I've read I need to set the qt param to "dismax", only when I search the member's core only, through the admin tool, I get "undefined field price"....my member doesn't have a price field. My product does though.
I need to do the following with my query.
Searching across multiple cores (sharding)
Case insensitivity
Contains word instead of equals word
Search multiple fields
Declare priority of the fields (Search on on name first, then description, etc)
I probably have my query all wrong, but here's what it looks like (servername changed to protect the innocent) Name field is actually a concatonation of the user's first and last name....so I was trying to see if dismax would see if the name contains the word jim (case insensitive).
mysolrserver.mydomain.int:8080/solrQA/select?indent=on&version=2.2&q=Name:jim&fq=&start=0&rows=10&fl=*%2Cscore&qt=dismax&wt=standard&explainOther=&hl.fl=&shards=mysolrserver.mydomain.int:8080/Members,mysolrserver.mydomain.int:8080/Businesses
Any help would be greatly appreciated.
SolrNet and sharding: did you try the ExtraParams property?
Case insensitivity: this is handled by the LowerCaseFilterFactory
Contains word: this is handled by the tokenizer, for example the WhitespaceTokenizerFactory.
Search multiple fields and boosting: since you're using dismax, see the qf parameter.

Categories