I'm trying to write my own checking policy.
I want to review if any .cs file contains some code. So my question is, if its possible to get the content of every file from the changeset in the overridden Initialize-Method and/or Evaluate-Method (from PolicyBase).
You can't get the contents from the files directly, you'll need to open them yourselves. For each checked In your Evaluate method, you should look at the PendingCheckin.PendingChanges.CheckedPendingChanges (to ensure that you only limit yourself to the pending changes that will be checked in.) Each PendingChange has a LocalItem that you can open and scan.
For example:
public override PolicyFailure[] Evaluate()
{
List<PolicyFailure> failures = new List<PolicyFailure>();
foreach(PendingChange pc in PendingCheckin.PendingChanges.CheckedPendingChanges)
{
if(pc.LocalItem == null)
{
continue;
}
/* Open the file */
using(FileStream fs = new FileStream(pc.LocalItem, ...))
{
if(/* File contains your prohibited code */)
{
failures.Add(new PolicyFailure(/* Explain the problem */));
}
fs.Close();
}
}
return failures.ToArray();
}
Related
I need to retrieve paths of files and folders currently copied into the clipboard, is this possible in C#?
So let's say I do Ctrl + C a folder. That folder will go to clipboard, I need a way to extract the path to that folder. Same goes for copied files.
I'm developing a file server, I already can send files and folders: all I need is to provide a list of paths to the function.
Microsoft supplies some samples about it:
Have a look at: DragDropOpenTextFile
This is the method used to check it there is a file copied in the clipboard:
// If the data object in args is a single file, this method will return the filename.
// Otherwise, it returns null.
private string IsSingleFile(DragEventArgs args)
{
// Check for files in the hovering data object.
if (args.Data.GetDataPresent(DataFormats.FileDrop, true))
{
var fileNames = args.Data.GetData(DataFormats.FileDrop, true) as string[];
// Check for a single file or folder.
if (fileNames?.Length is 1)
{
// Check for a file (a directory will return false).
if (File.Exists(fileNames[0]))
{
// At this point we know there is a single file.
return fileNames[0];
}
}
}
return null;
}
You get a DragEventArgs from the Drop event handler of your control.
private void EhDrop(object sender, DragEventArgs args)
{
// Mark the event as handled, so Control's native Drop handler is not called.
args.Handled = true;
var fileName = IsSingleFile(args);
if (fileName != null)
{
// Do something.
}
}
Ok got it to work myself, Clipboard.GetFileDropList() gets you both files and folders paths, what a neat little function!
var unparsedFilesList = Clipboard.GetFileDropList();
foreach(var filePath in unparsedFilesList)
{
MessageBox.Show(filePath);
}
I am using a WinForms PropertyGrid to display various configuration settings for a program. The PropertyGrid is bound to an XML document which has been Xmlserializer.Deserialize-ed. This allows a user to type in new values, which then get serialized back into the config.xml file. In some cases, these properties are just numbers, and typing in values makes sense. However, in other cases, the values are file names or directory paths, so it makes much more sense to have these entered through an OpenFileDialog or FolderBrowserDialog.
What I'd like to have happen is that the if user clicks on a folder or filename cell in the PropertyGrid, the UI will open the appropriate dialog, get a result, and enter that result into the grid, replacing the existing value. The trouble is, PropertyGrid doesn't seem to allow access to the controls inside it, so I can't respond to an OnClicked event.
Here's how I would like the code to work (EDIT: updated code):
private void propertyGrid_config_Click(object sender, EventArgs e)
{
PropertyGrid grid = (PropertyGrid)sender;
PropertyDescriptor selectedItem = grid.SelectedGridItem.PropertyDescriptor;
if (selectedItem.Category == "Files & Folders")
{
if (selectedItem.DisplayName.Contains("directory"))
{
FolderBrowserDialog folder = new FolderBrowserDialog();
if (folder.ShowDialog() == DialogResult.OK)
{
selectedItem.SetValue(grid.SelectedObject, folder.SelectedPath);
grid.Refresh();
}
}
else if (selectedItem.DisplayName.Contains("file"))
{
OpenFileDialog file = new OpenFileDialog();
if (file.ShowDialog() == DialogResult.OK)
{
selectedItem.SetValue(grid.SelectedObject, file.FileName);
grid.Refresh();
}
}
}
}
I've set the grid's "Clicked" event to this handler, but obviously that doesn't work since that only handles the container and not what's in it. (Note this handler works fine if I base it on the "PropertyChanged" event, but that's obviously not what I'm looking for.)
Is there some way to get access to the components and create the events I want? How would you conquer this issue?
In case it's relevant, here's some of the code for the PropertyGrid:
The grid exists in a class called "Configuration" which defines all the properties like this:
[Description("Folder for storing Bonding Key logs")]
[Category("Files & Folders")]
[DisplayName("Log output directory")]
public string dirLogOutput { get; set; }
The XML file will have a corresponding entry for each Property like this:
<dirLogOutput>C:\Users\AHoffman\Desktop\TestData</dirLogOutput>
The Serializer does a good job of matching data from the XML file to the grid, and vice-versa:
public Configuration TryLoadConfiguration(Configuration thisConfig)
{
string filename = GetConfigFilename();
try
{
if (!File.Exists(filename))
{
thisConfig.setDefaults();
}
else
{
using (var stream = File.Open(filename, FileMode.Open, FileAccess.Read))
{
var serializer = new XmlSerializer(typeof(Configuration));
thisConfig = (Configuration)serializer.Deserialize(stream);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to load configuration file during startup: " + ex.Message);
thisConfig.setDefaults();
}
return thisConfig;
}
private void SaveConfiguration(string filename, Configuration thisConfig)
{
try
{
using (var stream = File.Open(filename, FileMode.Create, FileAccess.Write))
{
var serializer = new XmlSerializer(typeof(Configuration));
serializer.Serialize(stream, thisConfig);
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to save configuration file: " + ex.Message);
}
}
I note that a question like this has been asked before here but with no answers. Hopefully I'm giving you enough info to get something back.
OK never mind. I found answers to my question here (for files) and here (for folders).
It all relies in using a custom UITypeEditor for each type.
[EditorAttribute(typeof(OpenFileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
[EditorAttribute(typeof(FolderNameEditor2), typeof(System.Drawing.Design.UITypeEditor))]
Thanks greatly to #Simon Mourier, #Stewy, and #tzup for their answers.
I'm programming an app that interact with dropbox by use DropNet API. I want to check if the folder is exist or not on dropbox in order to I will create one and upload file on it after that. Everything seen fine but if my folder is exist it throw exception. Like this:
if (isAccessToken)
{
byte[] bytes = File.ReadAllBytes(fileName);
try
{
string dropboxFolder = "/Public/DropboxManagement/Logs" + folder;
// I want to check if the dropboxFolder is exist here
_client.CreateFolder(dropboxFolder);
var upload = _client.UploadFile(dropboxFolder, fileName, bytes);
}
catch (DropNet.Exceptions.DropboxException ex) {
MessageBox.Show(ex.Response.Content);
}
}
I'm not familiar with dropnet, but looking at the source code, it appears you should be able to do this by using the GetMetaData() method off of your _client object. This method returns a MetaData object.
Example:
//gets contents at requested path
var metaData = _client.GetMetaData("/Public/DropboxManagement/Logs");
//without knowing how this API works, Path may be a full path and therefore need to check for "/Public/DropboxManagement/Logs" + folder
if (metaData.Contents.Any(c => c.Is_Dir && c.Path == folder)
{
//folder exists
}
How would I use Linq on list.Items = directoryInfo.GetFiles("\\server\share\folder\"); to include only the files the user has read access to?
...
So far only suggestions are using try/catches, or APIs that are obsolete in .NET 4.0? I'd prefer something to read the ACL's and see if the specific user or a group the user is a member of has been granted read access. I'm trying to do this for simplified management of granting reports to users on a website that won't be high traffic, so the logic that "who knows if you can actually read it when you try to open the file" doesn't pertain to this case. I sense that Microsoft should really make this task easier.
You run the risk of a race condition if you check for read permission prior to opening the file.
If you're attempting to read all of the files you have access to in a folder, better to just try opening each one and catch the UnauthorizedAccessException.
See:
how can you easily check if access is denied for a file in .NET?
How do you check for permissions to write to a directory or file?
just try this out .should work .haven't tested though
var fw = from f in new DirectoryInfo("C:\\Users\\User\\Downloads\\").GetFiles()
where SecurityManager.IsGranted(new FileIOPermission
(FileIOPermissionAccess.Write, f.FullName))
select f;
EDIT if it is just read only files then try this
var fe = from f in new DirectoryInfo("C:\\Users\\ashley\\Downloads\\").GetFiles()
where f.IsReadOnly==true
select f
Note: I haven't tested it, but in theory it should work
First, define a predicate to determine read access
bool CanRead(FileInfo file)
{
try {
file.GetAccessControl();
//Read and write access;
return true;
}
catch (UnauthorizedAccessException uae)
{
if (uae.Message.Contains("read-only"))
{
//read-only access
return true;
}
return false;
}
}
Then, it should be a simple case of using a where clause in a linq query
from file in directoryInfo.GetFiles("\\server\share\folder\")
where HaveAccess(f) == true
select f;
Tested and working, but will return false if the file is in use
void Main()
{
var directoryInfo = new DirectoryInfo(#"C:\");
var currentUser = WindowsIdentity.GetCurrent();
var files = directoryInfo.GetFiles(".").Where(f => CanRead(currentUser, f.FullName));
}
private bool CanRead(WindowsIdentity user, string filePath)
{
if(!File.Exists(filePath))
return false;
try
{
var fileSecurity = File.GetAccessControl(filePath, AccessControlSections.Access);
foreach(FileSystemAccessRule fsRule in fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)))
{
foreach(var usrGroup in user.Groups)
{
if(fsRule.IdentityReference.Value == usrGroup.Value)
return true;
}
}
} catch (InvalidOperationException) {
//File is in use
return false;
}
return false;
}
I want to move a directory from one location to another using C# .NET. I used Directory.Move or even DirectoryInfo (with MoveTo) this simple way:
// source is: "C:\Songs\Elvis my Man"
// newLocation is: "C:\Songs\Elvis"
try
{
// Previous command was: Directory.Move(source, newLocation);
DirectoryInfo dir = new DirectoryInfo(source);
dir.MoveTo(newLocation);
}
catch (Exception e)
{
Console.WriteLine("Error: "+ e.Message);
}
But action that's being done (for both cases) is renaming the folder name from 'source' to 'newLocation'
What I expected? that folder "Elvis my man" will be now in "Elvis" folder.
What has happened? "Elvis my man" was changed to "Elvis" (Renamed). If the directory "Elvis" is already exists, it can't change it to "Elvis" (cause he can't make a duplicate names), therefore I get an exception saying that.
What am I doing wrong??
Many thanks!!!
I would advise putting validation around the Move command to ensure that the source location does exists and the destination location doesn't exists.
I've always found it easier to avoid the exceptions than handle them once they do occur.
You'll probably want to include exception handling as well, just in case the access permissions are a problem or a file is open and can't be moved...
Here's some sample code for you:
string sourceDir = #"c:\test";
string destinationDir = #"c:\test1";
try
{
// Ensure the source directory exists
if (Directory.Exists(sourceDir) == true )
{
// Ensure the destination directory doesn't already exist
if (Directory.Exists(destinationDir) == false)
{
// Perform the move
Directory.Move(sourceDir, destinationDir);
}
else
{
// Could provide the user the option to delete the existing directory
// before moving the source directory
}
}
else
{
// Do something about the source directory not existing
}
}
catch (Exception)
{
// TODO: Handle the exception that has been thrown
}
Even though this works in the command line to move a file, when programming you need to provide the full new name.
So you'd need to change newLocation to "C:\Songs\Elvis\Elvis my Man" to make this work.
From MSDN,
This method throws an IOException if, for example, you try to move c:\mydir to c:\public, and c:\public already exists. You must specify "c:\public\mydir" as the destDirName parameter, or specify a new directory name such as "c:\newdir".
It looks like you need to set newLocation to C:\Songs\Elvis\Elvis my man
private void moveDirectory(string fuente,string destino)
{
if (!System.IO.Directory.Exists(destino))
{
System.IO.Directory.CreateDirectory(destino);
}
String[] files = Directory.GetFiles(fuente);
String[] directories = Directory.GetDirectories(fuente);
foreach (string s in files)
{
System.IO.File.Copy(s, Path.Combine(destino,Path.GetFileName(s)), true);
}
foreach(string d in directories)
{
moveDirectory(Path.Combine(fuente, Path.GetFileName(d)), Path.Combine(destino, Path.GetFileName(d)));
}
}