|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
Introduction
There are many features that every commercial application has, but aren't easy to implement, or find out how to implement, for many people. Look at Undo/Redo, the Office 2007 Ribbon Bar, spell check, associated file types, and lot's of other small, but powerful features.
While many of these aren't actually hard to program, it can be difficult to find out exactly how. More specifically, this article is on how to link a file extension (or two, three, four, or five...) to your program and have your application display the appropriate content according to the file.
Background
Take a second to open up Windows Explorer. See all the different types of files (jpg, gif, png, txt, html, etc)? Each one has a different icon and opens with a certain application when you double click on it. Take a guess, how many lines of code does it take to link your application and an extension? 10? 20? 30?
The answer is 2. Just 2 will do it!
How are programs associated?
The registry stores all the file type-app associations. Click on the Start Menu > Run > Type in 'regedit' > Ok. Now expand the HKEY_CLASSES_ROOT node. At the top of the window are all the extensions that your computer recognizes. Scroll down to .txt and click on it. Now look at the default value, it probably is 'txtfile'. Scrolling down the tree on the left, find the txtfile node. This contains all the information about any extensions that have their default value set to txtfile. Right now, we're just interested in opening the file, so open Shell > Open > Command. If your .txt files open with notepad, then the default value should be "%SystemRoot%\system32\NOTEPAD.EXE %1".
%SystemRoot% is pretty self-explanatory, it's replaced by the folder that contains system32, which contains NOTEPAD.EXE.
%1 is a command-line argument to pass the the program when a txtfile is opened. %1 is replaced by the file's location.
Step 1: Running your Program when a .Hello File is Opened
The first step is to get your application to open when a chosen extension (like .mp3) is double clicked in Windows Explorer. For this article, we'll use a file extension that shouldn't exist: .Hello. To use this file type, create a new project called 'Hello World'. The basic idea is this: a .Hello file contains (in plain text) an adjective. When one is opened, a message box will pop-up and say, "Hello, (file contents) World". If you open the application manually, it will just say, "Hello, World".
Now we have to edit the registry just like you saw with the .txt extension. In the forms Load event, type the following:
My.Computer.Registry.ClassesRoot.CreateSubKey(".Hello").SetValue("", "Hello", Microsoft.Win32.RegistryValueKind.String)
My.Computer.Registry.ClassesRoot.CreateSubKey("Hello\shell\open\command").SetValue("", Application.ExecutablePath & _
" ""%l"" ", Microsoft.Win32.RegistryValueKind.String)
What does all this do? If you don't understand My.Computer.Registry, here's a link to it on MSDN, otherwise look below:
|
Code
|
What it does
|
CreateSubKey(".Hello") |
Creates a registry key in ClassesRoot for the .Hello extension. Notice that you must include the beginning period.
|
.SetValue("", "Hello"... |
-
"" (Or Nothing) sets the default value of the key.
-
"Hello" is like the "txtfile" we saw earlier, it tells which registry key contains the information about the .Hello extension.
|
CreateSubKey("Hello" & _ "\shell\open\command") |
This creates the "Hello" sub-key and the "store\open\command" subkey that is needed to store the path to the application that will open this file type.
|
.SetValue("", Application.ExecutablePath & _ " ""%l"" ",... |
- Again, "" tells the application to set the key's default value.
Application.ExecutablePath tells the code to associate the currently running executable with this file type.
" ""%1"" " passes the opened file's location to your program. The quotes around it are optional, but if you have more than one argument, you must put them around each.
|
Now run your application once. It will edit the registry. Your program is now associated with the .Hello file!
You want to create file association for .txt in your program. You create the file association, but it still opens in Notepad.
What's going on? There is another value that needs to be deleted located here:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt
The value name is 'Progid'. This will consist of a string value of the default program to open this filetype. If this value is present,
you will not be able to associate anything with this particular filetype. You must delete the 'Progid' value in order for the association to work.
Now to test it out. Open Notepad, type in an adjective, and save it as a .Hello file (Make sure you don't accidentally save it as a .Hello.txt file). Open the file in Windows Explorer. Your program will run! But nothing happens...
Step 2: Reading the File Contents
Now I've told you how to associate the files and the article should be over, right? Nope! This wouldn't be any use if you didn't know how to read the command-line arguments and finish the program! Luckily, this is simple. My.Application.CommandlineArgs returns a ReadonlyCollection(Of String).
When the registry is set correctly and a file is opened in Windows Explorer, the file's path is pass as a command-line argument (if you think of an application as a method - a subroutine or function - then these are the parameters). To retrieve the arguments, you use My.Application.CommandlineArgs. It returns a ReadOnlyCollection(Of String). You can use My.Application.CommandlineArgs(0) to retrieve the file path, or use the code below to convert the collection to an array.
To convert this to an array (which you don't really need to do unless you're not familiar with working with collecions), add the following to the Application's Load Event:
Dim strAllArgs(My.Application.CommandLineArgs.Count - 1) As String
Dim x as integer = 0
For Each arg as string In My.Application.CommandLineArgs
Try
strAllArgs(x) = arg
Catch ex As Exception
strAllArgs(x) = "Could not write argument."
Debug.Writeline(ex.message)
End Try
x += 1
Next
If My.Application.CommandLineArgs.Count = 0 Then
ReDim strAllArgs(0) As String
strAllArgs(0) = Nothing
End If
The strAllArgs is the new array.
Now, we have to display the message. More code for the Load event:
msgbox("Hello, " & My.Computer.FileSystem.ReadAllText(strAllArgs(0)) & " World!")
Using RegistryActions.FileAssociation
(The easier way)
Okay, now you've done it the hard way, time to learn the easy way. Using the included RegistryActions DLL, you can associate a file type with a variable and a method. Then, you can read the arguments with just one more method!
Imports RegistryActions.FileAssociation
Public Class HelloForm
Private ftHello As New FileType(".Hello", "Hello", "Hello World Adjective File", "C:\World.ico")
Private Sub HelloForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DoAssociation.Associate(ftHello, Application.ExecutablePath)
msgbox("Hello, " & My.Computer.FileSystem.ReadAllText(DoAssociation.WriteCommandsToArray(My.Application.CommandLineArgs)(0)) & " World!")
End Sub
End Class
See the documentation for more on the RegistryActions Namespace.
Beyond...
Explore the HKEY_CLASSES_ROOT hive. Look for additional features you can add, for example when you right click on a file. Find out how to change the default icon for a file type... And Keep on Programming!
History
| Date |
Change |
| 4/29/07 |
Article Submitted |
| 4/30/07 |
- Fixed up article so it fits on one page.
- Updated demo project.
|
| 5/8/07 |
- Explained
My.Application.CommandLineArgs.
|
| 6/3/07 |
Added this tip. |
| 6/8/07 |
Fixed problems in the DLL. |
| 6/26/07 |
Changed the wordings in some phrases and fixed some errors in the examples. |
| 6/29/07 |
- Fixed links.
- No more sidescrolling!
|
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 33 (Total in Forum: 33) (Refresh) | FirstPrevNext |
|
|
 |
|
|
 |
|
|
Hi, I've tried your dll, with the following code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim fType As New FileType(".fitytest", "filetypetest", "Test of filetypes", "C:\Documents and Settings\Jesper\Skrivebord\free_icons\amc\Standard V.ico") DoAssociation.Associate(fType, Application.ExecutablePath, """%1""") End Sub
I've looked in my registry, and it seem to work, but when i open my .fifytest file, windows don't know which program to use. The program aren't shown either. What have i done wrong? - galaicra
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi - I run my project and your example that uses your dll library and it throws inner exception I think that the bug is in the constructor of RegistryActions.FileAssociation.DoAssociation.Associate - you check there whether FileType.Description != NULL ???? Can you fix this please ?? And I'll be glad I you can attached your origin code if you dont mind..
Thanks. Adi
Adi Keidar
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi - I run my project and your example that uses your dll library and it throws inner exception I think that the bug is in the constructor of RegistryActions.FileAssociation.DoAssociation.Associate - you check there whether FileType.Description != NULL instead of == ???? Can you fix this please ?? And I'll be glad I you can attached your origin code if you dont mind..
Thanks. Adi
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I get this error when I run my program: Value cannot be null. Parameter name: path .
It's in this line: MsgBox("Hello, " & My.Computer.FileSystem.ReadAllText(DoAssociation.WriteCommandsToArray(My.Application.CommandLineArgs)(0)) & " World!").
What does that mean?
This is my signature.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It looks like no command-line args were specified. Which would probably be because you didn't run it by opening a file.
Will it work if you double click a file that ends in whichever extension you associated instead of running it via visual stuido? (So if you decided to use the .Hello extension, then open a .Hello file in Windows Explorer)
Edit: Somehow you are getting your argument passed to the application, but it's empty. Check this part:
.SetValue("", Application.ExecutablePath & _ " ""%l"" ",... Make sure you have the %1 (as in one, not the letter L).
Try both of these suggestions and tell me what happens.
-- modified at 13:05 Sunday 11th November, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
how can i associat more then 1 file at once?
if i select more then 1 file and i click on open i want all paths form all files!
i want the same effect when i select some mp3-files (and click on play) and the mediaplayer opens all files in ONE mediaplayer (like a playlist)?
thx
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
You could try a single instance application (see "Open With while the program is already running" for a link)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
no, if i select more then one file (for example two) and i click right on it (to open both) there are always coming 2 windows: MOVE FILES TO...
if i click on cancle my programm starts.
but why that 2 windows?
thx.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Is this code: My.Computer.Registry.ClassesRoot.CreateSubKey(".Hello").SetValue("", "Hello", Microsoft.Win32.RegistryValueKind.String) My.Computer.Registry.ClassesRoot.CreateSubKey("Hello\shell\open\command").SetValue("", Application.ExecutablePath & _ " ""%l"" ", Microsoft.Win32.RegistryValueKind.String)
supposed to set it so that now when you view .hello files in windows explorer, the icon of the .hello file will look like your executable's icon? Because I tried this and the icon changes but to an odd looking generic icon. So, how can I set the icon myself?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Try this:
My.Computer.Registry.ClassesRoot.CreateSubKey("Hello\DefaultIcon").SetValue("", "C:\YOURICONHERE.ico", _ Microsoft.Win32.RegistryValueKind.String)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I've implemented your code for opening a document and setting the default icon in a project, and it works fine with Windows XP. However, I tried it on a Vista machine and ran into a problem with not having permission to write to the registry. I've been having trouble finding any articles about this issue and was wondering if you have encountered this and, if so, how you overcame it. Any help would be appreciated.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
-Are you having problems with all registry writes/file associations, or just setting a default icon?
-Do you get any error messages? If so, what?
-Try running the program as an administrator.
-Try the suggestion in this post[^].
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I write to the registry to set the file association and then I set the default icon. The error is thrown on the file association registry write. The error message I get is: (my file extention is .fac)
System.UnauthorizedAccessException: Access to the registry key 'HKEY_CLASSES_ROOT\fac\shell\open\command' is denied. at Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str) at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity) at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey) at FileAccess.Main.SetFileAssociation() in C:\Project Source\FileAccess2\Forms\Main.vb:line 1833 at FileAccess.Main.Main_Load(Object sender, EventArgs e) in C:\Project Source\FileAccess2\Forms\Main.vb:line 20 at System.EventHandler.Invoke(Object sender, EventArgs e) at System.Windows.Forms.Form.OnLoad(EventArgs e) at System.Windows.Forms.Form.OnCreateControl() at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) at System.Windows.Forms.Control.CreateControl() at System.Windows.Forms.Control.WmShowWindow(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ScrollableControl.WndProc(Message& m) at System.Windows.Forms.ContainerControl.WndProc(Message& m) at System.Windows.Forms.Form.WmShowWindow(Message& m) at System.Windows.Forms.Form.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
And I am already running the program as an administrator.
I looked into the suggestion you posted, but if I'm understanding it correctly it doesn't look quite right. The registry at that location doesn't have a default icon area, andit seems to just refer back to the registry settings that your article discusses. If you have any other suggestions or ideas, I would really appreciate the advice.
Thank you for your time.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This code worked fine for me under XP:
Sub Main()
My.Computer.Registry.ClassesRoot.CreateSubKey(".fac").SetValue("", "TestFacExt", Microsoft.Win32.RegistryValueKind.String) My.Computer.Registry.ClassesRoot.CreateSubKey("TestFacExt\shell\open\command").SetValue("", "C:\XXX" & _ " ""%1"" ", Microsoft.Win32.RegistryValueKind.String) Console.ReadLine() End Sub If yours is a lot different, then could you post it?
Edit: If you are using the OpenSubKey() method, then you may be using the wrong overload.
Make sure you set writeable to true: OpenSubKey(name, True)
-- modified at 7:35 Friday 31st August, 2007
-- modified at 13:00 Sunday 11th November, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
That is basically what my code looks like. I don't use an OpenSubKey method though. I just always use the CreateSubKey. Could that be my problem? Here is my code in case there is some difference I am not seeing. (I put my ext in a global variable in case I wanted to change it.)
My.Computer.Registry.ClassesRoot.CreateSubKey("." & gblstrFileExt).SetValue("", gblstrFileExt,Microsoft.Win32.RegistryValueKind.String) My.Computer.Registry.ClassesRoot.CreateSubKey(gblstrFileExt & "\shell\open\command").SetValue("", Application.ExecutablePath & _ " ""%l"" ", Microsoft.Win32.RegistryValueKind.String)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I used the following code and it worked fine:
Private Const gblstrFileExt As String = "randomExt" Sub Main() My.Computer.Registry.ClassesRoot.CreateSubKey("." & gblstrFileExt).SetValue("", gblstrFileExt, Microsoft.Win32.RegistryValueKind.String) My.Computer.Registry.ClassesRoot.CreateSubKey(gblstrFileExt & "\shell\open\command").SetValue("", "xxx" & _ " ""%l"" ", Microsoft.Win32.RegistryValueKind.String) End Sub
It works fine under XP and Vista (without the UAC) for me. Try running the program with the UAC turned off.
Make sure your program has all necessary permissions.
-- modified at 12:58 Sunday 11th November, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks for the interesting read first of all.
Is there anyway to read in a file associated with the vb.net program if one only wants one instance of the program running and it has already opened?
For example,
I text file with a ".HELLO" extension is right clicked / open withed or is associated with the VB.NET program already and the program itself is running, anyway to retrieve the info in the text file as like a backgroundworker rather than on load?
thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
If I remember correctly can't you just put the following in a batch file and call it?
assoc .hello=Hello.App.File ftype Hello.App.File=C:\Program Files\MyCompany\Hello.exe %1
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
A couple months ago I spent some time trying to process command line arguments. I had no idea about most of the My tools available at that time.
I implemented (or tried to) the command line code using My.Application.CommandLineArgs in my class library application. Of course, not being the initial application, it doesn't have My.Application.CommandLineArgs. Instead, I have to call to my new class in that Library and pass an argument of type System.Collections.ObjectModel.ReadOnlyCollection(Of String).
Hope this helps someone else in the same spot I was in.
Props to the author!
--Taf
P.E.B.C.A.K. (Problem Exists Between Chair And Keyboard)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I get this error when i try to use this method. even using the pre-compiled demo app:
"One or more of the FileTy[e's properties are invalid."
************** Exception Text ************** System.Exception: One or more of the FileType's properties are invalid. See innerexception for deatails. ---> System.Exception: Type.Name: WebTAN Type.Extension: .html Type.Description: HTML Web File Type.IconC:\WT_A_html.ico --- End of inner exception stack trace --- at RegistryActions.FileAssociation.DoAssociation.Associate(FileType Type, String ExeFile, String ExtraCommands) at WebTAN.Preferences.Button1_Click(Object sender, EventArgs e) in C:\Documents and Settings\Tanaalethan\My Documents\Visual Studio 2005\Projects\WebTAN 2\WebTAN 2\Preferences.vb:line 147 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
General News Question Answer 
|