Is there a way to enable the ASP.NET Web Service Extension in IIS6 via C#? I'm trying to simplify a website setup program for people who haven't used IIS before.
C# NET. Framework usage:
Process.Start(#"C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis", "-i -enable");
CMD usage:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -i -enable
It's useful.
Source: https://serverfault.com/questions/1649/why-does-iis-refuse-to-serve-asp-net-content
You could call out to WMI easily enough (System.Management namespace, IIRC) and I believe you can set it from there. However, it may well be much simpler to set it manually, you can't do it from within an ASP.NET site since your server won't be able to run it until it is set...
Principles of doing something similar may be found here
Looking around all the examples of this are written in vbscript. So I cheated and came up with this function:
static void EnableASPNET()
{
var file = "wmi.vbs";
using (var writer = new StreamWriter(file))
{
writer.WriteLine("Set webServiceObject = GetObject(\"IIS://localhost/W3SVC\")");
writer.WriteLine("webServiceObject.EnableWebServiceExtension \"ASP.NET v2.0.50727\"");
writer.WriteLine("webServiceObject.SetInfo");
}
var process = Process.Start("cscript", file);
process.WaitForExit();
File.Delete(file);
}
// if windows 2003
if (Environment.OSVersion.Version.Major == 5 &&
Environment.OSVersion.Version.Minor == 2)
{
DirectoryEntry folderRoot = new DirectoryEntry("IIS://localhost/W3SVC");
folderRoot.Invoke("EnableWebServiceExtension", "ASP.NET v2.0.50727");
}
Copied from: http://lastdon.blogspot.com/2006/12/setup-web-application-on-windows-2003.html
I believe you can also run the following command line:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -s W3SVC
And this will recursively enable the AND.NET framework v2.0.50727 for all configured websites.
Related
When you run Get-ExecutionPolicy in PowerShell, it gets the effective execution policy. I need to know the best way to get that information in C#. I don't need to know how to change it like many other questions about PowerShell Execution Policy, I just need to know how to get it in C#.
Note:
PowerShell execution policies apply only on Windows.
With respect to Windows, the answer below covers both PowerShell editions.
It can be inferred from the docs that boxdog pointed to in a comment, but to spell it out:
using System;
using System.Management.Automation;
namespace demo
{
class ConsoleApp {
static void Main() {
using (var ps = PowerShell.Create()) {
var effectivePolicy = ps.AddCommand("Get-ExecutionPolicy").Invoke()[0].ToString();
ps.Commands.Clear();
Console.WriteLine("Effective execution policy: " + effectivePolicy);
}
}
}
}
Note:
The above assumes that you're using the PowerShell SDK - see this answer for the appropriate NuGet package to add to your project.
If you're using a PowerShell (Core) 7+ SDK, additional considerations apply:
On Unix-like platforms, execution policies fundamentally do not apply (Unrestricted is reported, though in effect it is Bypass), so the following applies to Windows only:
The LocalMachine scope of any - by definition install-on-demand - PowerShell (Core) 7+ version does not apply; only - if defined - the CurrentUser and GPO-based policies (which preempt the former) do.
On Windows:
In the absence of a relevant execution policy being defined, Restricted is the default, which categorically prevents execution of script files (.ps1).
If your application needs to execute .ps1 files when hosting the PowerShell SDK, for predictable behavior it is best to set the execution policy, for the current process only, as shown in this answer.
The most elegant solution would probably be to get the ExecutionPolicy registry key in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell. For this solution to work, your program needs to be running on the same architecture (x64 or x86) as the operating system it's running on or it won't be able to see the registry key. Code to do this would look something like this:
using Microsoft.Win32
...
string executionPolicy = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell", "ExecutionPolicy", null)?.ToString();
If for any reason you can't do the first solution, the second way I would recommend is by using the System.Management.Automation.PowerShell NuGet package. This method would look something like this:
using(var ps = PowerShell.Create()){
ps.AddScript("Get-ExecutionPolicy");
Collection<PSObject> output = ps.Invoke();
Console.WriteLine($"Execution policy is {output[0]}")
}
If you really don't want to add an extra NuGet package to your project, there is another, but quite a bit messier way of doing this using System.Diagnostics.Process and it's output stream. It would look something like this:
var procInfo = new ProcessStartInfo("powershell.exe", "-Command \"Get-ExecutionPolicy\"")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true
};
var proc = new Process
{
StartInfo = procInfo
};
proc.OutputDataReceived += Proc_OutputDataReceived;
proc.Start();
proc.BeginOutputReadLine();
Console.ReadLine();
...
private static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.Data))
Console.WriteLine($"Execution policy is {e.Data}");
}
I have an ASP.NET Core application and I need to validate that the uploaded file is an image and not a non-image file which has an image extension....
All solutions that I found and makes sense use System.Drawing.Image or similar classes that aren't available in ASP.NET Core.
Can you kindly suggest an alternative?
*Please note that I'm not trying to check the extension but the contents.
Thank you
Now "System.Drawing.Common" NuGet is available for .NET Core.
You can do the following to validate the "possible" images:
using System.Drawing;
// ...
public bool IsImage(byte[] data)
{
var dataIsImage = false;
using (var imageReadStream = new MemoryStream(data))
{
try
{
using (var possibleImage = Image.FromStream(imageReadStream))
{
}
dataIsImage = true;
}
// Here you'd figure specific exception to catch. Do not leave like that.
catch
{
dataIsImage = false;
}
}
return dataIsImage;
}
if you have privileges to run executables on the server you can use imagemagick's identify command. it's a lot of work.you'd need to install imagemagick on the server and need to have permissions to run executables.
https://www.imagemagick.org/script/identify.php
you'd need to call the program and give the image file to it
how to call exe files in c#: https://msdn.microsoft.com/en-us/library/0w4h05yb(v=vs.110).aspx
how to read process output: https://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline(v=vs.110).aspx
How do I develop my Windows application so it will auto update on the client machine, like Firefox, Skype, etc.?
Is there any simple approach or any open source library which help me to do it just following some steps or a few lines of code?
ClickOnce is what you're searching for.
You might also find these SO questions interesting (which offers some different solutions):
Auto update for WinForms application
How do I implement an auto update strategy for my in-house winform app
try microsoft clickonce technology
(in MSDN)
You can use wyUpdate or .NET Application Updater Component
There is also the Update Block in the Ent Lib by msft.
The most popular frameworks are:
Google Omaha - This is what Chrome uses. Very powerful.
Squirrel - This is used in Electron applications. Easy to use but can't update machine-wide installations. Also, no graphical update notifications.
WinSparkle - Gives you graphical update notifications. But less mature than Squirrel.
AutoUpdater.NET - Both graphical and silent updates. Similar to Squirrel and WinSparkle.
I've taken these links from this article. It goes into more details about the pros and cons of each of the frameworks.
Use MD5-Update it easy only need add 5 lines at your application, no configuration need in your app only add library and publish the files.
1. Your need a web server with PHP for publish your files please include updt.exe.
2. Add index.php for make list of update files. aviable on github repository https://github.com/jrz-soft-mx/MD5-Update/blob/main/Tools/Tools.zip o create new app with this code.
<?php
$_dat = array();
$_dir=new RecursiveDirectoryIterator(".");
foreach (new RecursiveIteratorIterator($_dir) as $_itm) {
$_fil = str_replace(".".DIRECTORY_SEPARATOR, "", $_itm);
if(!is_dir($_fil) && $_fil != "index.php"){
$_dat[]=array('StrFil' => "$_fil", 'StrMd5' => strtoupper(md5_file($_fil)), 'lonSiz' => filesize($_fil));
}
}
echo json_encode($_dat, JSON_UNESCAPED_UNICODE);
?>
3. Add nuget repository at your proyect
PM> Install-Package MD5.Update
4. Call the library when your app stars, with your update folder url, update all files and download your new app on updt folder, for replace your app need updt.exe
string strUrl = "http://yourdomain.com/app/";
if (MD5Update.MD5Update.Check(strUrl, true))
{
Process.Start(AppDomain.CurrentDomain.BaseDirectory + #"updt.exe", AppDomain.CurrentDomain.FriendlyName + " " + Process.GetCurrentProcess().ProcessName);
Application.Exit();
}
5. updt.exe for replace the current app with the new app updt folder to app. aviable on github repository https://github.com/jrz-soft-mx/MD5-Update/blob/main/Tools/Tools.zip o create new app with this code.
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
List<string> lisArg = Environment.GetCommandLineArgs().ToList();
if (lisArg.Count < 2)
{
MessageBox.Show("Please provide App Excutable Name and Procees name");
Application.Exit();
return;
}
string strAppName = lisArg[1];
string strAppProcees = lisArg[2];
Process[] lisPro = Process.GetProcessesByName(strAppProcees);
foreach (Process Pro in lisPro)
{
if (Pro.Id != Process.GetCurrentProcess().Id)
{
Pro.Kill();
Thread.Sleep(1000);
}
}
string strAppMain = AppDomain.CurrentDomain.BaseDirectory + strAppName;
string strAppUpdate = AppDomain.CurrentDomain.BaseDirectory + #"updt\" + strAppName;
if (!File.Exists(strAppMain))
{
MessageBox.Show("App Excutable dosent exists");
Application.Exit();
return;
}
if (!File.Exists(strAppUpdate))
{
MessageBox.Show("App Excutable Updated dosent exists");
Application.Exit();
return;
}
File.Copy(strAppUpdate, strAppMain, true);
long fileSize = 0;
FileInfo currentFile = new FileInfo(strAppMain);
while (fileSize < currentFile.Length)
{
fileSize = currentFile.Length;
Thread.Sleep(1000);
currentFile.Refresh();
}
Process.Start(strAppMain);
}
catch (Exception Ex)
{
MessageBox.Show("An error ocurred");
File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + #"updt_" + DateTime.Now.ToString("yyyyMMddTHHmmss") + " .txt", Ex.ToString());
Application.Exit();
}
How about System Center 2012 Configuration Manager?
I'd add another possible variation:
https://github.com/synhershko/NAppUpdate
https://github.com/cecon/autoupdatereasy
https://github.com/NetSparkleUpdater/NetSparkle
While ClickOnce is simple and it resurrected for .NET 5, it still has a lot of limitations, so I found out that nowadays better option exists: you could use included in Windows 10 mechanism for app delivery called AppInstaller by packaging your app in MSIX bundle or package.
I covered my findings related to the topic in this answer
I'm building a web application in which I need to scan the user-uploaded files for viruses.
Does anyone with experience in building something like this can provide information on how to get this up and running? I'm guessing antivirus software packages have APIs to access their functionality programatically, but it seems it's not easy to get a hand on the details.
FYI, the application is written in C#.
Important note before use:
Be aware of TOS agreement. You give them full access to everything: "When you upload or otherwise submit content, you give VirusTotal (and those we work with) a worldwide, royalty free, irrevocable and transferable licence to use, edit, host, store, reproduce, modify, create derivative works, communicate, publish, publicly perform, publicly display and distribute such content."
Instead of using a local Antivirus program (and thus binding your program to that particular Antivirus product and requesting your customers to install that Antivirus product) you could use the services of VirusTotal.com
This site provides a free service in which your file is given as input to numerous antivirus products and you receive back a detailed report with the evidences resulting from the scanning process. In this way your solution is no more binded to a particular Antivirus product (albeit you are binded to Internet availability)
The site provides also an Application Programming Interface that allows a programmatically approach to its scanning engine.
Here a VirusTotal.NET a library for this API
Here the comprensive documentation about their API
Here the documentation with examples in Python of their interface
And because no answer is complete without code, this is taken directly from the sample client shipped with the VirusTotal.NET library
static void Main(string[] args)
{
VirusTotal virusTotal = new VirusTotal(ConfigurationManager.AppSettings["ApiKey"]);
//Use HTTPS instead of HTTP
virusTotal.UseTLS = true;
//Create the EICAR test virus. See http://www.eicar.org/86-0-Intended-use.html
FileInfo fileInfo = new FileInfo("EICAR.txt");
File.WriteAllText(fileInfo.FullName, #"X5O!P%#AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*");
//Check if the file has been scanned before.
FileReport fileReport = virusTotal.GetFileReport(fileInfo);
bool hasFileBeenScannedBefore = fileReport.ResponseCode == ReportResponseCode.Present;
Console.WriteLine("File has been scanned before: " + (hasFileBeenScannedBefore ? "Yes" : "No"));
//If the file has been scanned before, the results are embedded inside the report.
if (hasFileBeenScannedBefore)
{
PrintScan(fileReport);
}
else
{
ScanResult fileResult = virusTotal.ScanFile(fileInfo);
PrintScan(fileResult);
}
... continue with testing a web site ....
}
DISCLAIMER
I am in no way involved with them. I am writing this answer just because it seems to be a good update for these 4 years old answers.
You can use IAttachmentExecute API.
Windows OS provide the common API to calling the anti virus software which is installed (Of course, the anti virus software required support the API).
But, the API to calling the anti virus software provide only COM Interface style, not supported IDispatch.
So, calling this API is too difficult from any .NET language and script language.
Download this library from here Anti Virus Scanner for .NET or add reference your VS project from "NuGet" AntiVirusScanner
For example bellow code scan a file :
var scanner = new AntiVirus.Scanner();
var result = scanner.ScanAndClean(#"c:\some\file\path.txt");
Console.WriteLine(result); // console output is "VirusNotFound".
I would probably just make a system call to run an independent process to do the scan. There are a number of command-line AV engines out there from various vendors.
Take a look at the Microsoft Antivirus API. It makes use of COM, which should be easy enough to interface with from .NET. It refers specifically to Internet Explorer and Microsoft Office, but I don't see why you wouldn't be able to use to to on-demand scan any file.
All modern scanners that run on Windows should understand this API.
Various Virus scanners do have API's. One I have integrated with is Sophos. I am pretty sure Norton has an API also while McAfee doesn't (it used to). What virus software do you want to use? You may want to check out Metascan as it will allow integration with many different scanners, but there is an annual license cost. :-P
I also had this requirement. I used clamAv anti virus which provides on-demand scanning by sending the file to their tcp listening port. You can use nClam nuget package to send files to clamav.
var clam = new ClamClient("localhost", 3310);
var scanResult = clam.ScanFileOnServerAsync("C:\\test.txt"); //any file you would like!
switch (scanResult.Result.Result)
{
case ClamScanResults.Clean:
Console.WriteLine("The file is clean!");
break;
case ClamScanResults.VirusDetected:
Console.WriteLine("Virus Found!");
Console.WriteLine("Virus name: {0}", scanResult.Result.InfectedFiles[0].FileName);
break;
case ClamScanResults.Error:
Console.WriteLine("Woah an error occured! Error: {0}", scanResult.Result.RawResult);
break;
}
A simple and detailed example is shown here. Note:- The synchronous scan method is not available in the latest nuget. You have to code like I done above
For testing a virus you can use the below string in a txt file
X5O!P%#AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
Shameless plug but you might want to check out https://scanii.com, it's basically malware/virus detection as a (REST) service. Oh also, make sure you read and understand virustotal's API terms (https://www.virustotal.com/en/documentation/public-api/) - they are very clear about not allowing commercial usage.
I would recommend using this approach:
using System;
using System.Diagnostics;
using Cloudmersive.APIClient.NET.VirusScan.Api;
using Cloudmersive.APIClient.NET.VirusScan.Client;
using Cloudmersive.APIClient.NET.VirusScan.Model;
namespace Example
{
public class ScanFileAdvancedExample
{
public void main()
{
// Configure API key authorization: Apikey
Configuration.Default.AddApiKey("Apikey", "YOUR_API_KEY");
var apiInstance = new ScanApi();
var inputFile = new System.IO.FileStream("C:\\temp\\inputfile", System.IO.FileMode.Open); // System.IO.Stream | Input file to perform the operation on.
var allowExecutables = true; // bool? | Set to false to block executable files (program code) from being allowed in the input file. Default is false (recommended). (optional)
var allowInvalidFiles = true; // bool? | Set to false to block invalid files, such as a PDF file that is not really a valid PDF file, or a Word Document that is not a valid Word Document. Default is false (recommended). (optional)
var allowScripts = true; // bool? | Set to false to block script files, such as a PHP files, Pythong scripts, and other malicious content or security threats that can be embedded in the file. Set to true to allow these file types. Default is false (recommended). (optional)
var allowPasswordProtectedFiles = true; // bool? | Set to false to block password protected and encrypted files, such as encrypted zip and rar files, and other files that seek to circumvent scanning through passwords. Set to true to allow these file types. Default is false (recommended). (optional)
var restrictFileTypes = restrictFileTypes_example; // string | Specify a restricted set of file formats to allow as clean as a comma-separated list of file formats, such as .pdf,.docx,.png would allow only PDF, PNG and Word document files. All files must pass content verification against this list of file formats, if they do not, then the result will be returned as CleanResult=false. Set restrictFileTypes parameter to null or empty string to disable; default is disabled. (optional)
try
{
// Advanced Scan a file for viruses
VirusScanAdvancedResult result = apiInstance.ScanFileAdvanced(inputFile, allowExecutables, allowInvalidFiles, allowScripts, allowPasswordProtectedFiles, restrictFileTypes);
Debug.WriteLine(result);
}
catch (Exception e)
{
Debug.Print("Exception when calling ScanApi.ScanFileAdvanced: " + e.Message );
}
}
}
}
Note that this way you can even control whether you filter out non-virus threat payloads such as executables, scripts, encrypted/password-protected files, etc.
This approach has a free tier and can also validate the contents of the files that you upload.
We tried two options:
clamav-daemon installed on a tiny linux container + "nClam" .NET library to interact with it. Works fine, but Clam AV misses a lot (a lot!) of viruses, especially dangerous macros hidden in MS Office files. Also ClamAV virus database has to be kept in memory at all times, which uses around 3.5GB of memory, which requires a rather expensive cloud virtual machine.
Ended up using Windows Defender via MpCmdRun.exe CLI api. See answer here
You can try to use DevDragon.io.
It is a web service with an API and .NET client DevDragon.Antivirus.Client you can get from NuGet. Scans are sub 200ms for 1MB file.
More documentation here:
https://github.com/Dev-Dragon/Antivirus-Client
Disclosure: I work for them.
From my experience you can use COM for interfacing with some anti-virus software. But what I would suggest is a bit easier, just parse scan results after scanning. All you need to do is to start the scanner process and point it to file/folder you want to scan, store scan results into file or redirect stdout to your application and parse results.
//Scan
string start = Console.ReadLine();
System.Diagnostics.Process scanprocess = new System.Diagnostics.Process();
sp.StartInfo.WorkingDirectory = #"<location of your antivirus>";
sp.StartInfo.UseShellExecute = false;
sp.StartInfo.FileName = "cmd.exe";
sp.StartInfo.Arguments = #"/c antivirusscanx.exe /scan="+filePath;
sp.StartInfo.CreateNoWindow = true;
sp.StartInfo.RedirectStandardInput = true;
sp.StartInfo.RedirectStandardError = true; sp.Start();
string output = sp.StandardOutput.ReadToEnd();
//Scan results
System.Diagnostics.Process pr = new System.Diagnostics.Process();
pr.StartInfo.FileName = "cmd.exe";
pr.StartInfo.Arguments = #"/c echo %ERRORLEVEL%";
pr.StartInfo.RedirectStandardInput = true;
pr.StartInfo.RedirectStandardError = true; pr.Start();
output = processresult.StandardOutput.ReadToEnd();
pr.Close();
I am working on an application which reads eventlogs(Application) from remote machines. I am making use of EventLog class in .net and then iterating on the Log entries but this is very slow. In some cases, some machines have 40000+ log entries and it takes hours to iterate through the entries.
what is the best way to accomplish this task? Are there any other classes in .net which are faster or in any other technology?
Man, I feel your pain. We had the exact same issue in our app.
Your solution has a branch depending on what server version you're running on and what server version your "target" machine is running on.
If you're both on Vista or Windows Server 2008, you're in luck. You should look at System.Diagnostics.Eventing.Reader.EventLogQuery and System.Diagnostics.Eventing.Reader.EventLogReader. These are new in .net 3.5.
Basically, you can build a query in XML and ship it over to run on the remote computer. Maybe you're just searching for events of a specific type, or maybe just new events from a specific point in time. The search runs on the remote machine, and then you just get back the matching events. The new classes are much faster than the old .net 2.0 way, but again, they are only supported on Vista or Windows Server 2008.
For our app when the target is NOT on Vista/Win2008, we downloaded the raw .evt file from the remote system, and then parsed the file using its binary format. There are several sources of data about the event log format for .evt files (pre-Vista), including link text and an article I recall on codeproject.com that had some c# code.
Vista and Windows Server 2008 machines use a new .evtx format that is a new format, so you can't use the same binary parsing approach across all versions. But the new EventLogQuery and EventLogReader classes are so fast that you won't have to. It's now perfectly speedy to just use the built-in classes.
Event Log Reader is horribly slow... too slow. WTF Microsoft?
Use LogParser 2.2 - Search for C# and LogParser on the Internet (or you can use the log parser commands from the command line). I don't want to duplicate the work already contributed by others.
I pull the log from the remote system by having the log exported as an EVTX file. I then copy the file from the remote system. This process is really quick - even with a network that spans the planet (I had issues with having the log exported to a network resource). Once you have it local, you can do your searches and processing.
There are multiple reasons for having the EVTX - I won't get into the reasons why we do this.
The following is a working example of the code to save a copy of the log as an EVTX:
(Notes: "device" is the network host name or IP. "LogName" is the name of the log desired: "System", "Security", or "Application". outputPathOnRemoteSystem is the path on the remote computer, such as "c:\temp\%hostname%.%LogName%.%YYYYMMDD_HH.MM%.evtx".)
static public bool DumpLog(string device, string LogName, string outputPathOnRemoteSystem, out string errMessage)
{
bool wasExported = false;
string errorMessage = "";
try
{
System.Diagnostics.Eventing.Reader.EventLogSession els = new System.Diagnostics.Eventing.Reader.EventLogSession(device);
els.ExportLogAndMessages(LogName, PathType.LogName, "*", outputPathOnRemoteSystem);
wasExported = true;
}
catch (UnauthorizedAccessException e)
{
errorMessage = "Unauthorized - Access Denied: " + e.Message;
}
catch (EventLogNotFoundException e)
{
errorMessage = "Event Log Not Found: " + e.Message;
}
catch (EventLogException e)
{
errorMessage = "Export Failed: " + e.Message + ", Log: " + LogName + ", Device: " + device;
}
errMessage = errorMessage;
return wasExported;
}
A good Explanation/Example can be found on MSDN.
EventLogSession session = new EventLogSession(Environment.MachineName);
// [System/Level=2] filters out the errors
// Where "Log" is the log you want to get data from.
EventLogQuery query = new EventLogQuery("Log", PathType.LogName, "*[System/Level=2]");
EventLogReader reader = new EventLogReader(query);
for (EventRecord eventInstance = reader.ReadEvent();
null != eventInstance;
eventInstance = reader.ReadEvent())
{
// Output or save your event data here.
}
When waiting 5-20 minutes with the old code this one does it in less than 10 seconds.
Maybe WMI can help you:
WMI with C#
Have you tried using the remoting features in powershell 2.0? They allow you to execute cmdlets (like ones to read event logs) on remote machines and return the results (as objects, of course) to the calling session.
You could place a Program at those machines that save the log to file and sends it to your webapplication i think that would be alot faster as you can do the looping local but im not sure how to do it so i cant ive you any code :(
I recently did such thing via WCF callback interface however my clients interacted with the server through WCF and adding a WCF Callback was easy in my project, full code with examples is available here
Just had the same issue and want to share my solution. It makes a search through application, system and security eventlogs from 260 seconds (using EventLog) about a 100 times faster (using EventLogQuery).
And this in a way where it is possible to check if the event message contains a pattern or any other check without the requirement of FormatDescription().
My trick is to use the same mechanism as PowerShells Get-WinEvent does and then pass it through the result check.
Here is my code to find all events within last 4 days where the event message contains a filter pattern.
string[] eventLogSources = {"Application", "System", "Security"};
var messagePattern = "*Your Message Search Pattern*";
var timeStamp = DateTime.Now.AddDays(-4);
var matchingEvents = new List<EventRecord>();
foreach (var eventLogSource in eventLogSources)
{
var i = 0;
var query = string.Format("*[System[TimeCreated[#SystemTime >= '{0}']]]",
timeStamp.ToUniversalTime().ToString("o"));
var elq = new EventLogQuery(eventLogSource, PathType.LogName, query);
var elr = new EventLogReader(elq);
EventRecord entryEventRecord;
while ((entryEventRecord = elr.ReadEvent()) != null)
{
if ((entryEventRecord.Properties)
.FirstOrDefault(x => (x.Value.ToString()).Contains(messagePattern)) != null)
{
matchingEvents.Add(entryEventRecord);
i++;
}
}
}
Maybe that the remote computers could do a little bit of computing. So this way your server would only deal with relevant information. It would be a kind of cluster using the remote computer to do some light filtering and the server would the the analysis part.