i am creating a .net setup project and i want to decide the name of the shortcut when i run the windows installer. is that possible?
if that is possible also let me know how to name the installation folder likewise.

the installation will be in silent mode, so there will be no gui. there must be some way to pass parameters to msiexec and you know...

please help.

Especially you Ramy, i challenge you to do that. you cant do that man! :)

i have some information, maybe you can help me use this information. /f option has s but i dont know how to use it.

Windows Installer
Command-Line Options
The executable program that interprets packages and installs products is Msiexec.exe. Note that Msiexec also sets an error level on return that corresponds to system error codes. Command-line options are case-insensitive.

The command-line options in the following table are available with Windows® Installer version 3.0 and earlier versions. The Standard Installer Command-Line Options are also available beginning with Windows Installer 3.0.

Option Parameters Meaning
/I Package|ProductCode Installs or configures a product.

/f [p|o|e|d|c|a|u|m|s|v] Package|ProductCode Repairs a product. This option ignores any property values entered on the command line. The default argument list for this option is 'omus.' This option shares the same argument list as the REINSTALLMODE property.

p - Reinstalls only if file is missing.

o - Reinstalls if file is missing or an older version is installed.

e - Reinstalls if file is missing or an equal or older version is installed.

d - Reinstalls if file is missing or a different version is installed.

c - Reinstalls if file is missing or the stored checksum does not match the calculated value. Only repairs files that have msidbFileAttributesChecksum in the Attributes column of the File table.

a - Forces all files to be reinstalled.

u - Rewrites all required user-specific registry entries.

m - Rewrites all required computer-specific registry entries.

s - Overwrites all existing shortcuts.

v - Runs from source and re-caches the local package. Do not use the v reinstall option for the first installation of an application or feature.

/a Package Administrative installation option. Installs a product on the network.

/x Package|ProductCode Uninstalls a product.
/j [u|m]Package
or

[u|m]Package/tTransform List

or

[u|m]Package/gLanguageID
Advertises a product. This option ignores any property values entered on the command line.

u - Advertises to the current user.

m - Advertises to all users of machine.

g - Language identifier.

t - Applies transform to advertised package.

/L [i|w|e|a|r|u|c|m|o|p|v|x|+|!|*] Logfile Writes logging information into a logfile at the specified existing path. The path to the logfile location must already exist. The installer does not create the directory structure for the logfile. Flags indicate which information to log. If no flags are specified, the default is 'iwearmo.'

i - Status messages.

w - Nonfatal warnings.

e - All error messages.

a - Start up of actions.

r - Action-specific records.

u - User requests.

c - Initial UI parameters.

m - Out-of-memory or fatal exit information.

o - Out-of-disk-space messages.

p - Terminal properties.

v - Verbose output.

x - Extra debugging information. Only available on Windows Server 2003.

+ - Append to existing file.

! - Flush each line to the log.

"*" - Wildcard, log all information except for the v and x options. To include the v and x options, specify "/l*vx".

Note For more information about all the methods that are available for setting the logging mode, see Normal Logging in the Windows Installer Logging section

/m filename Generates an SMS status .mif file. Must be used with either the install (-i), remove (-x), administrative installation (-a), or reinstall (-f) options. The ISMIF32.DLL is installed as part of SMS and must be on the path.

The fields of the status mif file are filled with the following information:

Manufacturer - Author

Product - Revision Number

Version - Subject

Locale - Template

Serial Number - not set

Installation - set by ISMIF32.DLL to "DateTime"

InstallStatus - "Success" or "Failed"

Description - Error messages in the following order: 1) Error messages generated by installer. 2) Resource from Msi.dll if installation could not commence or user exit. 3) System error message file. 4) Formatted message: "Installer error %i", where %i is error returned from Msi.dll.

/p PatchPackage[;patchPackage2…] Applies a patch. To apply a patch to an installed administrative image you must combine the following options:

/p <PatchPackage>[;patchPackage2…] /a <Package>

/q n|b|r|f Sets user interface level.

q , qn - No UI

qb - Basic UI. Use qb! to hide the Cancel button.

qr - Reduced UI with no modal dialog box displayed at the end of the installation.

qf - Full UI and any authored FatalError, UserExit, or Exit modal dialog boxes at the end.

qn+ - No UI except for a modal dialog box displayed at the end.

qb+ - Basic UI with a modal dialog box displayed at the end. The modal box is not displayed if the user cancels the installation. Use qb+! or qb!+ to hide the Cancel button.

qb- - Basic UI with no modal dialog boxes. Please note that /qb+- is not a supported UI level. Use qb-! or qb!- to hide the Cancel button.

Note that the ! option is available with Windows Installer 2.0 and works only with basic UI. It is not valid with full UI.

/? or /h Displays copyright information for Windows Installer.

/y module Calls the system function DllRegisterServer to self-register modules passed in on the command line. Specify the full path to the DLL. For example, for MY_FILE.DLL in the current folder you can use:

msiexec /y .\MY_FILE.DLL

This option is only used for registry information that cannot be added using the registry tables of the .msi file.

/z module Calls the system function DllUnRegisterServer to unregister modules passed in on the command line. Specify the full path to the DLL. For example, for MY_FILE.DLL in the current folder you can use:

msiexec /z .\MY_FILE.DLL

This option is only used for registry information that cannot be removed using the registry tables of the .msi file.

/c Advertises a new instance of the product. Must be used in conjunction with /t. Available starting with the Windows Installer version that is shipped with Windows Server 2003 and Windows XP SP1.

/n ProductCode Specifies a particular instance of the product. Used to identify an instance installed using the multiple instance support through a product code changing transforms. Available starting with the Windows Installer version shipped with Windows Server 2003 and Windows XP SP1.

The options /i, /x, /f[p|o|e|d|c|a|u|m|s|v], /j[u|m], /a, /p, /y and /z should not be used together. The one exception to this rule is that patching an administrative installation requires using both /p and /a. The options /t, /c and /g should only be used with /j. The options /l and /q can be used with /i, /x, /f[p|o|e|d|c|a|u|m|s|v], /j[u|m], /a, and /p. The option /n can be used with /i, /f, /x and /p.

To install a product from A:\Example.msi, install the product as follows:

msiexec /i A:\Example.msi

Only public properties can be modified using the command line. All property names on the command line are interpreted as uppercase but the value retains case sensitivity. If you enter MyProperty at a command line, the installer overrides the value of MYPROPERTY and not the value of MyProperty in the Property table. For more information, see About Properties.

To install a product with PROPERTY set to VALUE, use the following syntax on the command line. You can put the property anywhere except between an option and its argument.

Correct syntax:

msiexec /i A:\Example.msi PROPERTY=VALUE

Incorrect syntax:

msiexec /i PROPERTY=VALUE A:\Example.msi

Property values that are literal strings must be enclosed in quotation marks. Include any white spaces in the string between the marks.

msiexec /i A:\Example.msi PROPERTY="Embedded White Space"

To clear a public property by using the command line, set its value to an empty string.

msiexec /i A:\Example.msi PROPERTY=""

For sections of text set apart by literal quotation marks, enclose the section with a second pair of quotation marks.

msiexec /i A:\Example.msi PROPERTY="Embedded ""Quotes"" White Space"

The following example shows a complicated command line.

msiexec /i testdb.msi INSTALLLEVEL=3 /l* msi.log COMPANYNAME="Acme ""Widgets"" and ""Gizmos."""

The following example shows advertisement options. Note that switches are not case-sensitive.

msiexec /JM msisample.msi /T transform.mst /LIME logfile.txt

The following example shows you how to install a new instance of a product to be advertised. This product is authored to support multiple instance transforms.

msiexec /JM msisample.msi /T :instance1.mst;customization.mst /c /LIME logfile.txt

The following example shows how to patch an instance of a product that is installed using multiple instance transforms.

msiexec /p msipatch.msp;msipatch2.msp /n {00000001-0002-0000-0000-624474736554} /qb

When you apply patches to a specific product, the /i and /p options cannot be specified together in a command line. In this case, you can apply patches to a product as follows.

msiexec /i A:\Example.msi PATCH=msipatch.msp;msipatch2.msp /qb

The PATCH property cannot be set in a command line, when /p option is used. If the PATCH property is set when the /p option is used, the value of PATCH property is ignored and overwritten.


Send comments about this topic to Microsoft

© 2006 Microsoft Corporation. All rights reserved.

wait a second. this information did not come from Scott's links. i copied and pasted it from windows installer .chm which comes with windows SDK.

Yes but that information is irrelevant for naming shortcuts as far as I had read. You need to take it over in code like in the URLs I posted earlier.

Then give me a favor, i dont have expert-exchange account. can you copy and paste the info on that site?

also my problem is atomic, it is all or nothing situation.
i need also custom folder and start menu names as well as shortcut names. you know why? our clients have different environments and these names must reflect which environment the application is working on. that is very important thing.
if you help me sort this out, i will add to your reputations 10 days long. think about it my reputation altering point is 4 and 4 times 10 makes 40. if you are smart enough you can add to my reputation and once it exceeds 100 it will make my repuation altering point more, which means not 4 times 10 but more times 10. think about it guys, it is all about reputation :D

Scott, this article is f..king great man!!! how did you search google to find it? dont give me the fish, teach me how to fish :)

Do I still get the 10 days of reptutation? :)

I googled for
"C# deployment project create shortcut code"
and found
http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_24013445.html

The sample had the library call to handle to shortcuts: "IWshRuntimeLibrary"

So then I googled:
"C# deployment project create shortcut code +IWshRuntimeLibrary"
and came up with:
http://vbcity.com/forums/topic.asp?tid=86291

Here is the experts exchange code:

string sysnovaPath = @"C:\Program Files\Sysnova\";
string desktop = "";
string allusers = "";
string allusersPrograms = "";
OperatingSystem os = Environment.OSVersion;
if ( os.Version.Major == 6 ) {
    desktop = "C:\\Users\\Public\\Desktop\\";
    allusers = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\";
    allusersPrograms = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\";
} else if ( os.Version.Major == 5 ) {
    desktop = "C:\\Documents and Settings\\All Users\\Desktop\\";
    allusers = "C:\\Documents and Settings\\All Users\\Menu Iniciar\\";
    allusersPrograms = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\";
}
 
desktop += "Sysnova EcoPlan.lnk";
allusersPrograms += "Sysnova Solution\\";
 
try { System.IO.File.Delete( desktop ); } catch ( Exception ) { }
try { System.IO.File.Delete( allusersPrograms + "Sysnova EcoPlan.lnk" ); } catch ( Exception ) { }
try { System.IO.File.Delete( allusers + "Sysnova EcoPlan.lnk" ); } catch ( Exception ) { }
 
IWshRuntimeLibrary.WshShellClass wshShell = new IWshRuntimeLibrary.WshShellClass();
IWshRuntimeLibrary.IWshShortcut myShortcut = (IWshRuntimeLibrary.IWshShortcut)wshShell.CreateShortcut( desktop );
myShortcut.TargetPath = sysnovaPath + "ecoplan\\ecoPlan.exe";
myShortcut.Description = "Gestor de Processos Ambientais";
myShortcut.IconLocation = sysnovaPath + "ecoplan\\ecoplan.ico";
myShortcut.Save();
 
System.IO.Directory.CreateDirectory( allusersPrograms );
System.IO.File.Copy( desktop, allusersPrograms + "Sysnova EcoPlan.lnk" );
System.IO.File.Copy( desktop, allusers + "Sysnova EcoPlan.lnk" );

nice, now i am creating a sample application to put this knowledge in action, when i am done i will attach it to this thread.
about 10 days reputation, as i said, my problem is atomic, if you help me solve it in all aspects, then you deserve it ;)

ok Ramy, i attach the entire project to this post. you will compile the setup project and copy and paste the generated .msi file to your c folder(you can run it at where it is but i just give example command line command assuming it is copied under c drive).


C:\Documents and Settings\serkans>msiexec.exe /i "C:\CustomSetup.msi" SHORTCUTNAME=anynameYoulike

it will create shortcut in your programs menu and desktop.

only thing you need to notice is the custom action and customActionData in setup project. i will submit another one when i incorporate dynamic folder specification.

Comments
I won't check, I trust in you :p

Do I still get the 10 days of reptutation? :)

I googled for
"C# deployment project create shortcut code"
and found
http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_24013445.html

The sample had the library call to handle to shortcuts: "IWshRuntimeLibrary"

So then I googled:
"C# deployment project create shortcut code +IWshRuntimeLibrary"
and came up with:
http://vbcity.com/forums/topic.asp?tid=86291

Here is the experts exchange code:

string sysnovaPath = @"C:\Program Files\Sysnova\";
string desktop = "";
string allusers = "";
string allusersPrograms = "";
OperatingSystem os = Environment.OSVersion;
if ( os.Version.Major == 6 ) {
    desktop = "C:\\Users\\Public\\Desktop\\";
    allusers = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\";
    allusersPrograms = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\";
} else if ( os.Version.Major == 5 ) {
    desktop = "C:\\Documents and Settings\\All Users\\Desktop\\";
    allusers = "C:\\Documents and Settings\\All Users\\Menu Iniciar\\";
    allusersPrograms = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\";
}
 
desktop += "Sysnova EcoPlan.lnk";
allusersPrograms += "Sysnova Solution\\";
 
try { System.IO.File.Delete( desktop ); } catch ( Exception ) { }
try { System.IO.File.Delete( allusersPrograms + "Sysnova EcoPlan.lnk" ); } catch ( Exception ) { }
try { System.IO.File.Delete( allusers + "Sysnova EcoPlan.lnk" ); } catch ( Exception ) { }
 
IWshRuntimeLibrary.WshShellClass wshShell = new IWshRuntimeLibrary.WshShellClass();
IWshRuntimeLibrary.IWshShortcut myShortcut = (IWshRuntimeLibrary.IWshShortcut)wshShell.CreateShortcut( desktop );
myShortcut.TargetPath = sysnovaPath + "ecoplan\\ecoPlan.exe";
myShortcut.Description = "Gestor de Processos Ambientais";
myShortcut.IconLocation = sysnovaPath + "ecoplan\\ecoplan.ico";
myShortcut.Save();
 
System.IO.Directory.CreateDirectory( allusersPrograms );
System.IO.File.Copy( desktop, allusersPrograms + "Sysnova EcoPlan.lnk" );
System.IO.File.Copy( desktop, allusers + "Sysnova EcoPlan.lnk" );

instead of checking the Operating System version, wouldnt it be better to use Environment.GetFolderPath(SpecializedFolder...)?
i think it does that checking for you?

Yes, that handles the w32 api call to find the folder based on operating system and system configuration.

But don't shoot the messenger -- I was just following orders and posting the experts exchange code you asked for :)

According to my research there is no built-in way to get All Users programs menu using .Net Framework 2.0.

there are two ways to do that which i think the latter is the better :

1)

Dim menudir As String = Environment.GetEnvironmentVariable("ALLUSERSPROFILE") + Mid(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), Environment.GetFolderPath(Environment.SpecialFolder.StartMenu).LastInd exOf("\") + 1)

this is found at : http://www.xtremevbtalk.com/showthread.php?t=137200

2)

using System.Runtime.InteropServices;
...
    [DllImport("shfolder.dll", CharSet=CharSet.Unicode)]
    private static extern int SHGetFolderPath(IntPtr owner, int folder, IntPtr token, int flags, StringBuilder path);

    private static string GetAllUsersMenuFolder() {
      StringBuilder path = new StringBuilder(260);
      int retval = SHGetFolderPath(IntPtr.Zero, 0x16, IntPtr.Zero, 0, path);
      if (retval == 0) return path.ToString();
      return Environment.GetFolderPath(Environment.SpecialFolder.StartMenu);
    }

this is found at : http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/5ee4fb1e-3cbb-488c-a517-272fc1aa097d

i will use the second one for my application.

ok guys this is finished, i did a good job. here is the essential coding :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using IWshRuntimeLibrary;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;
using System.Reflection;

namespace CustomInstaller
{
	[RunInstaller(true)]
	public partial class CustomInstaller : Installer
	{
		public CustomInstaller()
		{
			InitializeComponent();
		}
		protected override void OnAfterInstall(System.Collections.IDictionary savedState)
		{
			base.OnAfterInstall(savedState);
			try
			{
				//Debugger.Break();
				//Create new folder under all users programs folder
				string myProgramFolder = Path.Combine(GetAllUsersMenuFolder(), "Programs\\MyProgramFolder");
				if (!Directory.Exists(myProgramFolder))
					Directory.CreateDirectory(myProgramFolder);

				string shortcutname;
				if (!string.IsNullOrEmpty(Context.Parameters["shortcutname"].ToString()))
					shortcutname = Path.Combine(myProgramFolder, Context.Parameters["shortcutname"].ToString() + ".lnk");
				else
					shortcutname = Path.Combine(myProgramFolder, "myshortcut.lnk");
				string targetDir = Context.Parameters["path"].ToString();

				WshShellClass WshShell = new WshShellClass();
				IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)WshShell.CreateShortcut(shortcutname);
				shortcut.Description = "Some Description";
				// your target executable
				shortcut.TargetPath = Path.Combine(targetDir, "CustomShortCuts-Folders-StartMenus.exe");
				shortcut.Save();
				// create the same shortcut on users desktop
				string shortcutnameForDesktop = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), Path.GetFileName(shortcutname));
				System.IO.File.Copy(shortcutname, shortcutnameForDesktop);

				// write the created shortcut names to text file so you can delete them when uninstalling the application.
				StreamWriter sw = System.IO.File.CreateText(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "shortcuts.txt"));
				sw.WriteLine(shortcutname);
				sw.WriteLine(shortcutnameForDesktop);
				sw.Close();

			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		
			
		}

		protected override void OnBeforeUninstall(System.Collections.IDictionary savedState)
		{
			
			base.OnBeforeUninstall(savedState);

			try
			{
				string[] shortcutnames = System.IO.File.ReadAllLines(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "shortcuts.txt"));
				System.IO.File.Delete(shortcutnames[1]);
				System.IO.File.Delete(shortcutnames[0]);
				System.IO.Directory.Delete(Path.GetDirectoryName(shortcutnames[0]));
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		protected override void OnAfterUninstall(System.Collections.IDictionary savedState)
		{
			base.OnAfterUninstall(savedState);
			
		}

		[DllImport("shfolder.dll", CharSet = CharSet.Unicode)]
		private static extern int SHGetFolderPath(IntPtr owner, int folder, IntPtr token, int flags, StringBuilder path);

		private static string GetAllUsersMenuFolder()
		{
			StringBuilder path = new StringBuilder(260);
			int retval = SHGetFolderPath(IntPtr.Zero, 0x16, IntPtr.Zero, 0, path);
			if (retval == 0) return path.ToString();
			return Environment.GetFolderPath(Environment.SpecialFolder.StartMenu);
		}

	}
}

i attach the entire solution so you can test it yourselves.

when you run the installer it will create the shortcuts with hardcoded values.

when you run it like this below it will create shortcuts and menu with the name you specify. you can also specify the target folder from the command line. you can also run the installer in silent mode.

msiexec.exe /i "C:\CustomSetup.msi" SHORTCUTNAME=whatevershortcutname TARGETDIR=c:\mydirectory

nice, now i am creating a sample application to put this knowledge in action, when i am done i will attach it to this thread.
about 10 days reputation, as i said, my problem is atomic, if you help me solve it in all aspects, then you deserve it ;)

Woohoo, today starts day 1!!!

Comments
day 2(yesterday i added one already)
This question has already been answered. Start a new discussion instead.