Get Operational log EventLog fails - c#

I get InvalidOperationException when I run this code:
static void Main(string[] args)
{
var aLog = new EventLog("Microsoft-Windows-Diagnostics-Performance/Operational");
EventLogEntry entry;
var entries = aLog.Entries;
var stack = new Stack<EventLogEntry>();
for (var i = 0; i < entries.Count; i++)
{
entry = entries[i];
stack.Push(entry);
}
entry = stack.Pop();// only display the last record
Console.WriteLine("[Index]\t" + entry.Index +
"\n[EventID]\t" + entry.InstanceId +
"\n[TimeWritten]\t" + entry.TimeWritten +
"\n[MachineName]\t" + entry.MachineName +
"\n[Source]\t" + entry.Source +
"\n[UserName]\t" + entry.UserName +
"\n[Message]\t" + entry.Message +
"\n---------------------------------------------------\n");
}
Exception says that:
Microsoft-Windows-Diagnostics-Performance/Operational doesn't exist on this computer
Why?

Updated
Since you are using EventLog class, the valid "categories" (for sure this is not the correct word to name it...) for your constructor must be Application, System or any other Log Name available under Windows Log tree, not under Applications And Services Log tree.
const string LogName = "Microsoft-Windows-Diagnostics-Performance/Operational";
var query = new EventLogQuery(LogName, PathType.LogName, "*[System/Level=2]");
using (var reader = new EventLogReader(query))
{
var currentEvent = reader.ReadEvent();
while (currentEvent != null)
{
// Do your stuff here...
// Read next event.
currentEvent = reader.ReadEvent();
}
}
This snippet code works for me.
Remember to run this under elevated privileges. If not, you'll receive an Unauthorized exception throw.
First Answer
Because you are initializing your EventLog class with a category that doesn't exists.
Typical valid categories would be Application, System, etc.
The single parameter constructor for EventLog refers to a log of the registry. [^]

Related

Retrieving members of a group that contains a subgroup

I created a dot.net form that uses c# code to retrieve members of an Active Directory group that a user selects from a drop-down, then displays the list of members (users is all I want) on the web page.
This works fine for groups that DO NOT contain sub-groups. When an Active Directory group contains users and sub-groups I receive an error.
I only want users of the group that the users selects from the drop-down. I don't want users from any sub-groups.
I have done lots of searching on the internet and testing various code suggestions.
public List<string> GetAllUsersFromGroup(string domain,
string group)
{
List<string> retVal = new List<string>();
DirectoryEntry entry = new DirectoryEntry(domain);
DirectorySearcher searcher = new DirectorySearcher("
(&(objectCategory=Group)(cn=" + group + "))");
searcher.SearchRoot = entry;
searcher.SearchScope = SearchScope.Subtree;
SearchResult result = searcher.FindOne();
var x = 0;
var txtCN = "";
var txtDispName = "";
var firstItem = 0; // Display Name
var secondItem = 1; // CN
var arraryResultsSize = result.Properties["member"].Count;
string[] deResultsArray = new string[arraryResultsSize];
foreach (string member in result.Properties["member"])
{
DirectoryEntry de = new DirectoryEntry(String.Concat(domain,
"/", member.ToString()));
if (de.Properties["objectClass"].Contains("user") &&
de.Properties["cn"].Count > 0)
{
deResultsArray[x] = de.Properties["displayName"]
[0].ToString() + "~" + de.Properties["cn"]
[0].ToString();
}
x = x + 1;
}
if (deResultsArray[0] != null) {
string[] sortSeperatedItems = sortLDAPUsers(deResultsArray);
for (var i = 0; i < sortSeperatedItems.Length/2; i++) {
txtDispName = "<tr><td>" + sortSeperatedItems[firstItem]
+ "</td>";
txtCN = "<td>" + sortSeperatedItems[secondItem] + "</td>
</tr>";
retVal.Add(txtDispName);
retVal.Add(txtCN);
firstItem = firstItem + 2;
secondItem = secondItem + 2;
}
} else {
txtDispName = "<tr><td>Group has no members</td>";
txtCN = "<td> </td></tr>";
retVal.Add(txtDispName);
retVal.Add(txtCN);
}
// retVal.Add("Array Size is: " + propCount);
return retVal;
}
public string[] sortLDAPUsers(string[] strArray) {
Array.Sort(strArray);
var newArraySize = (strArray.Length * 2);
string[] itemSeperated = new string[2];
string[] allSepItems = new string[newArraySize];
var arrayItemsString = "";
var xDName = 0;
var xCName = 1;
for (var i = 0; i < strArray.Length; i++) {
itemSeperated = strArray[i].Split('~');
allSepItems[xDName] = itemSeperated[0];
allSepItems[xCName] = itemSeperated[1];
arrayItemsString = arrayItemsString + "Length of allSepItems
is: " + allSepItems.Length + " Text is: " +
allSepItems[xDName] + " NetId is: " + allSepItems[xCName] +
"<br><br>";
xDName = xDName + 2;
xCName = xCName + 2;
}
return allSepItems;
}
When user selects an Active Directory group that contains users and sub-group(s), I receive the following error:
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 205: for (var i = 0; i < strArray.Length; i++) {
Line 206:
Line 207: itemSeperated = strArray[i].Split('~');
Line 208: allSepItems[xDName] = itemSeperated[0];
Line 209: allSepItems[xCName] = itemSeperated[1];
I think the error has to do with how I'm filtering or getting results in GetAllUsersFromGroup(). I don't know how to just get users from a group and not include any sub-group(s) in the results.
The problem with this filter (&(objectCategory=Group)(cn=<group>)) is that you are querying a specific group to iterate and grab all its members regardless of the type/objectClass, so you are left with users, groups and whatever.
Instead, you can request users that are members of this group directly using the proper filter :
new DirectorySearcher("(&(objectCategory=person)(memberOf=" + groupDN + "))");
Note that the memberOf attribute must match a DN, so given the passed in variable group (if the caller can't pass the actual group dn) you may have to grab it in the first place using the 1st filter.
The error you get then is another issue due to sorting, maybe comment this part until you get the proper results.
You do not need to work that hard when you could let Microsoft Active Directory do the work.
An LDAP search request with an LDAP filter to Resolve all members (including nested) Security Groups (requires at least Windows 2003 SP2)
(&(objectClass=user)(memberof:1.2.840.113556.1.4.1941:=CN=GroupOne,OU=Security Groups,OU=Groups,DC=YOURDOMAIN,DC=NET)
This will return all (objectClass=user) that are members of the "GroupOne".

How to copy file from one library to another library using CSOM?

I need to copy a particular file from one library to another library.
At first, need to check if file is existing in that library.
If Existing, then need to overwrite file content and new sharepoint version should be updated for that document.
I need to do this using c# CSOM and sharepoint version is 2013.
Thanks in advance :)
public static void CopyDocuments(string srcUrl, string destUrl, string srcLibrary, string destLibrary, Login _login)
{
// set up the src client
SP.ClientContext srcContext = new SP.ClientContext(srcUrl);
srcContext.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
srcContext.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(_login.UserName, _login.Password);
// set up the destination context (in your case there is no needs to create a new context, because it would be the same library!!!!)
SP.ClientContext destContext = new SP.ClientContext(destUrl);
destContext.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
destContext.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(_login.UserName, _login.Password);
// get the list and items
SP.Web srcWeb = srcContext.Web;
SP.List srcList = srcWeb.Lists.GetByTitle(srcLibrary);
SP.ListItemCollection col = srcList.GetItems(new SP.CamlQuery());
srcContext.Load(col);
srcContext.ExecuteQuery();
// get the new list
SP.Web destWeb = destContext.Web;
destContext.Load(destWeb);
destContext.ExecuteQuery();
foreach (var doc in col)
{
try
{
if (doc.FileSystemObjectType == SP.FileSystemObjectType.File)
{
// get the file
SP.File f = doc.File;
srcContext.Load(f);
srcContext.ExecuteQuery();
// build new location url
string nLocation = destWeb.ServerRelativeUrl.TrimEnd('/') + "/" + destLibrary.Replace(" ", "") + "/" + f.Name;
// read the file, copy the content to new file at new location
SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
}
if (doc.FileSystemObjectType == SP.FileSystemObjectType.Folder)
{
// load the folder
srcContext.Load(doc);
srcContext.ExecuteQuery();
// get the folder data, get the file collection in the folder
SP.Folder folder = srcWeb.GetFolderByServerRelativeUrl(doc.FieldValues["FileRef"].ToString());
SP.FileCollection fileCol = folder.Files;
// load everyting so we can access it
srcContext.Load(folder);
srcContext.Load(fileCol);
srcContext.ExecuteQuery();
foreach (SP.File f in fileCol)
{
// load the file
srcContext.Load(f);
srcContext.ExecuteQuery();
string[] parts = null;
string id = null;
if (srcLibrary == "My Files")
{
// these are doc sets
parts = f.ServerRelativeUrl.Split('/');
id = parts[parts.Length - 2];
}
else
{
id = folder.Name;
}
// build new location url
string nLocation = destWeb.ServerRelativeUrl.TrimEnd('/') + "/" + destLibrary.Replace(" ", "") + "/" + id + "/" + f.Name;
// read the file, copy the content to new file at new location
SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
}
}
}
catch (Exception ex)
{
Log("File Error = " + ex.ToString());
}
}
}
Source: https://sharepoint.stackexchange.com/questions/114033/how-do-i-move-files-from-one-document-library-to-another-using-jsom
I strongly advise against using the approach suggested by Nikerym. You don't want to download the bytes only to upload them unmodified. It's slow and error-prone. Instead, use the built-in method provided by the CSOM API.
https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/mt162553(v=office.15)?redirectedfrom=MSDN
var srcPath = "https://YOUR.sharepoint.com/sites/xxx/SitePages/Page.aspx";
var destPath = $"https://YOUR.sharepoint.com/sites/xxx/SitePages/CopiedPage.aspx";
MoveCopyUtil.CopyFileByPath(ctx, ResourcePath.FromDecodedUrl(srcPath), ResourcePath.FromDecodedUrl(destPath), false, new MoveCopyOptions());
ctx.ExecuteQuery();
You can configure the override behavior by adjusting the 4th and 5th arguments of the function signature.
[...]
bool overwrite,
MoveCopyOptions options
https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/mt844930(v=office.15)

Instance '[Instance Name]' does not exist in the specified Category

We are developing project for oracle database performance counter in webapi.The code for getting the instance name shown below
string pid = GetCurrentProcessId().ToString();
string instanceName2 =AppDomain.CurrentDomain.FriendlyName.ToString().Replace('(', '[')
.Replace(')', ']').Replace('#', '_').Replace('/', '_').Replace('\\', '_');
instName = instanceName2 + "[" + pid + "]";
and setting the instance in PerformanceCounter class
PerformanceCounter perfCounter = new PerformanceCounter();
perfCounter.CategoryName = catagoryName;
perfCounter.CounterName = counterName;
perfCounter.InstanceName = instName;
code for reading the counter value shown below
foreach (PerformanceCounter p in this.PerfCounters)
{
string counterValue = string.Join("=", p.CounterName, p.NextValue());
obj.textBox1.AppendText("\r\n" + counterValue);
}
when I trying to read the counter values getting exception like, Instance '[Instance Name]' does not exist in the specified Category.After opening the DB connection unable to detect instance name.

How do I retrieve a list of users from Active Directory using C#?

I want to create an online user directory and pull the information directly from Active Directory. So after hours of searching I came up with this solution(which is not much of a solution). When I run my program all it does is spin like it wants to do something but after all of the spinning it gives me a blank white page.
protected void btnClick_Click1(object sender, EventArgs e)
{
string dom = txtDomainName.Text;
System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry("LDAP://" + dom);
System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(entry);
mySearcher.Filter = ("(objectClass=user)");
Console.WriteLine("Listing of users in the Active Directory");
Console.WriteLine("========================================");
foreach (System.DirectoryServices.SearchResult resEnt in mySearcher.FindAll())
{
try
{
System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();
Console.WriteLine("Display Name : " + de.Properties["DisplayName"].Value.ToString());
Console.WriteLine("Email : " + de.Properties["Mail"].Value.ToString());
Console.WriteLine("Title : " + de.Properties["Title"].Value.ToString());
Console.WriteLine("User Name : " + de.Properties["sAMAccountName"].Value.ToString());
Console.WriteLine("First Name : " + de.Properties["GivenName"].Value.ToString());
Console.WriteLine("Last Name : " + de.Properties["sn"].Value.ToString());
Console.WriteLine("Initials : " + de.Properties["Initials"].Value.ToString());
Console.WriteLine("Company : " + de.Properties["Company"].Value.ToString());
Console.WriteLine("Department : " + de.Properties["Department"].Value.ToString());
Console.WriteLine("Telephone No. : " + de.Properties["TelephoneNumber"].Value.ToString());
}
catch (Exception ex)
{
}
Console.WriteLine("=========== End of user =============");
}
Console.WriteLine("=========== End of Listing =============");
}
Please note that I know little to nothing about active directory, only that it can be use to store Employee Information and create and manage user groups. I have used C# and LDAP to create login pages that requires and verifies username and password from ID to pass authentication.
Edited
The application posted requires the user to put in their domain. After I enter the domain name it should list all users or something, it just spins and gives me a white page of nothing
Instead of using
Console.WriteLine(
try
Response.Write(string.Format(
This will give you a print out and that should fix your blank page issue.
I tested this in a console based application. I used the Directory.Services.AccountManagement class to achieve this. In my example, I am just listing the names.
private static string SearchUsers(UserPrincipal parUserPrincipal)
{
PrincipalSearcher insPrincipalSearcher = new PrincipalSearcher {QueryFilter = parUserPrincipal};
PrincipalSearchResult<Principal> results = insPrincipalSearcher.FindAll();
var builder = new StringBuilder();
foreach (UserPrincipal p in results)
{
builder.AppendFormat("SamAccountName:{0}\t DisplayName:{1}\tUserPrincipal:{2}\tDescription:{3}\tEmail:{4}\tTel:{5}\n", p.SamAccountName, p.DisplayName, p.UserPrincipalName, p.Description, p.EmailAddress, p.VoiceTelephoneNumber);
}
return builder.ToString();
}
public static string SetPrincipal()
{
// **Make sure you set the correct domain name**
var pc = new PrincipalContext(ContextType.Domain, "myCompany");
UserPrincipal insUserPrincipal = new UserPrincipal(pc) {Name = "*"};
return SearchUsers(insUserPrincipal);
}

Get Username of an Accesed File

I would like to get the username of an accessed file (add, delete, rename,...).
actually I use filesystemwatcher to monitor the file access and I have activated object access on an directory to get userinformation via eventlogs. This solution is not perfect, because there are a lot of file events and the eventlog messages are not so detailed. there is just one eventd id for write data. this it is used for add file, rename , move,... every write data. Additionally I had to crosscheck that the eventlog message matches the filesystemwatcher event. I would prefer handle this better. so i spend al lot of time googleing, reading, ... I know there is another post on stackoverflow
Get username of opened file
but i think there should be a possible solution because Windows Events can get the username.
with reading on a few pages i disovered that there should be a possible solution using netapi32.dll. the example code on
http://vbcity.com/forums/t/133307.aspx?PageIndex=2
doesn't work for me. i was unable to get the fileid so i changed the code to
private ulong GetFileIdFromPath(string filePath)
{
WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo = new WinAPI.BY_HANDLE_FILE_INFORMATION();
Thread.Sleep(200);
FileInfo fi = new FileInfo(filePath);
FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
WinAPI.GetFileInformationByHandle(fs.Handle, out objectFileInfo);
fs.Close();
ulong fileIndex = ((ulong)objectFileInfo.FileIndexHigh << 32) + (ulong)objectFileInfo.FileIndexLow;
return fileIndex;
}
with this code I'm able to get the fileid but with the fileid and the example code I'm unable to get the username.
From My last program ( 2 week ago) - I was asked to audit change in files ( also the user name)
the Solution was by filesystemwatcher and after an event -> goto the Event Log of windows and bu Xpath search - To find which user made the action.
public static EventUnit DisplayEventAndLogInformation(string fileToSearch, DateTime actionTime)
{
StringBuilder sb = new StringBuilder();
const string queryString = #"<QueryList>
<Query Id=""0"" Path=""Security"">
<Select Path=""Security"">*</Select>
</Query>
</QueryList>";
EventLogQuery eventsQuery = new EventLogQuery("Security", PathType.LogName, queryString);
eventsQuery.ReverseDirection = true;
EventLogReader logReader = new EventLogReader(eventsQuery);
EventUnit e = new EventUnit();
bool isStop = false;
for (EventRecord eventInstance = logReader.ReadEvent(); null != eventInstance; eventInstance = logReader.ReadEvent())
{
foreach (var VARIABLE in eventInstance.Properties)
if (VARIABLE.Value.ToString().ToLower().Contains(fileToSearch.ToLower()) && actionTime.ToString("d/M/yyyy HH:mm:ss") == eventInstance.TimeCreated.Value.ToString("d/M/yyyy HH:mm:ss"))
{
foreach (var VARIABLE2 in eventInstance.Properties) sb.AppendLine(VARIABLE2.Value.ToString());
e.Message = sb.ToString();
e.User = (eventInstance.Properties.Count > 1) ? eventInstance.Properties[1].Value.ToString() : "n/a";
e.File = fileToSearch;
isStop = true;
break;
}
if (isStop) break;
try
{
// Console.WriteLine("Description: {0}", eventInstance.FormatDescription());
}
catch (Exception e2)
{
}
}
return e;
}

Categories