I've been wanting to create a simple text-manipulating extension for Visual Studio for a while, and now I've finally found some time to look into how extensions are written. What I have in mind could be accomplished through VBA macros, but I'd rather implement it as a "real" extension; as a learning process, and because I honestly can't stand VBA.
After a fair amount of googling, blog reading, digging into MSDN and browsing StackOverflow posts, I think I've gathered enough information that I can implement it - but I'd like some feedback on whether I'm approaching things right before I start hacking away :)
What I'd like is:
Registering Commands that users can bind hotkeys to via Tools->Options->Keyboard.
Modify the text buffer of the active window when Commands are invoked.
I don't really care about menus or toolbars, but know how to add it via .vsct files (are there better options?)
For #1, it seems I have to do a full VSPackage, .vsct file et cetera - there's no nice-and-easy MEF extension point I can handle instead? (Perhaps exporting a IWpfTextViewCreationListener and fiddling around with manual keyboard shortcut handling - but that'd be a major hack).
For #2, I'm unsure how to get an ITextBuffer for the active document. I could go through DTE.ActiveDocument, but I'm not sure how to obtain an ITextBuffer from that. Alternatively, I could do something along the lines of...
var txtMgr = (IVsTextManager)ServiceProvider.GetService(typeof(SVsTextManager));
IVsTextView textViewCurrent;
txtMgr.GetActiveView(true, null, out textView);
IWpfTextView wpfViewCurrent = AdaptersFactory.GetWpfTextView(textView);
ITextBuffer textCurrent = wpfViewCurrent.TextBuffer;
...but that sure does look like a roundabout way of doing things?
For both of these, take a look at the Align Assignments extension source. It's a package/MEF component that adds a command and handles it in the active window.
Your answer to #1 is correct. The best way to do commands is with a .vsct file, which requires a package. However, all a package means is that your project will be producing a dll with embedded resources (from the .vsct file) and a .pkgdef file, which adds registry keys according to the attributes you supply on your package. It (hopefully) isn't too much overhead.
For your second question, there is a cleaner way. Take a look at the command filter, which listens for commands in the active view, instead of listening for them globally and then finding the active view. It lets the shell handle the command routing and just concentrates on the implementation.
Not entirely sure what you mean by "the text buffer" but assuming you mean either the current text file that is open or the current selection, here is some code I have in a package to access those:
EnvDTE.DTE app = (EnvDTE.DTE)GetService(typeof(SDTE));
if (app.ActiveDocument != null && app.ActiveDocument.Type == "Text")
{
EnvDTE.TextDocument text = (EnvDTE.TextDocument)app.ActiveDocument.Object(String.Empty);
if (!text.Selection.IsEmpty)
{
//work with text.Selection.Text
}
}
Of course if you're doing an editor extension it would be different.
Related
I am trying to put a filter on my C# openFileDialog that excludes certain file extensions. For example I want it to show all files in a directory that are not .txt files.
Is there a way to do this?
I don't think this is possible. The way the filter is set up, is that you can choose which files to show, but I don't think there's a way to show "All files except...". Come to think of it, have you ever seen an Open File Dialog in Windows that has this? I don't think I've ever seen one.
Your best bet is to let them choose all files, and then prompt the user if they select one that isn't allowed OR filter it down to all the possible files that you can deal with.
There is no direct way to do this using the BCL OpenFileDialog.
I can think of a couple of options:
1) Make a filter that just has all of the types you do want to support. This would be my recommendation, since that's the most common way of going about this type of operation.
2) Use something along the lines of this custom OpenFileDialog implementation. You could then override the OnFileNameChanged() method to potentially disable the "Open" button if the selected file has a .txt extension.
3) Let the user pick a .txt file, throw up an error dialog, and reopen the file dialog. This feels clunky and not too great to me, though....
Found with Google search "OpenFileDialog"
EDIT: Sorry about not expanding on the EXCLUDE aspects. You may not need to go to this extreme, but it would meet your needs....
Do a recursive directory search of all the files that the user may choose from. (Hopefully that's a small set of folders.)
Uniquely identify the extensions on those files. (System.IO.Path.GetExtension() and Linq's .Distint() method may work well here)
Remove the ".txt" entry from the list.
Construct a filter string by looping through these extensions.
I'm afraid this isn't possible. You'll either have to
a) Include a long list of all the extensions that should be allowed, or
b) Allow all extensions, and then use a simple check in code that reopens the dialog if the selected file has extension .txt.
Also, could you provide a bit more context for this question? I'm having trouble envisaging a scenario where I might explicitly need to exclude a certain extension. You can't probably get away with just a filter (and maybe a bit of checking in code) in almost all situations.
Here's a completely different approach, which you're unlikely to use.
Instead of using OpenFileDialog, analyze the specific features you need and create your own dialog box. You could easily provide whatever filtering you want, but then the difficulty moves over to the implementing and maintaining the new UI.
I don't suggest that you do this, but sometimes users are rather insistent upon what they need.
Another alternate: Instead of using a dialog, come up with something completely different that fits well within the app. This may not be possible, but then we don't know much about the app.
You cannot set a filter to exclude extensions from file dialogs.
You could however implement a delegate for the FileOk event on the dialog. This event fires just before the file the user selected will be accepted, and the event arguments provide a Cancel property that you can set to disallow selection.
It is not as elegant as actually making the wrong files invisible, but it will allow you to disallow selection of the wrong kind of file.
PS: Do not forget to give the user feedback why the file was not accepted, otherwise they may wonder why the dialog is not closing when they pick a 'txt' file.
I would like a particular type of file (eg. Namefile.ext2) read all the names preceded by a #
Sample contents of the file:
#nameone
#nametwo
#namethree
When I click the right mouse button on the ext2 file extension beyond the standard options (like: open, properties, etc ...) I would like to be:
contents of the file > nameone
nametwo
namethree
Then, select the item (eg. nameone) pass this parameter to my program running in the background / or services
Do you need to modify the registry somehow? I will be grateful for tips on how to achieve the desired effect.
What you are asking about is called 'shell extension'. Basically it requires some knowledge of COM objects programming, but .NET made things a bit easier in that matter.
Shortly: you have to develop a piece of code which will reads the file and generates menu items dynamically (which may be tricky but possible). That code needs to be registered in the system as COM object.
Before it starts working you have to associate file extension with COM object you created.
Perhaps this article can explaint it a bit more:
http://www.codeproject.com/Articles/512956/NET-Shell-Extensions-Shell-Context-Menus
I'm currently working with a Chinese SMB server, on which almost all the company files are stored.
As the structure doesn't change, I'd like to be able to put a "label" on files, based on a rules (something that allow me to handle generated files, which includes dates for example).
I need only support for win7 and above, and I'd like my informations to be read from a text file rather than relying on some metadata or client's data.
So I thought of writting a shell extension to do the work. My problem is, that by looking at the documentation, I didn't find something that allow me to change the name. The best solution I've found so far is to go with the infotip handler, but I wondering if anyone has a better way to do this.
In short, it needs:
1) To be compatible with win7 (and above),
2) To be visible at first sight
3) To use a readonly fs
After extensive research, I've found that the best way to do it is to write a Shell Namespace extension.
I'll be able to provide a virtual directory representing my server's structure, and translate the names the way I want.
This seems a little overkill though, but there's no other way to change the informations displayed as the display name is managed by an IShellFolder which provides it to an IShellView
One excellent source of informations I've found about it, and the most up to date so far, is an article on Michael Edenfiled's blog
Is there a way to modify the behavior of the OpenFileDialog so that it looks inside the files in the folder it opens to and then ignores certain ones based on their content?
One example would be to open to a folder full of Zip files but only show the ones that contain a certain file.
From the documentation, there's the HookProc but I'm not exactly sure how I'd use it.
Please note that if it is possible, I realize that it'll be a relatively slow operation. At the moment I'm not concerned about performance.
Thanks!
I wouldn't dismiss the complexity of the OpenFileDialog. It's not so easy to build one that really works. When you do build your own, it's not the "normal" dialog and as a result it confuses users. This is true even if you do it well, which is difficult. So I'd suggest you stick to extending what is already there, rather than writing something new.
Check this article for an extension of OFD that might/could be tweaked to do exactly what you want. There's a callback that you write in C# that responds to path selection.
Related: FolderBrowserDialogEx is a similar extension on FolderBrowserDialog. Despite the name, you can configure it to search for files, as well as folders. There's a callback that gets invoked when something (a folder, a file) is selected, and within that callback you can do what you need to do. For example, peek inside the files within a folder and populate the list of files to display with only those files.
Another option you might consider is the dialog library from Ookii. This is an open source implementation of the OpenFileDialog, and it includes COM wrappers for all the new dialog stuff in Vista. Using that library you can pop a Vista OpenFileDialog and receive events from the IFileDialogEvents interface, in C# code. One such event is OnFolderChange(). Within the handler you could call IFolder.GetFolder() which will get you an IShellItem, which gives you the folder the user is changing to. The next step would be to itemize and potentially filter the set of files, which is an exercise I will leave to the reader...
No, you would have to implement your own functionality for that. But to be honest, the OpenFileDialog really doesn't do a whole lot anyway. To be honest, yeah, you probably could hook into it, but you'd be doing a lot of work for nothing when the real work is to inspect the content of the files and then you can write your own simple OpenFileDialog class on top of that.
You might find this question helpful regarding listing contents of zip files:
How to list the contents of a .zip folder in c#?
(Note, you could potentially thread it to improve performance, just don't span many threads)
You can probably use the Windows API Code Pack (comes with the source). The Common File dialogs feature exposes a lot more functionality of file dialogs than the versions in Winforms/WPF.
http://code.msdn.microsoft.com/WindowsAPICodePack
Alright, so I'm working on programming my own installer in C#, and what I'd like to do is something along the lines of put the files in the .exe, so I can do
File.Copy(file, filedir);
Or, if this isn't possible, is there another way of doing what I am attempting to do?
I wouldn't code my own installer, but if you truely want to embed files into your assembly you could use strongly typed resources. In the properties dialog of your project open up the "Resources" tab and then add your file. You'll then be able to get the file using:
ProjectNamespace.Properties.Resources.MyFile
Then you'll be able to write the embedded resource to disk using:
System.IO.File.WriteAllBytes(#"C:\MyFile.bin", ProjectNamespace.Properties.Resources.MyFile);
Honestly, I would suggest you NOT create your own installer. There are many many issues with creating installers. Even the big installer makers don't make their own actual installers anymore, they just create custom MSI packages.
Use Mirosoft Installer (MSI). It's the right thing to do. Make your own custom front-end for it, but don't recreate the already very complex wheel that exists.
UPDATE: If you're just doing this for learning, then I would shy away from thinking of it as "an installer". You might be tempted to take your "research" and use it someday, and frankly, that's how we end up with so many problems when new versions of Windows come out. People create their own wheels with assumptions that aren't valid.
What you're really trying to do is called "packaging", and you really have to become intimately familiar with the Executable PE format, because you're talking about changing the structure of the PE image on disk.
You can simulate it, to a point, with putting files in resources, but that's not really what installers, or self-extractors do.
Here's a link to Self-Extractor tutorial, but it's not in C#.
I don't know enough about the .NET PE requirements to know if you can do this in with a managed code executable or not.
UPDATE2: This is probably more of what you're looking for, it embeds files in the resource, but as I said, it's not really the way professional installers or self-extractors do it. I think there are various limitations on what you can embed as resources. But here's the like to a Self-Extractor Demo written in C#.
I'm guessing here, but if you are trying to store resources in your application before compilation, you can in the Project Explorer, right click a file you would like to add, chose properties and change the type to Embedded Resource.
You can then access the embedded resources later by using the instructions from this KB:
http://support.microsoft.com/kb/319292
in case you simply want to store multiple files in a single file storage (and extract files from there, interact etc.) you might also want to check out NFileStorage, a .net file storage. written in 100% .NET C# with all sources included. It also comes with a command line interpreter that allows interaction from the command line.