Using array foreach loop with variables c# - c#

you very helpful people,
I am currently trying to go through an array of "permissions" run a block of code to check if there have been any changes made and then add the changes as a log on our site.
I currently have the following array (this is a very slimmed down version of the array in question):
string[] permissions = {"CanLogOn",
"CanAddConsignments",
"CanAddUsers",
"CanListBrokers",
"CanViewBrokers",
"CanAddBrokers",
"CanModifyBrokers",
"CanPutAwayWaste"};
This array is saved in the same file just above this snippet of code:
if (dbSecurityGroup.PermissionList != model.PermissionList)
{
foreach (string permission in permissions)
{
if (dbSecurityGroup.PermissionList.permission != model.PermissionList.permission)
{
model.PermissionList.Logs.Add(model.PermissionList.Log(Logger.LogType.Information, permission + " was edited by " + Authentication.AuthenticationManager.LoggedOnUser.Name));
};
};
}
As you can see we have a lot of permissions that are always being added too so we need this to be scalable and check if any of the permissions have changed.
The following code will work as intended but is for a single permission, we are just trying to find a more efficient way of producing this code for many permissions:
if (dbSecurityGroup.PermissionList != model.PermissionList)
{
if (dbSecurityGroup.PermissionList.CanLogOn != model.PermissionList.CanLogOn)
{
model.PermissionList.Logs.Add(model.PermissionList.Log(Logger.LogType.Information, "Can Log On was edited by " + Authentication.AuthenticationManager.LoggedOnUser.Name));
};
}
Any help is more than welcome. (if this method can be used we will also need a RegEx to put a space in between all of the capitals when producing the logs, to change "CanLogOn" to "Can Log On")

Related

c# DirectoryEntrie Propertie allowedAttributesEffective is always null

I have a very old project that worked like a charm for many years.
All of a sudden It seems that the following code snippet is only returning false because the "allowedAttributesEffective" property is null, and therefore thinking that the user has no rights to Modify an AD object
public static bool checkWritePermission(DirectoryEntry de) {
de.RefreshCache(new string[] { "allowedAttributesEffective" });
log.write("Write permission == " + (bool)(de.Properties["allowedAttributesEffective"].Value != null), 5);
// Outputs always -> "Write permission == False"
return de.Properties["allowedAttributesEffective"].Value != null;
}
The "original" codes taken years ago from here: How can I check if a user has write rights in Active Directory using C#?
In reality the user that executes this code should have modify permissions on all AD Objects (proven by the fact that I can Modify all objects in question via Active Directory Users and Computers Management Interface)
Any Ideas what the issue could be here?
I have also tried with ldapsearch on linux to see if I can read the property "allowedAttributesEffective" but I have not found a clear answer if that should even be the case as it is not returning anything on any LDAP object

C# active directory update unknown error for 2 people

I have a C# console application that updates Active Directory properties using data from the HR system.
Below is a sample of the code I'm using to update the manager property:-
if (ADManagerPath != adManager)
{
if (enableActiveDirectoryUpdates)
{
if (ADManagerPath.Length > 0)
{
deLDAPUpdate.Properties["manager"].Value = ADManagerPath;
managerUpdated++;
}
else
{
deLDAPUpdate.Properties["manager"].Clear();
managerBlanked++;
}
}
managerChanged = true;
}
Obviously, there are other properties that I am updating and finally if I have made any changes, there is a CommitChanges statement.
My issue is that the line will I am setting the manager, fails but only for 2 active directory accounts (which may well be for the same person).
The error codes I am receiving are (0x80005000) -2147463168. I have searched the site, and others, however most answers appear to be cases where LDAP has not been capitalized or the property/attribute you're trying to update does not exist. Both of which I do not believe apply to my situation, as I can update other accounts.
Can anybody help?
Okay I have fixed the above problem but still have a problem with these 2 accounts. The value I was reading from a database, somehow had an extra backslash in the manager path and that was the problem for setting the manager. My program now successfully can update a person's manager to 1 of these 2 accounts.
However I still believe there is a problem with the 2 accounts in question. I cannot set any property for the 2 accounts in question. Interestingly, I have developed a program, only for my use, where you enter a samAccountName and it will display and iterate through all the properties. However, this program also falls over when I attempt to use it on either of these accounts.
I write any errors to an exception table and all that error message says is "Unknown error (0x80005000)".
This program has been running for a couple of months, although it has been developed further over the past few weeks, and it is only these 2 accounts that will not update?
The code that I am using to create the various active directory connection objects is:-
string gcConnection = "GC://" + guidBindRootPath + "/<GUID=" + adID + ">";
deGUIDBind.Username = username;
deGUIDBind.Password = password;
deGUIDBind.AuthenticationType = AuthenticationTypes.Secure;
deGUIDBind.Path = gcConnection;
deLDAPUpdate.Username = username;
deLDAPUpdate.Password = password;
deLDAPUpdate.AuthenticationType = AuthenticationTypes.Secure;
string distinguishedName = deGUIDBind.Properties["distinguishedName"].Value.ToString();
string ldapConnection = "LDAP://" + getDomainNameFromDistinguishedName(distinguishedName) + "/" + distinguishedName;
deLDAPUpdate.Path = ldapConnection;
`
To reiterate, I have solved the problem of setting, the accounts in question, as the manager of other accounts, however, I can still not change any of the properties of the 2 problematic accounts. My program successfully updates other accounts.
The other program that I have written, in C#, which iterates through and displays all the properties, for a given samAccountName, also falls over for these 2 accounts.
string adDivision = convertNullToString(deLDAPUpdate.Properties["Division"].Value);
propertyDetails = propertyDetails + "Division" + "," + adDivision + Environment.NewLine;
foreach (System.DirectoryServices.PropertyValueCollection p in deLDAPUpdate.Properties)
With regard to the 2 problem accounts, this program falls over both on attempt to retrieve the division property and also when it attains to evaluate deLDAPUpdate.Properties.
I am not asking for help with the 2nd application, which is only for my own use, I only mention it since it seems to indicate that there might be a problem with the 2 accounts. This test application successfully displays the properties of other accounts.

Sharepoint 2007 - is there a way to determine if first check-in of file?

I thought this would be a lot easier, however I'm unable to find a way to determine in my event handler if it is the FIRST check-in of the file..
You see, I'm breaking role inheritance, and selectively inheriting permissions for files in doc libs, yet I wish to do it only once, during the first check-in of the file.
I've tried adding an entry to 'SPListItem.Properties' in the ItemAdded event in order to indicate if the file is new, however the moment I do 'SPListItem.Update()' it vanishes..
I've played with the ItemCheckingIn and ItemCheckedIn events with no success...
My only hope at the moment is adding a SPField to the ContentType to indicate if new file or not, but I really wish to avoid it..
ANY IDEAS????
PLEASE HELP ME!
I would recommend considering not only whether the system account has access, but also if the checked out date of the file is identical to the file's creation date.
public bool IsFirstCheckIn(SPListItem item)
{
// Item not null!
if (item != null)
{
SPSecurity.RunWithElevatedPrivileges(delegate
{
// Open privileged Site
using (SPSite pSite = new SPSite(site.ID))
{
// Open privileged Web
using (SPWeb pWeb = pSite.OpenWeb(web.ID))
{
// Create privileged SharePoint-Objects
SPList pList = GetList(pWeb, list.ID);
SPListItem pItem = GetListItem(pList, item.UniqueId);
// Check the Item
if (pItem == null)
{
// Can't access
return true;
}
else if (pItem.File != null && pItem.File.CheckedOutByUser != null)
{
// If the Item's File and checked out User is set, check if checked out date is equal creation date
return (pItem.File.CheckedOutDate.ToLocalTime() == pItem.File.TimeCreated.ToLocalTime());
}
}
}
});
}
return false;
}
To use the system account, is definitely a good idea, otherwise authorization settings would cause problems. Use the "local time" instead of the "UTC-Time", SharePoint handled the Time Zone while storing!
Seems like, SharePoint used the UTF-FileTime to store the file's creation time but used the Time Zone defined for the SPWeb or for the SPUser to store the file checked out date based on the "local time".
Fortunately the DateTime value does know what it is and can convert it to the same "local time" while calling ToLocalTime(). Strangely it will be still a File-Time while calling ToUniversalTime();
So I got a solution for this.
I'm sorry I can't post code here, I do not have access to internet on my dev machine.
It should be good enough for everyone.
Solution:
During the CheckingIn event I try to access the file using the SHAREPOINT\system("SPSecurity.RunWithElevatedPrivileges()"). During the first check-in the file is new and not accessible to other users besides the uploader.
So if I fail getting the file with SHAREPOINT\system it means its new, and I save its Guid in a dictionary in my EventHandlers class.
Then in the CheckedIn event I simply check if the dictionary contains the Guid of the current item, if it does - FIRST CHECK-IN, if it does not - NOT FIRST CHECK-IN.
Of course after I'm finished with the file I remove the entry from the dictionary.
Hope it helps, if you got any questions you are welcome to ask :)

How can I check access rights on a given directory?

Currently I have a program that searches a user set directory and sub-directories for music files and adds them to a collection. However if one of the directories it comes accross is protected then the program falls over. I wanted to know how I can check if the user has access to the directory before trying to search it to avoid this problem.
Below is the code I'm using for the search, it currently contains a basic work around for "System Volume Information" but as there is a possibility that there may be other protected directories I wanted to change this to include them.
public void SearchForMusic()
{
//Searches selected directory and its sub directories for music files and adds their path to ObservableCollection<string> MusicFound
foreach (string ext in extentions)
{
foreach (string song in Directory.GetFiles(SearchDirectory, ext))
{
musicFound.Add(song);
}
foreach (string directory in Directory.GetDirectories(SearchDirectory))
{
if (directory.Contains("System Volume Information"))
{
}
else
{
foreach (string song in Directory.GetFiles(directory, ext))
{
musicFound.Add(song);
}
foreach (string subDirectory in Directory.GetDirectories(directory))
{
foreach (string subSong in Directory.GetFiles(subDirectory, ext))
{
musicFound.Add(subSong);
}
}
}
}
}
}
Many thanks :)
By far the easiest way to be sure that you have access to a file system object is to attempt to access it. If it fails with an Access Denied error, then you don't have access. Just detect that error condition and proceed with the next item in the search.
In other words, delegate checking access to the system which is, after all, the ultimate arbiter of access rights.
You can check this question by replacing the Write with Read permissions. Also, wrap your code in a try catch block and if the exception is thrown, you can assume (or properly check the exception type to be sure) that the directory cannot be traversed.

Scanning a drive with drilldowns using C#?

I'm trying to create an application which scans a drive. The tricky part though, is that my drive contains a set of folders that have folders within folders and contain documents. I'm trying to scan the drive, take a "snapshot" of all documents & folders and dump into a .txt file.
The first time i run this app, the output will be a text file with all the folders & files.
The second time i run this application, it will take the 2 text files (the one produced from the 2nd time i run the app and the .txt file from the 1st time i have run the app) and compare them...reporting what has been moved/overridden/deleted.
Does anybody have any code for this? I'm a newbie at this C# stuff and any help would be greatly appreciated.
Thanks in advance.
One thing that we learned in the 80's was that if it's really tempting to use recursion for file system walking, but the moment you do that, someone will make a file system with nesting levels that will cause your stack to overflow. It's far better to use heap-based walking of the file system.
Here is a class I knocked together which does just that. It's not super pretty, but it does the job quite well:
using System;
using System.IO;
using System.Collections.Generic;
namespace DirectoryWalker
{
public class DirectoryWalker : IEnumerable<string>
{
private string _seedPath;
Func<string, bool> _directoryFilter, _fileFilter;
public DirectoryWalker(string seedPath) : this(seedPath, null, null)
{
}
public DirectoryWalker(string seedPath, Func<string, bool> directoryFilter, Func<string, bool> fileFilter)
{
if (seedPath == null)
throw new ArgumentNullException(seedPath);
_seedPath = seedPath;
_directoryFilter = directoryFilter;
_fileFilter = fileFilter;
}
public IEnumerator<string> GetEnumerator()
{
Queue<string> directories = new Queue<string>();
directories.Enqueue(_seedPath);
Queue<string> files = new Queue<string>();
while (files.Count > 0 || directories.Count > 0)
{
if (files.Count > 0)
{
yield return files.Dequeue();
}
if (directories.Count > 0)
{
string dir = directories.Dequeue();
string[] newDirectories = Directory.GetDirectories(dir);
string[] newFiles = Directory.GetFiles(dir);
foreach (string path in newDirectories)
{
if (_directoryFilter == null || _directoryFilter(path))
directories.Enqueue(path);
}
foreach (string path in newFiles)
{
if (_fileFilter == null || _fileFilter(path))
files.Enqueue(path);
}
}
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
Typical usage is this:
DirectoryWalker walker = new DirectoryWalker(#"C:\pathToSource\src", null, (x => x.EndsWith(".cs")));
foreach (string s in walker)
{
Console.WriteLine(s);
}
Which recursively lists all files that end in ".cs"
A better approach than your text file comparisons would be to use the FileSystemWatcher Class.
Listens to the file system change notifications and raises events when a directory, or file in a directory, changes.
You could log the changes and then generate your reports as needed from that log.
you can easily utilize the DirectoryInfo/FileInfo classes for this.
Basically instantiate an instance of the DirectoryInfo class, pointing towards the c:\ folder. Then using it's objects walk the folder structure.
http://msdn.microsoft.com/en-us/library/system.io.directoryinfo.aspx has code that could quite easily be translated.
Now, the other part of your question is insanity. You can find the differences between the two files relatively easily, but translating that into what has been moved/deleted/etc will take the some fairly advanced logic structures. After all, if I have two files, both named myfile.dat, and one is found at c:\foo and the other at c:\notfoo, how would the one at c:\notfoo be reported if I deleted the one at c:\foo? Another example, is if I have a file myfile2.dat and copy it from c:\bar to c:\notbar is that considered a move? What happens if I copy it on Tuesday, and then on Thursday I delete c:\bar\myfile2.dat--is that a move or a delete? And would the answer change if I ran the program on every Monday as opposed to daily?
There's a whole host of questions, and their corresponding logic structures which you'd need to think of amd code for in order to build that functionality, and even then, it would not be 100% correct, because it's not paging the file system as changes occur--there will always exist the possibility of a scenario that did not get reported correctly in your logic due to timing, logic structure, process time, when the app runs, or just due to the sheer perversity of computers.
Additionally, the processing time would grow exponentially with the size of your drive. After all, you'd need to check every file against every other file to determine it's state as opposed to its previous state. I'd hate to have to run this against my 600+GB drive at home, let alone the 40TB drives I have on servers at work.

Categories

Resources