Windows API CodePack. Get all selected items in the CommonOpenFileDialog:IFileOpenDialog - c#

I work with the CommonOpenFileDialog class from the Windows® API Code Pack for Microsoft® .NET Framework that implements the IFileOpenDialog interface.
More info about Windows API CodePack here:
http://archive.msdn.microsoft.com/WindowsAPICodePack
Problem:
The below method returns the First selected folder if (multiple folders) or (mutltiple folders and files) were selected in the "Open File Dialog" dialog window.
IFileOpenDialog.GetSelectedItems([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppsai)
How to return All selected elements (folders and files) in the IFileOpenDialog window as a list of IShellItem, no matter what I selected there?

You need to specify the Multiselect property.
Here's an unmarshalled example:
CommonOpenFileDialog folderDialog = new CommonOpenFileDialog("Input Folder Selection");
folderDialog.IsFolderPicker = true;
folderDialog.Multiselect = true;
if (folderDialog.ShowDialog() == CommonFileDialogResult.Ok)
{
foreach (string folderName in folderDialog.FileNames) //it's a little confusing, but FileNames represents folders as well in the API
{
// do something
}
}

Related

How to rewrite pplEditor in Sharepoint to something that can be used in ASP.NET

I would like to write a tool which can search through users in the active directory. At the moment, I am working on a pre-existing code that uses Sharepoint 2007. I would like to convert that from Sharepoint 2007 to ASP.NET. Within this pre-existing code is a reference to pplEditor of sharepoint, which I am assuming is being used to look through the active directory. I want to rewrite this code so I am not referencing pplEditor at all. Rather I would like an 'alternative' that can access the users in the active directory. Code is in C#.
List(string)_lstExistingLogin = null;
Label lblLoginID;
if (pplEditor.ResolvedEntities.Count > 0)
{
if (gvAssignedTos.Rows.Count > 0){
// if the hospital already has existing data coordinators associated with it,
// build a list of this set of existing datacoordinators
_lstExistingLogin = new List<string>();
foreach (GridViewRow row in gvAssignedTos.Rows)
{
lblLoginID = (Label)row.FindControl("lblLoginID");
if (lblLoginID.Text.Length > 0)
{
_lstExistingLogin.Add(lblLoginID.Text);
}
}
}
ALL Operations on Active Directory (AD) using c# by using System.DirectoryServices.
Not sure whether you're inheriting from pplEditor, while it can be used in SharePoint.
People picker control implementation in asp.net mvc application

How to check which file type has PrintTo command available in Windows?

In Windows Explorer, when you right click, there is a 'Print' function for some of the file type. I know it's using the vert PrintTo to print the file.
I want to know how can I identify does a specific file type has this PrintTo verb association? Any available library in C#?
The context menu from the windows explorer is build with the information from the registry => HKEY_CLASSES_ROOT. Here you will find all registered extensions. For example .txt, under .txt you will find his (Default) => txtfile.
My Windows is german so whats called (Default) is here (Standard).
And when you look for the txtfile entry in the registry there will be txtfile=>shell=>print/printto. And if you don't find the shell=>print/printto entry, there also will be no print option in the context menu. There even is the print command which windwos will use to print your file. You can to this for every file type.
And to read from the registry there will be many example on the web like this: https://www.codeproject.com/Articles/3389/Read-write-and-delete-from-registry-with-C
This is how I implement it in C# based on Momo's answer.
public static bool HasPrintToVerb(string filename)
{
try
{
var ext = Path.GetExtension(filename);
var value = Registry.GetValue("HKEY_CLASSES_ROOT\\" + ext, string.Empty, null);
var printToValue = Registry.GetValue(string.Format(#"HKEY_CLASSES_ROOT\{0}\shell\Printto\command", value), string.Empty, null);
return printToValue != null;
}
catch(Exception ex)
{
return false;
}
}

Create a folder without read-only using c# [duplicate]

I was successfully able to remove read only attribute on a file using the following code snippet:
In main.cs
FileSystemInfo[] sqlParentFileSystemInfo = dirInfo.GetFileSystemInfos();
foreach (var childFolderOrFile in sqlParentFileSystemInfo)
{
RemoveReadOnlyFlag(childFolderOrFile);
}
private static void RemoveReadOnlyFlag(FileSystemInfo fileSystemInfo)
{
fileSystemInfo.Attributes = FileAttributes.Normal;
var di = fileSystemInfo as DirectoryInfo;
if (di != null)
{
foreach (var dirInfo in di.GetFileSystemInfos())
RemoveReadOnlyFlag(dirInfo);
}
}
Unfortunately, this doesn't work on the folders. After running the code, when I go to the folder, right click and do properties, here's what I see:
The read only flag is still checked although it removed it from files underneath it. This causes a process to fail deleting this folder. When I manually remove the flag and rerun the process (a bat file), it's able to delete the file (so I know this is not an issue with the bat file)
How do I remove this flag in C#?
You could also do something like the following to recursively clear readonly (and archive, etc.) for all directories and files within a specified parent directory:
private void ClearReadOnly(DirectoryInfo parentDirectory)
{
if(parentDirectory != null)
{
parentDirectory.Attributes = FileAttributes.Normal;
foreach (FileInfo fi in parentDirectory.GetFiles())
{
fi.Attributes = FileAttributes.Normal;
}
foreach (DirectoryInfo di in parentDirectory.GetDirectories())
{
ClearReadOnly(di);
}
}
}
You can therefore call this like so:
public void Main()
{
DirectoryInfo parentDirectoryInfo = new DirectoryInfo(#"c:\test");
ClearReadOnly(parentDirectoryInfo);
}
Try DirectoryInfo instead of FileInfo
DirectoryInfo di = new DirectoryInfo(#"c:\temp\content");
di.Attributes = FileAttributes.Normal;
To clean up attrbutes on files-
foreach (string fileName in System.IO.Directory.GetFiles(#"c:\temp\content"))
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
fileInfo.Attributes = FileAttributes.Normal;
}
The dialog just works in a fairly bizarre way. It always shows up the way you see it in your screen shot, whatever the state of the ReadOnly attribute. The checkbox is in the 'indetermined' state. You have to click it and either clear or check it to make it perform its action. And in spite of the prompt text (but not the hint next to the checkbox), it only changes the ReadOnly attribute on the files in the directory, not the directory itself.
Use the attrib command line command to see what is really going on. In all likelihood, your code fails because the directory contains files that have their ReadOnly attribute set. You'll have to iterate them.
The read-only flag on directories in Windows is actually a misnomer. The folder does not use the read-only flag. The issue is going to be with the customization. The flag is used by Windows to identify that there are customizations on the folder.
This is an old post, with an issue that is sunsetting, but, figured people might still run into it, as it is pretty annoying when you hit it.
Microsoft's Explanation
IEnumerable / Lambda solution for recursively removing readonly attribute from directories and files:
new DirectoryInfo(#"some\test\path").GetDirectories("*", SearchOption.AllDirectories).ToList().ForEach(
di => {
di.Attributes &= ~FileAttributes.ReadOnly;
di.GetFiles("*", SearchOption.TopDirectoryOnly).ToList().ForEach(fi => fi.IsReadOnly = false);
}
);
Set the Attributes property on the original dirInfo:
dirInfo.Attributes = FileAttributes.Normal;
FileSystemInfo[] sqlParentFileSystemInfo = dirInfo.GetFileSystemInfos();
foreach (var childFolderOrFile in sqlParentFileSystemInfo)
{
RemoveReadOnlyFlag(childFolderOrFile);
}
Just in case any one happens across this later...
ALL of the other answers posted before mine are either wrong or use unnecessary recursion.
First of all the "Read Only" check box in the property dialog of windows always has the tri-state marker for folders. This is because the folder itself is not read only but the files inside can be.
If you want to set/unset read only flag for ALL files. you can do it simply as follows:
void SetReadOnlyFlagForAllFiles(DirectoryInfo directory, bool isReadOnly)
{
// Iterate over ALL files using "*" wildcard and choosing to search all directories.
foreach(FileInfo File in directory.GetFiles("*", SearchOption.All.Directories))
{
// Set flag.
File.IsReadOnly = isReadOnly;
}
}
I see that #DotnetDude said in comments that solutions of guys don't work. To my mind it is happens because guys don't mentioned that need to use File.SetAttributes method to apply new attributes.
This may or may not be directly related, but the root issue in your case may be caused by the underlying files. For example, I ran into this issue trying to delete a directory:
System.IO.Directory.Delete(someDirectory, true)
This results in "Access to the path 'blah' is denied". To resolve this underlying problem, I removed the read-only attribute on sub-files and was then able to remove the parent directory. In my case, I was using powershell, so you can use the .NET equivalent.
dir -r $PrePackageDirectory |% {if ($_.PSIsContainer -ne $true){$_.IsReadOnly = $false}}
Shell("net share sharefolder=c:\sharefolder/GRANT:Everyone,FULL")
Shell("net share sharefolder= c:\sharefolder/G:Everyone:F /SPEC B")
Shell("Icacls C:\sharefolder/grant Everyone:F /inheritance:e /T")
Shell("attrib -r +s C:\\sharefolder\*.* /s /d", AppWinStyle.Hide)
this code is working for me.. to share a folder to every one with read and write permission

Monitor file selection in explorer (like clipboard monitoring) in C#

I am trying to create a little helper application, one scenario is "file duplication finder". What I want to do is this:
I start my C# .NET app, it gives me an empty list.
Start the normal windows explorer, select a file in some folder
The C# app tells me stuff about this file (e.g. duplicates)
How can I monitor the currently selected file in the "normal" windows explorer instance. Do I have to start the instance using .NET to have a handle of the process. Do I need a handle, or is there some "global hook" I can monitor inside C#. Its a little bit like monitoring the clipboard, but not exactly the same...
Any help is appreciated (if you don't have code, just point me to the right interops, dlls or help pages :-) Thanks, Chris
EDIT 1 (current source, thanks to Mattias)
using SHDocVw;
using Shell32;
public static void ListExplorerWindows()
{
foreach (InternetExplorer ie in new ShellWindowsClass())
DebugExplorerInstance(ie);
}
public static void DebugExplorerInstance(InternetExplorer instance)
{
Debug.WriteLine("DebugExplorerInstance ".PadRight(30, '='));
Debug.WriteLine("FullName " + instance.FullName);
Debug.WriteLine("AdressBar " + instance.AddressBar);
var doc = instance.Document as IShellFolderViewDual ;
if (doc != null)
{
Debug.WriteLine(doc.Folder.Title);
foreach (FolderItem item in doc.SelectedItems())
{
Debug.WriteLine(item.Path);
}
}
}
You can do this with the shell automation interfaces. The basic process is to
Run Tlbimp on Shdocwv.dll and
Shell32.dll (or directly add a
reference from VS).
Create an
instance of the ShellWindows
collection and iterate. This will
contain both Windows Explorer and
Internet Explorer windows.
For
Windows Explorer windows, the
IWebBrowser2.Document property will
return a IShellFolderViewDual
reference.
The IShellFolderViewDual
has a SelectedItems method you can
query and an event for changes you
can handle.

Get all folders from TFS using TFS SDK

I am creating a TFS tool that will get "changeset information" from the TFS server.
Now, I want to provide a "TFS Browser" so that the user can browse what "branch/folder" he wants to fetch information from.
I am using a TreeView control and the GetItems function to get the items' path from TFS:
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
e.Node.Nodes.RemoveAt(0);
RecursionType recursion = RecursionType.OneLevel;
Item[] items = null;
// Get the latest version of the information for the items.
ItemSet itemSet = sourceControl.GetItems(e.Node.Tag.ToString(), recursion);
items = itemSet.Items;
foreach (Item item in items)
{
if (item.ServerItem == e.Node.Tag.ToString()) //Skip self
continue;
string filename = Path.GetFileName(item.ServerItem);
if (Path.GetExtension(filename) == "")
{
TreeNode node = new TreeNode(filename, new TreeNode[] { new TreeNode() });
node.Tag = item.ServerItem;
e.Node.Nodes.Add(node);
}
}
}
The code below demonstrates that after clicking the "expand" button from a node, the app will "query" the items that are below the current "branch" (e).
However, I don't want to include files to the browser. As a quick and dirty check, I am checking if the "path" has an extension and if not, assume that it is a directory and show it. All was good until I discovered that we have a folder named "v1.1".
There is a solution. I can re-invoke GetItems and check its content. According to MSDN:
If the path argument is a file,
returns a set of Items that contain
just that file. If the path is a
folder, returns a set of Items that
contain all items in that folder. If
the path contains a wildcard
character, returns a set of Items in
the specified folder that match the
wildcard.
However, each call to GetItems take roughly a second and if a folder contains multiple files, the "expansion" of the node takes forever.
So, is there a way to just get all the "folders" from TFS? Or any other idea how to check if a path is a folder or a file?
Thanks!
It seems that there is a member called .ItemType for Item. You can check against that.
One solution that I have just found is to use the GetFileTypes method to retrieve the different extensions registered on the server. Then check every "item" against these extensions like so:
if (!Extensions.Contains(Path.GetExtension(item.ServerItem).Replace(".","").ToLower()))
{
//Add Node
}
However, this is not really fool proof. What if a folder is named FOLDER.DLL?

Categories