|

Introduction
It should be a simple matter to programatically create a shortcut on the
desktop that links to a particular file. Unfortunately, as far as I know, the
.NET Framework does not support this directly. However, by using the Windows
Scripting Host Object Model, it takes only a few lines of code to create a
shortcut anywhere within the file system. The purpose of this article is to show
how to do this and to provide a class with methods that make it even simpler.
The demonstration program uses this class to test for the existence of shortcuts
and create or delete them with the click of a checkbox.
Shell Links
A standard feature of the Windows operating system is the ability to create a
file that provides a link to any other file within the Windows file system.
These so-called "Shortcuts" or "Shell Links" are used in many ways.
Examples include the shortcuts that appear as icons on the Windows Desktop, the
Start menu, the Quick Launch area within the Task Bar, and the "Send To" menu
that appears when right-clicking a file in Explorer. These shortcuts are easy to
create manually in the Windows GUI, but within a .NET program they typically
require the programmer to use Interop.
Windows Scripting Host
The Windows Scripting Host (WSH) enables a number of file system and network
operations to be performed from a script file. Fortunately, it is very simple to
directly program the WSH in a .NET program by including a reference to the WSH
runtime library (IWshRuntimeLibrary). To do this within the Visual Studio .NET
IDE, do the following: after creating a new project, right-click on the project
name within the Solution Explorer, select "Add Reference", select the "COM" tab,
find and select the "Windows Script Host Object Model" in the listbox, click
"Select", and then click "OK". Next, include a reference to the library, for
example, within a C# file use the following:
using IWshRuntimeLibrary;
Once this groundwork is done, it is nearly trivial to create a Shell
Link.
Creating a Shell Link
The following code is all that is necessary to create a Shell Link using the
Windows Scripting Host.
WshShell shell = new WshShell();
IWshShortcut link = (IWshShortcut)shell.CreateShortcut(LinkPathName);
link.TargetPath=TargetPathName;
link.Save();
The IWshShortcut object has a number of properties that allow
the programmer to set things like the target path, the icon, the file name, the
arguments, etc. You can explore these within Visual Studio using the Object
Browser or Intellisense.
The Link Class
The demonstration program includes a class named Link that
encapsulates static methods to test for the presence of a shortcut and to create
or delete one if necessary. For example, to test for the presence of a desktop
shortcut named "Shell Link", use the following code:
DesktopFolder=Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
if(Link.Exists(DesktopFolder, "Shell Link"))DoSomething();
To create or delete a desktop shortcut named "Shell Link" that points to a
file whose path is given by TargetPathName, use the following code:
DesktopFolder=Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
Link.Update(DesktopFolder, TargetPathName, "Shell Link", Create);
This will create a link if Create is true and
delete it if Create is false. If no change is needed,
the code will do nothing.
Conclusion
That's all there is to it! It is simple to incorporate WSH in a .NET program.
Creating Shell Links is one good reason to do so. You may find other uses for
WSH in your programs such as mapping network drives, setting up printer
connections, determining the free space on a disk, or any other tasks that can
be automated with the Windows Scripting Host.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 27 (Total in Forum: 27) (Refresh) | FirstPrevNext |
|
|
 |
|
|
I can't work out how I use the link creator to build an new directory in the start menu and add a link?
For example "Start menu | Program files | My application abc | link to program"
The utility looks great, thanks 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
First you have to create the subdirectory and then put the link in it. For example:
string ProgramsFolder = Environment.GetFolderPath(Environment.SpecialFolder.Programs); DirectoryInfo di = new DirectoryInfo(ProgramsFolder); DirectoryInfo subDi = di.CreateSubdirectory("My Application ABC"); Link.Update(subDi.FullName, ExecutablePath, "link to program", true);
You'll probably want to add some code to handle errors, for example if you are unable to create the subdirectory.
Regards,
Jim
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
There is a way, to create a shortcut that prompt for credentials. On existent shortcuts, this can be done setting the 'run with alternative credentials' flag in advanced properties. Can I set this flag on by code?
Michele
ps sorry for my poor english...
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
im building a windows application, i have a frame inside my window i want 2run another application inside this frame (several old program i have done previously)my application is like a toolkit.So i want to run those applications(*.exe) inside this frame. The problem is When the application is on the computer (dont need 2specify the path) it work, but when i specify the path it run separately:
//this following code launch myprogram that exist on the machine(c:\) private void button1_Click(object sender, EventArgs e) { ProcessStartInfo pinfo = new ProcessStartInfo ("myprogram"); Process p = System.Diagnostics.Process.Start(pinfo); p.WaitForInputIdle(); SetParent(p.MainWindowHandle, this.Lable1.Handle);
} //So what if i want to specify the path of for example (e:\myprogram) as my main application(parent) guna launch from a cd and all exuctable application guna be on a cd.
private void button2_Click(object sender, EventArgs e) { Process proc = new Process(); proc.StartInfo.FileName = @"e:\myprogram.exe"; proc.Start(); proc.WaitForInputIdle(); SetParent(proc.MainWindowHandle, this.label1.Handle); }
what happened in the second chunck of code is that myprogram run in a new window not inside the label1.
i want it to run inside the label.
THZXsavcsv swv ad a as
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I tried running this code on Sharepoint, because I was unable to strong name IWshRuntimeLibrary.dll for my vb.net code. So, I tried to create a class in C# where you can strong name the dll, and call this class from my vb.net code.
However, I get "Specified cast is not valid" on:
WshShortcut link = (WshShortcut)shell.CreateShortcut(myfile + ".url");
Any clues? Larry
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
The example works great when adding or removing for a known user. Is there a way to add/delete an icon setup for all users?
VS2005 creates repair type icons that I don't want - the first time the app runs, I want to replace the VS20065 WinInstaller icons with regular icons that don't attempt to do a repair.
Thanks for any help.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have created Shortcut Now i want target path of file. How to Read lnk files through WSH using C#.net
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi.
I have tried this code to create shortcuts: WshShell shell = new WshShell(); IWshShortcut link = (IWshShortcut)shell.CreateShortcut(LinkPathName);
Everything is fine. But, if the LinkPathName is really big ( imagine that you can have many nested folders), the method is not working. It is throwing an exception that doesn't say anything useful.
Any sugestions?
Thanks.
Best regards. Mircea
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Thank you for your reply.
Using ShellLink I can create the shortcut in the same folder where the Wsh failed.
So, I think this method has some limitations.
Thank you again.
Regards. Mircea
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I noticed that using ShellLink I am creating "normal" shortcuts, not internet shortcuts.
Does anybody know how I can use ShellLink to create Internet Shortcuts?
Thanks. Mircea
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
This method works for me for my C# application in English. Now I tried to run this program on a L10N platform, say, Japanese with the shortcut name in Japanese character. It does not create the shortcut. link.Save() generates exception.
Any suggestion?
Thanks -Tapas
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
 | MC++ |  | Anonymous | 16:03 26 Aug '05 |
|
|
I had to make some changes to get this to work with MC++. The using statement is this instead:
using namespace Interop::IWshRuntimeLibrary;
That conflicts with System::IO, so I ended up using it explicitly. Here is the rest of the stuff I changed.
IWshShell* shell = new WshShellClass(); IWshShortcut* link = static_cast(shell->CreateShortcut(LinkPathName)); link->TargetPath = TargetPathName; link->Save();
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
How are you referring to Windows Script Host type library in your code? Are you doing #import "wshom.ocx"
Could you post your code?
Thanks, Diganta
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I did this in my MS VC++ .Net program, come out with the error:
c:\Code\VC.Net\itlStart\Form1.h(318) : error C2059: syntax error : '('
error in the statement: IWshShortcut* link = static_cast(shell->CreateShortcut(DesFile));
need your help. Thanks.
IWshShell* shell = new WshShellClass(); IWshShortcut* link = static_cast(shell->CreateShortcut(DesFile)); link->TargetPath = Environment::GetFolderPath(Environment::SpecialFolder::Desktop); link->Save();
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello,
The WSH solution is cool!!! The problem is when I try use in Win98. The exception said me that can´t use the SAVE() method. I don´t understant why, if somebody can help me, please.... I need it.
Thanks!!
Thiago
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Is there a way to find if the desktop icon is selected(highlighted by single mouse click). I have to scan desktop and save target path of all currently selected items to arraylist. Thank you.
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
I'm working on a small program that is a standalone executable -- no installation, can be run from any directory, no extra files to worry about -- it's just a .exe.
I added your Link class to my program because I need to let people to choose if they want it to run when Windows starts. However, I quickly saw that a file was created called "Interop.IWshRuntimeLibrary.dll" I need to create a Startup folder link without needing that DLL. Can this be done?
Thanks.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
Jordan, I don't know if this will help or not but I recently came accross an example of how an assembly may be loaded from an embedded resource instead of from disk, I've never tried it nor did I write it.
/*========================================================================
File: Embed.cs
Summary: This file shows an example of how an assembly may be loaded from
an embedded resource instead of from disk.
Instructions for use:
1. Include the Embed.cs file in the project or assembly in which you wish to
'embed' an assembly.
2. As early in the startup code as possible ( preferably in Main() ), make
a call to Dennany.Embed.Init(). This will register Embed.LoadComponentAssembly()
as the callback method for the AssemblyResolve event.
3. Add the 'dynamic' assembly to your project as an Embedded Resource.
This may be done from the menu:
Project -> Add Existing Item (Browse to appropriate .dll file here)
Make certain that you set the properties of the .dll to "Embedded Resource"!
(This may be done from the Solution Explorer by right-clicking on the .dll file,
selecting properties, and setting the "Build Action" to "Embedded Resource.")
Special Note: Because of the way the CLR loads assemblies, you may not reference
a type in one of these embedded assemblies before the call to Embed.Init().
You may also not reference a type in one of these embedded assemblies in the same method
that the call to Embed.Init() is made.
Copyright (c) 2003, Jerry Dennany
========================================================================*/
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.IO;
using System.Diagnostics;
namespace Dennany {
public sealed class Embed {
// this class is static, and should not be instantiated.
private Embed() {}
// Init is the only public callable method of this class. It should be called once
// (and only once!)
// to register the LoadComponentAssembly method as the event handler to call should the
// AssemblyResolve event get fired.
public static void Init(){
ResolveEventHandler loadAssembly = new ResolveEventHandler(LoadComponentAssembly);
AppDomain.CurrentDomain.AssemblyResolve += loadAssembly;
}
// This method is called when an assembly fails to load via probing path, GAC, etc.
// Note that we return null to the CLR if we have no assembly to load. This is
// expected behavior, so that the CLR may notify the rest of the application that
// it could not load the assembly in question.
static Assembly LoadComponentAssembly(Object sender, ResolveEventArgs args) {
// We'll use this reference fairly often in the future...
Assembly assembly = Assembly.GetExecutingAssembly();
// Get the requested assembly's simple name (no namespace info or file extension)
string simpleName = args.Name.Substring(0, args.Name.IndexOf(',') );
string dllImageResourceName = getResourceLibName( simpleName, assembly );
return streamFromResource(dllImageResourceName, assembly);
}
private static string getResourceLibName(string simpleLibName){
return getResourceLibName( simpleLibName, Assembly.GetExecutingAssembly() );
}
// We will go through the list of resources in the assembly and using the
// simpleLibName, we will find if the dll resource is embedded in the assembly
// Note that we return null on purpose if we didn't find anything.
// This is because we also want to return null to the CLR if we have no assembly to load.
private static string getResourceLibName(string simpleLibName, Assembly assembly) {
if ( simpleLibName == null || assembly == null ) return null;
simpleLibName += ".dll"; // assume that the file ends in this extension.
string dllImageResourceName = null;
// We will iterate through the list of resources in this assembly,
// looking for the name of the assembly that failed to load from disk
foreach (string resourceName in assembly.GetManifestResourceNames()) {
if (resourceName.Length < simpleLibName.Length) continue;
// if the simpleName and resourceName end the same (we drop namespace info here),
// then this should be the embedded assembly that we are looking for.
if (String.Compare(simpleLibName,
0,
resourceName,
(resourceName.Length - simpleLibName.Length),
simpleLibName.Length,
true) == 0 ) {
dllImageResourceName = resourceName;
}
}
return dllImageResourceName;
}
private static Assembly streamFromResource(string dllImageResourceName){
return streamFromResource(dllImageResourceName, Assembly.GetExecutingAssembly() );
}
// this is the 'workhorse' of the class. Once we've got a resource name in the assembly,
// we stream the resource to a byte array, and load the Assembly from the byte array.
private static Assembly streamFromResource(string dllImageResourceName, Assembly assembly){
if ( dllImageResourceName == null || assembly == null ) return null;
Stream imageStream;
imageStream = assembly.GetManifestResourceStream(dllImageResourceName);
long bytestreamMaxLength = imageStream.Length;
byte[] buffer = new byte[bytestreamMaxLength];
imageStream.Read(buffer,0,(int)bytestreamMaxLength);
return AssemblyBuilder.Load(buffer);
}
}
} // EOF
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Yes, it appears Mattias Sjoegren has done an excellent job of encapsulating the complex marshalling required to manipulate shell links with COM interfaces and CoClasses. He provides .NET classes that hide this complexity from the programmer.
My point was to show how easy it is to accomplish this in managed code using an object that is already available on most systems, the Windows Scripting Host.
|
| Sign In·View Thread·PermaLink | 3.67/5 (2 votes) |
|
|
|
 |
|
|
 |
|
|
I looked at Mattias Sjoegren code, and frankly it's a hell lot more complicated that this example.
Plus, if the interface of the object changes, Mattias's code if going to need major changes, whereas this one would just need minor changes if any at all.
This is a good tutorial
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|