I want to compress a folder using NTFS compression in .NET. I found this post, but it does not work. It throws an exception ("Invalid Parameter").
DirectoryInfo directoryInfo = new DirectoryInfo( destinationDir );
if( ( directoryInfo.Attributes & FileAttributes.Compressed ) != FileAttributes.Compressed )
{
string objPath = "Win32_Directory.Name=" + "\"" + destinationDir + "\"";
using( ManagementObject dir = new ManagementObject( objPath ) )
{
ManagementBaseObject outParams = dir.InvokeMethod( "Compress", null, null );
uint ret = (uint)( outParams.Properties["ReturnValue"].Value );
}
}
Anybody knows how to enable NTFS compression on a folder?
Using P/Invoke is, in my experience, usually easier than WMI. I believe the following should work:
private const int FSCTL_SET_COMPRESSION = 0x9C040;
private const short COMPRESSION_FORMAT_DEFAULT = 1;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int DeviceIoControl(
SafeFileHandle hDevice,
int dwIoControlCode,
ref short lpInBuffer,
int nInBufferSize,
IntPtr lpOutBuffer,
int nOutBufferSize,
ref int lpBytesReturned,
IntPtr lpOverlapped);
public static bool EnableCompression(SafeFileHandle handle)
{
int lpBytesReturned = 0;
short lpInBuffer = COMPRESSION_FORMAT_DEFAULT;
return DeviceIoControl(handle, FSCTL_SET_COMPRESSION,
ref lpInBuffer, sizeof(short), IntPtr.Zero, 0,
ref lpBytesReturned, IntPtr.Zero) != 0;
}
Since you're trying to set this on a directory, you will probably need to use P/Invoke to call CreateFile using FILE_FLAG_BACKUP_SEMANTICS to get the SafeFileHandle on the directory.
Also, note that setting compression on a directory in NTFS does not compress all the contents, it only makes new files show up as compressed (the same is true for encryption). If you want to compress the entire directory, you'll need to walk the entire directory and call DeviceIoControl on each file/folder.
I have tested the code and it
(source: typepad.com)
!
Make sure it works for you with the gui. Maybe the allocation unit size is too big for compression. Or you don't have sufficient permissions.
For your destination use format like so: "c:/temp/testcomp" with forward slashes.
Full code:
using System.IO;
using System.Management;
class Program
{
static void Main(string[] args)
{
string destinationDir = "c:/temp/testcomp";
DirectoryInfo directoryInfo = new DirectoryInfo(destinationDir);
if ((directoryInfo.Attributes & FileAttributes.Compressed) != FileAttributes.Compressed)
{
string objPath = "Win32_Directory.Name=" + "'" + directoryInfo.FullName.Replace("\\", #"\\").TrimEnd('\\') + "'";
using (ManagementObject dir = new ManagementObject(objPath))
{
ManagementBaseObject outParams = dir.InvokeMethod("Compress", null, null);
uint ret = (uint)(outParams.Properties["ReturnValue"].Value);
}
}
}
}
There is a much simpler way, which I am using in Windows 8 64-bit, rewritten for VB.NET. Enjoy.
Dim Path as string = "c:\test"
Dim strComputer As String = "."
Dim objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Dim colFolders = objWMIService.ExecQuery("Select * from Win32_Directory where name = '" & Replace(path, "\", "\\") & "'")
For Each objFolder In colFolders
objFolder.Compress()
Next
works great for me. Chagne .\root to \pcname\root if you need to do it on another computer. Use with care.
When creating the Win32_Directory.Name=... string you need to double the backslashes, so for example the path C:\Foo\Bar would be built up as:
Win32_Directory.Name="C:\\Foo\\Bar",
or using your example code:
string objPath = "Win32_Directory.Name=\"C:\\\\Foo\\\\Bar\"";
Apparently the string is fed to some process that expects an escaped form of the path string.
This is a slight adaption of Igal Serban answer. I ran into a subtle issue with the Name having to be in a very specific format. So I added some Replace("\\", #"\\").TrimEnd('\\') magic to normalize the path first, I also cleaned up the code a bit.
var dir = new DirectoryInfo(_outputFolder);
if (!dir.Exists)
{
dir.Create();
}
if ((dir.Attributes & FileAttributes.Compressed) == 0)
{
try
{
// Enable compression for the output folder
// (this will save a ton of disk space)
string objPath = "Win32_Directory.Name=" + "'" + dir.FullName.Replace("\\", #"\\").TrimEnd('\\') + "'";
using (ManagementObject obj = new ManagementObject(objPath))
{
using (obj.InvokeMethod("Compress", null, null))
{
// I don't really care about the return value,
// if we enabled it great but it can also be done manually
// if really needed
}
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine("Cannot enable compression for folder '" + dir.FullName + "': " + ex.Message, "WMI");
}
}
I don't believe there is a way to set folder compression in the .NET framework as the docs (remarks section) claim it cannot be done through File.SetAttributes. This seems to be only available in the Win32 API using the DeviceIoControl function. One can still do this through .NET by using PInvoke.
Once familiar with PInvoke in general, check out the reference at pinvoke.net that discusses what the signature needs to look like in order to make this happen.
Related
I know similar questions have been asked before but all the answers have been partial, for example suggesting I use AssocQueryString which I am doing. However I'm still failing to find some exe. For example the code below fails to find outlook.exe or firefox.exe - Typing outlook.exe into Windows Explorer address bar finds these almost instantley.
In the code below the exe fileName can be any local location on the users machine, it may or may not be on the users search path.
How can I improve this to find the files? (this is called from a 32 bit exe)
// for example, get actual full path to outlook.exe
string fullPath = FindPath("outlook.exe");
public static string FindPath(string fileName)
{
uint length = UnsafeMethods.MAX_PATH;
StringBuilder path = new StringBuilder((int)length);
if (Path.GetDirectoryName(fileName) == string.Empty)
{
if (UnsafeMethods.AssocQueryString(UnsafeMethods.AssocF.OpenByExeName, UnsafeMethods.AssocStr.Executable, fileName, null, path, ref length) != 0)
{
IntPtr filePart = IntPtr.Zero;
IntPtr wow64Value = IntPtr.Zero;
// try 64 bit path
UnsafeMethods.Wow64DisableWow64FsRedirection(ref wow64Value);
bool success = UnsafeMethods.SearchPath(null, fileName, null, path.Capacity, path, ref filePart) > 0;
UnsafeMethods.Wow64RevertWow64FsRedirection(wow64Value);
if (!success)
{
// try 32 bit path
success = UnsafeMethods.SearchPath(null, fileName, null, path.Capacity, path, ref filePart) > 0;
}
}
return path.ToString();
}
else
{
return fileName;
}
}
It seems there are many places to look to find the path to an exe. While the original code above works, it is not an exhaustive search and you also need to look in the registry key SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\ and also check the SpecialFolders Windows, System and SystemX86 (https://learn.microsoft.com/en-us/dotnet/api/system.environment.specialfolder?view=netframework-4.7.2)
How can I figure out if a file is in a folder that has been SUBST'ed or is located in a user folder using C#?
I think you need to P/Invoke QueryDosDevice() for the drive letter. Subst drives will return a symbolic link, similar to \??\C:\blah. The \??\ prefix indicates it is substituted, the rest gives you the drive+directory.
This is the code I use to get the information if a path is substed:
(Some parts come from pinvoke)
using System.Runtime.InteropServices;
[DllImport("kernel32.dll", SetLastError=true)]
static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);
public static bool IsSubstedPath(string path, out string realPath)
{
StringBuilder pathInformation = new StringBuilder(250);
string driveLetter = null;
uint winApiResult = 0;
realPath = null;
try
{
// Get the drive letter of the path
driveLetter = Path.GetPathRoot(path).Replace("\\", "");
}
catch (ArgumentException)
{
return false;
//<------------------
}
winApiResult = QueryDosDevice(driveLetter, pathInformation, 250);
if(winApiResult == 0)
{
int lastWinError = Marshal.GetLastWin32Error(); // here is the reason why it fails - not used at the moment!
return false;
//<-----------------
}
// If drive is substed, the result will be in the format of "\??\C:\RealPath\".
if (pathInformation.ToString().StartsWith("\\??\\"))
{
// Strip the \??\ prefix.
string realRoot = pathInformation.ToString().Remove(0, 4);
// add backshlash if not present
realRoot += pathInformation.ToString().EndsWith(#"\") ? "" : #"\";
//Combine the paths.
realPath = Path.Combine(realRoot, path.Replace(Path.GetPathRoot(path), ""));
return true;
//<--------------
}
realPath = path;
return false;
}
I think you have a few choices --
Via System.Management classes:
http://briancaos.wordpress.com/2009/03/05/get-local-path-from-unc-path/
Or
Via P/Invoking this MAPI function:
ScUNCFromLocalPath
http://msdn.microsoft.com/en-us/library/cc842520.aspx
If SUBST is run without parameters it produces a listing of all current substitutions. Get the list, and check your directory against the list.
There is also the issue of mapping a volume to a directory. I have never attempted to detect these, but the mount point directories do show up differently than regular directories, so they must have a different attribute of some kind, and that could be detected.
Is there a way to tell using C# if a file is real or a symbolic link?
I've dug through the MSDN W32 docs, and can't find anything for checking this. I'm using CreateSymbolicLink from here, and it's working fine.
private bool IsSymbolic(string path)
{
FileInfo pathInfo = new FileInfo(path);
return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint);
}
I have some source code for symlinks posted on my blog that will allow you to:
create symlinks
check whether a path is a symlink
retrieve the target of a symlink
It also contains NUnit test cases, that you may wish to extend.
The meaty bit is:
private static SafeFileHandle getFileHandle(string path)
{
return CreateFile(path, genericReadAccess, shareModeAll, IntPtr.Zero, openExisting,
fileFlagsForOpenReparsePointAndBackupSemantics, IntPtr.Zero);
}
public static string GetTarget(string path)
{
SymbolicLinkReparseData reparseDataBuffer;
using (SafeFileHandle fileHandle = getFileHandle(path))
{
if (fileHandle.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
int outBufferSize = Marshal.SizeOf(typeof(SymbolicLinkReparseData));
IntPtr outBuffer = IntPtr.Zero;
try
{
outBuffer = Marshal.AllocHGlobal(outBufferSize);
int bytesReturned;
bool success = DeviceIoControl(
fileHandle.DangerousGetHandle(), ioctlCommandGetReparsePoint, IntPtr.Zero, 0,
outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero);
fileHandle.Close();
if (!success)
{
if (((uint)Marshal.GetHRForLastWin32Error()) == pathNotAReparsePointError)
{
return null;
}
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
reparseDataBuffer = (SymbolicLinkReparseData)Marshal.PtrToStructure(
outBuffer, typeof(SymbolicLinkReparseData));
}
finally
{
Marshal.FreeHGlobal(outBuffer);
}
}
if (reparseDataBuffer.ReparseTag != symLinkTag)
{
return null;
}
string target = Encoding.Unicode.GetString(reparseDataBuffer.PathBuffer,
reparseDataBuffer.PrintNameOffset, reparseDataBuffer.PrintNameLength);
return target;
}
That is:
Open the file with CreateFile()
Call DeviceIoControl() to get the reparse point data (NOTE: it could be a junction point!)
Check out the returned data structure to inspect. The reparse tag will tell you if it is a junction point or symbolic link. This may be all you want to do.
Here is an example of differentiating files and directories from links to files and links to directories.
Links to either files or directories maintain their own attributes (creation date, permissions) separate from their targets.
File links can be deleted (e.g. using "del") without affecting the target file.
Directory links can be removed (e.g. "rmdir") without affecting the target directory. Take care when using "rd /s". This WILL remove the directory link target.
The key FileAttributes flag to check in both FileInfo and DirectoryInfo is FileAttributes.ReparsePoint.
static void Main( string[] args ) {
FileInfo file_info = new FileInfo(args[0]);
DirectoryInfo directory_info = new DirectoryInfo(args[0]);
bool is_file = file_info.Exists;
bool is_directory = directory_info.Exists;
if (is_file) {
Console.WriteLine(file_info.ToString() + " is a file");
if ( file_info.Attributes.HasFlag(FileAttributes.ReparsePoint) )
Console.WriteLine(args[0] + " is a Windows file link");
}
else if (is_directory) {
Console.WriteLine(directory_info.ToString() + " is a directory");
if ( directory_info.Attributes.HasFlag(FileAttributes.ReparsePoint) )
Console.WriteLine(args[0] + " is a Windows directory link");
}
It proves the above answers are not reliable.
Finally I got the right solution from MSDN:
To determine if a specified directory is a mounted folder, first call the GetFileAttributes function and inspect the FILE_ATTRIBUTE_REPARSE_POINT flag in the return value to see if the directory has an associated reparse point. If it does, use the FindFirstFile and FindNextFile functions to obtain the reparse tag in the dwReserved0 member of the WIN32_FIND_DATA structure. To determine if the reparse point is a mounted folder (and not some other form of reparse point), test whether the tag value equals the value IO_REPARSE_TAG_MOUNT_POINT. For more information, see Reparse Points.
Starting with .NET 6 you can use:
FileSystemInfo.LinkTarget Property
Property description:
Gets the target path of the link located in FullName, or null if this FileSystemInfo instance doesn't represent a link.
For example:
static bool IsSymbolicLink(string path)
{
FileInfo file = new FileInfo(path);
return file.LinkTarget != null;
}
GetFileInformationByHandle fills a BY_HANDLE_FILE_INFORMATION structure which has a field dwFileAttributes where bits are set with info about the file's attributes (details here). In particular, look at the bit at mask...:
FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400
A file or directory that has an
associated reparse point, or a file
that is a symbolic link.
According to this answer to Stack Overflow question Find out whether a file is a symbolic link in PowerShell, getting the System.IO.FileAttributes for the file (via File.GetAttributes), and testing for the ReparsePoint bit, works. If the bit is set, it is a symlink or a junction point. If not, it is a regular file (or hardlink).
The library MonoPosix provides API to check if a file is a symbolic link:
public bool IsSymlink(string filePath)
=> UnixFileSystemInfo.GetFileSystemEntry(filePath).IsSymbolicLink;
I know I am late to the party but found this discussion when researching same question
I found the below worked for me so thought I would post in case of use to anyone else
It works like this:-
var provider = ReparsePointFactory.Provider;
var link = provider.GetLink(#"c:\program files (x86)\common files\microsoft shared\vgx\vgx.dll");
MsgBox("Link Type: " + link.Type.ToString + " Link Target: " + link.Target + " Link Attributes: " + link.Attributes.ToString);
https://github.com/NCodeGroup/NCode.ReparsePoints https://www.nuget.org/packages/NCode.ReparsePoints/
How can I get the url from a running instance of firefox using .NET 2.0 windows/console app? C# or VB codes will do.
Thanks!
Building on Rob Kennedy's answer and using NDde
using NDde.Client;
class Test
{
public static string GetFirefoxURL()
{
DdeClient dde = new DdeClient("Firefox", "WWW_GetWindowInfo");
dde.Connect();
string url = dde.Request("URL", int.MaxValue);
dde.Disconnect();
return url;
}
}
NB: This is very slow. It takes a few seconds on my computer. The result will look something like this :
"http://stackoverflow.com/questions/430614/get-firefox-url","Get Firefox URL? - Stack Overflow",""
More info on browser DDE here.
For most browsers, including Internet Explorer, Navigator, Firefox, and Opera, the supported and sanctioned way of doing this is to use DDE. The topic name in all of them is WWW_GetWindowInfo; only the name of the target window varies. That technique will be difficult for you, though, because .Net doesn't support DDE. If you can find a way to get around that limitation, you'll be all set.
it seems that this might be difficult, here's some discussion on it: http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/c60b1699-9fd7-408d-a395-110c1cd4f297/
You may want to check into the source code of WatiN. Their next version is open source and supports firefox, so I would imagine the functionality for doing this is in it.
Use MozRepl: https://github.com/bard/mozrepl/wiki/ + mozRepl .NET Connector: http://mozreplconnector.codeplex.com/releases/view/17398
var connect = new MozReplConnectDotNet.MozReplConnect(4242);
connect.Connect();
Console.WriteLine(connect.SendRecieve("gBrowser.currentURI.spec"));
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr parentHandle,
IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd,
int msg, int wParam, StringBuilder ClassName);
private static string GetURL(IntPtr intPtr, string programName, out string url)
{
string temp=null;
if (programName.Equals("chrome"))
{
var hAddressBox = FindWindowEx(intPtr, IntPtr.Zero, "Chrome_OmniboxView", IntPtr.Zero);
var sb = new StringBuilder(256);
SendMessage(hAddressBox, 0x000D, (IntPtr)256, sb);
temp = sb.ToString();
}
if (programName.Equals("iexplore"))
{
foreach (InternetExplorer ie in new ShellWindows())
{
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(ie.FullName);
if (fileNameWithoutExtension != null)
{
var filename = fileNameWithoutExtension.ToLower();
if (filename.Equals("iexplore"))
{
temp+=ie.LocationURL + " ";
}
}
}
}
if (programName.Equals("firefox"))
{
DdeClient dde = new DdeClient("Firefox", "WWW_GetWindowInfo");
dde.Connect();
string url1 = dde.Request("URL", int.MaxValue);
dde.Disconnect();
temp = url1.Replace("\"","").Replace("\0","");
}
url = temp;
return temp;
}
Please do following to run this code
Add Reference > Com > Microsoft.Internet.Controls from VS.NET in your project
Download the bin from http://ndde.codeplex.com/ for DdeClient class and add it to your project
Please Let me know if any issue
Poor man's solution, if anything else fails: activate the Firefox window, send Ctrl+L (activates address bar), send Ctrl+C (copy selection, ie. URL, to clipboard) and read the clipboard.
Lot of issues with this method (among them it does strange stuff for the user if they are in front of the computer) so it is only a backup solution...
try this one:
//get all running process of firefox
Process[] procsfirefox = Process.GetProcessesByName("firefox");
foreach (Process firefox in procsfirefox)
{
//the firefox process must have a window
if (firefox.MainWindowHandle == IntPtr.Zero)
{
continue;
}
AutomationElement sourceElement = AutomationElement.FromHandle(firefox.MainWindowHandle);
AutomationElement editBox = sourceElement.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Search with Google or enter address"));
// if it can be found, get the value from the editbox
if (editBox != null)
{
ValuePattern val = ((ValuePattern)editBox.GetCurrentPattern(ValuePattern.Pattern));
Console.WriteLine("\n Firefox URL found: " + val.Current.Value);
}
//-----------------------------find titlebar element for site title---------------------------------//
AutomationElement elmTitleBar = sourceElement.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TitleBar));
if (elmTitleBar != null)
Console.WriteLine("\n Firefox TitleBar found: " + elmTitleBar.Current.Name);
}
full source code:https://github.com/Moeedahmad899/GetFirefoxURL
I'm developing an application targeting .NET Framework 2.0 using C# for which I need to be able to find the default application that is used for opening a particular file type.
I know that, for example, if you just want to open a file using that application you can use something like:
System.Diagnostics.Process.Start( "C:\...\...\myfile.html" );
to open an HTML document in the default browser, or
System.Diagnostics.Process.Start( "C:\...\...\myfile.txt" );
to open a text file in the default text editor.
However, what I want to be able to do is to open files that don't necessarily have a .txt extension (for example), in the default text editor, so I need to be able to find out the default application for opening .txt files, which will allow me to invoke it directly.
I'm guessing there's some Win32 API that I'll need to P/Invoke in order to do this, however a quick look with both Google and MSDN didn't reveal anything of much interest; I did find a very large number of completely irrelevant pages, but nothing like I'm looking for.
All current answers are unreliable. The registry is an implementation detail and indeed such code is broken on my Windows 8.1 machine. The proper way to do this is using the Win32 API, specifically AssocQueryString:
using System.Runtime.InteropServices;
[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern uint AssocQueryString(
AssocF flags,
AssocStr str,
string pszAssoc,
string pszExtra,
[Out] StringBuilder pszOut,
ref uint pcchOut
);
[Flags]
public enum AssocF
{
None = 0,
Init_NoRemapCLSID = 0x1,
Init_ByExeName = 0x2,
Open_ByExeName = 0x2,
Init_DefaultToStar = 0x4,
Init_DefaultToFolder = 0x8,
NoUserSettings = 0x10,
NoTruncate = 0x20,
Verify = 0x40,
RemapRunDll = 0x80,
NoFixUps = 0x100,
IgnoreBaseClass = 0x200,
Init_IgnoreUnknown = 0x400,
Init_Fixed_ProgId = 0x800,
Is_Protocol = 0x1000,
Init_For_File = 0x2000
}
public enum AssocStr
{
Command = 1,
Executable,
FriendlyDocName,
FriendlyAppName,
NoOpen,
ShellNewValue,
DDECommand,
DDEIfExec,
DDEApplication,
DDETopic,
InfoTip,
QuickTip,
TileInfo,
ContentType,
DefaultIcon,
ShellExtension,
DropTarget,
DelegateExecute,
Supported_Uri_Protocols,
ProgID,
AppID,
AppPublisher,
AppIconReference,
Max
}
Relevant documentation:
AssocQueryString
ASSOCF
ASSOCSTR
Sample usage:
static string AssocQueryString(AssocStr association, string extension)
{
const int S_OK = 0;
const int S_FALSE = 1;
uint length = 0;
uint ret = AssocQueryString(AssocF.None, association, extension, null, null, ref length);
if (ret != S_FALSE)
{
throw new InvalidOperationException("Could not determine associated string");
}
var sb = new StringBuilder((int)length); // (length-1) will probably work too as the marshaller adds null termination
ret = AssocQueryString(AssocF.None, association, extension, null, sb, ref length);
if (ret != S_OK)
{
throw new InvalidOperationException("Could not determine associated string");
}
return sb.ToString();
}
You can check under registry section HKEY_CLASSES_ROOT for the extension and action details. Documentation for this is on MSDN. Alternatively, you can use the IQueryAssociations interface.
Doh! Of course.
HKEY_CLASSES_ROOT\.txt
includes a reference to
HKEY_CLASSES_ROOT\txtfile
which contains a subkey
HKEY_CLASSES_ROOT\txtfile\shell\open\command
which references Notepad.
Sorted, many thanks!
Bart
Here is a blog post with about this topic. The code samples are in VB.net, but it should be easy to port them to C#.
You can just query the registry. First get the Default entry under HKEY_CLASSES_ROOT\.ext
That will give you the classname. For example .txt has a default of txtfile
Then open up HKEY_CLASSES_ROOT\txtfile\Shell\Open\Command
That will give you the default command used.
A late answer, but there is a good NUGET package that handles file associations: File Association
Link NUGET File Association
Usage is simple, for instance to add all allowed file extensions to a context menu:
private void OnMenuSourceFileOpening(object sender, ...)
{ // open a context menu with the associated files + ".txt" files
if (File.Exists(this.SelectedFileName))
{
string fileExt = Path.GetExtension(this.SelectedFileNames);
string[] allowedExtensions = new string[] { fileExt, ".txt" };
var fileAssociations = allowedExtensions
.Select(ext => new FileAssociationInfo(ext));
var progInfos = fileAssociations
.Select(fileAssoc => new ProgramAssociationInfo (fileAssoc.ProgID));
var toolstripItems = myProgInfos
.Select(proginfo => new ToolStripLabel (proginfo.Description) { Tag = proginfo });
// add also the prog info as Tag, for easy access
// when the toolstrip item is selected
// of course this can also be done in one long linq statement
// fill the context menu:
this.contextMenu1.Items.Clear();
this.contextMenuOpenSourceFile.Items.AddRange (toolstripItems.ToArray());
}
}