ClickOnce Desktop Shortcut using VB

This is a follow-up post to the article How to Create a Desktop Shortcut for a ClickOnce Application, providing the VB version of the code, as requested by one of the readers of this blog.

The implementation is slightly different in VB than it is in C#. In C#, you just add the code to the Program.cs and run it prior to the first form being displayed.

In VB, the best place to call this is in the Application Startup event. This video will show you exactly how to do that.

This download contains the sample code in VB (VS2008) as well as a Word document with the same information as the video.
ClickOnce_DesktopShortcut_VB.zip

[Edit 7/7/2011 Move zip file to Azure blob storage]

[Edit 3/8/2015 Move to different Azure blob storage account]

Tags:

46 Responses to “ClickOnce Desktop Shortcut using VB”

  1. Creating a desktop shortcut for a Click Once application « RobinDotNet’s Blog Says:

    […] link to the follow-up post that provides the code and implementation details for doing same in VB. ClickOnce Desktop Shortcut Using VB Possibly related posts: (automatically generated)Desk Topmost brings your desktop quickly to the […]

  2. J Rose Says:

    I am trying to use the VB version of the code and when installing the click once deployment on our machines, we are getting the following error:
    *** System.IO.FileNotFoundException: Could not find file ‘C:\Documents and Settings\jrose\Start Menu\Programs\Generation Mortgage Company\Generation Equity Mortgage System.appref-ms’.
    File name: ‘C:\Documents and Settings\jrose\Start Menu\Programs\Generation Mortgage Company\Generation Equity Mortgage System.appref-ms’
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite)
    at System.IO.File.Copy(String sourceFileName, String destFileName, Boolean overwrite)
    at Gfm.Gems.UI.My.MyApplication.CheckForShortcut()
    at Gfm.Gems.UI.My.MyApplication.MyApplication_Startup(Object sender, StartupEventArgs e)
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnStartup(StartupEventArgs eventArgs)
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()

    ANY help would be greatly appreciated!

    • robindotnet Says:

      The code basically looks for the shortcut on the start menu and copies it to the desktop. To locate the entry on the start menu, it has to have the name of the folder and the name of the shortcut itself.

      In a ClickOnce deployment, the Publisher Name is used for the name of the folder, and the Product Name is used for the name of the actual shortcut.

      Rather than hardcoding those values, the code for the shortcut uses Reflection to retrieve the corresponding information from the Assembly. It assumes the Assembly Company matches the Publisher Name, and the Assembly Description matches the Product Name.

      From the error you are showing here, that’s not the case. It looks like it can’t find the shortcut it wants to copy. So check your Assembly information against your Publish Options and make those two values match, and it should work.

      Please let me know if this fixes your problem!

  3. J Rose Says:

    Thank you so much for your help! It is greatly appreciated. That worked. You were correct . . the Description didn’t quite match my product name.

  4. Ian Says:

    I’m trying to implement your vb code for the desktop icon and its not letting me use the System.Deployment.Application. It says Application is not a memeber or Deployment. What am I doing wrong?

    • robindotnet Says:

      You are probably missing the reference to System.Deployment. Go into MyProject, then choose the References tab. Do you see System.Deployment in either the top or bottom? Click on the Add button under the top window and look for System.Deployment and select it. Then the System.Deployment.Application should work fine for you. –RobinDotNet

  5. Thai Dang Says:

    Robin,

    Thank you very much for your code. This works wonderfully for VS2005. Have great day. -Thai

    • robindotnet Says:

      You’re welcome. BTW, MSFT is pushing .NET 3.5 SP-1 via Windows Updates these days. Last week I discovered a bug in it that results in the desktop shortcut being removed on occasion when there is no update. (I haven’t figured out the pattern yet.)

      To work around that problem, just remove the line of code in the method that creates the shortcut that checks for first run (“If ad.IsFirstRun”). Then it will copy the shortcut every time the user runs the application, thereby working around Microsoft’s bug.

  6. Thai Dang Says:

    Robin,

    Thank you for the information. I will remove the code accordingly. Have a great weekend. I have been using a third party control like Infragistic (Window and Web). Please let me know if I can be of any help.

    Cheers,
    Thai

  7. Diane Says:

    Thanks works great with VS 2005. Other solutions, I had found created the icon but the update no longer worked. By removing the line for creating the shortcut the first time, it fixed the problem with the icon disappearing from the desktop with an update. The people I work with insist on just using icons on their desktop. I really appreciate it. You saved me a lot of grief.

    • robindotnet Says:

      You’re welcome; I’m glad it was helpful to you.

      The original version of my code does check IsFirstRun. When you get an update, Microsoft removes the shortcut from the desktop in anticipation of recreating it because you have checked that box on the option screen that is available when you are using .NET 3.5. It does this even if you don’t have the checkbox selected or are not targeting .NET 3.5. (Grrr.)

      However, we recently had to take out the check for IsFirstRun too. Microsoft is deploying the .NET 3.5 SP-1 Framework via Windows Updates, and there is a bug in it that causes the shortcut to be removed from some users’ desktop when there is no update as well. I haven’t figured out the pattern yet, but it definitely happens. Removing that line of code and just letting it re-copy the shortcut every time the user runs the application pretty much covers all cases.

      I did some testing with the checkbox and targeting .NET 3.5. I forgot to check it the first time I deployed the application. When I checked it and issued an update, it wouldn’t create the shortcut. I’ll do some more testing on it and submit the info to Microsoft. It looks like we won’t be removing this code from our application even when we upgrade to.NET 3.5 SP-1.

  8. Clint Says:

    Hi Robin,
    My application uses multiple desktop shortcuts with command line arguments to determine database connection and some options. would I simply add the command line arguments as part of “shortcutName = String.Concat( _
    Environment.GetFolderPath(Environment.SpecialFolder.Programs), _
    “\”, company, “\”, description, “.appref-ms”)” concatonation? eg …”\”, company, “\”, description, “.appref-ms”, “/DB=ThisDB /Docking=1”)

    And for the multiple shortcuts simply repeat the file.copy with different command lines. Also each shortcut wants its own icon. I am uncertain where the icon is setup in your code and how I could modify it to specify the icons I want.

    I hope my question is clear

    Thanks for what you have already done

    Clint

    • robindotnet Says:

      Hi Clint,
      Unfortunately, you can’t specify the icon used in the shortcut. It uses whatever icon the application uses. Obviously, you can change the name of the icon.
      I didn’t think you could use arguments with the shortcut if the app wasn’t online-only, but I found out in a meeting w/the ClickOnce folks at MSFT last week that you can, if you are targeting .NET 3.5 SP-1.
      The code for finding the shortcut in the start menu is in my shortcut code. It’s string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs), “\”, company, “\”, description, “.appref-ms”), where the company and description come from the assembly information.
      You should be able to just tack the arguments on the end like this:
      MyApp.appref-ms arg1 arg2
      Then you can get the arguments using
      Dim activationItems as string() = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData
      Give it a try and let me know if it works.
      RobinDotNet

      • John C. Pachkoski Says:

        Trying to add command line parameters by using the above concatenation does not work. It can’t find the path (once the parameters are added, as above).

        • robindotnet Says:

          Is your application an online/offline application or just online? It has to be online/offline for there to be a shortcut on the start menu. Do you have a shortcut on the start menu, and do your assembly attributes match the product name and publisher specified in the ClickOnce options?

        • John C. Pachkoski Says:

          Yes, I have a shortcut on the start menu, and was able to create one on the desktop using the code and/or installing SP1 for Visual Studio…which then gives you an option to check a box and have it make the desktop icon without using the code. However, trying to append command line arguments to the shortcut, as you have mentioned, does not work since the application reference file (the shortcut) “thinks” the actual path to the executable is the path PLUS the command line parameters…not a path to the executable then command line arguements to pass to that path. You should actually try it and you will see what I am saying. Thanks for the code to make the shortcut; unfortunately, however, the only way to send parameters, for Click-Once is via a querystring to a URL.

          • robindotnet Says:

            Placing a shortcut on the desktop has nothing to do with appending parameters to it. Plus, you don’t want to use the path to the executable, because it won’t act like a ClickOnce application — no updates, no security checks, nothing.

            And you are incorrect — You CAN pass parameters to a ClickOnce application even if it is offline or deployed to a file share. I just discovered this recently. You have to be using .NET 3.5 SP-1 or .NET 4.0. My blog entry (complete with code samples in both VB and C#) on how to do this is here.

            Good luck!

        • John C. Pachkoski Says:

          Placing a shortcut on the desktop (or in the Start Menu) has EVERYTHING to do with attempting to tack arguments on to it (the shortcut). Without a shortcut (on the desktop, or otherwise) you have nothing on which to “tack on” the arguments, as you haphazardly stated earlier.

          Again, your original “idea” of tacking parameters on, does not work because the application reference file (the shortcut) “thinks” the actual path to the executable is the path PLUS the command line parameters…not a path to the executable then command line arguements to pass to that path. Basically, your haphazard comments waste other peoples’ time.

          Here is what you stated, copied below:

          “The code for finding the shortcut in the start menu is in my shortcut code. It’s string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs), “\”, company, “\”, description, “.appref-ms”), where the company and description come from the assembly information.
          You should be able to just tack the arguments on the end like this:
          MyApp.appref-ms arg1 arg2”

          Now….hopefully, in your more recent April 16. 2010 (at 5:07pm) blog entry, you have actually determined how to pass parameters to a ClickOnce application (not via a QueryString), and have tested the code (and it actually works?) before you put it on the internet for others to use. If it really does work, then I thank you for your effort. I have not tested/looked at it; therefore, I can’t confirm that it actually does work. Hopefully, someone else can/will confirm that it works.

          • robindotnet Says:

            Thanks for your feedback. However, you CAN tack parameters on when invoking the application via the shortcut. As noted above,this blog entry explains how and provides code samples for doing so. So I am going to have to respectfully disagree with what you’ve said. Please check it out; I hope it is helpful to you.

    • John C. Pachkoski Says:

      Clint,

      Take a look at the last part of my blog entry, April 29, 2010 at 9:37 am, which mentions that you can read the contents of the shortcut (application reference file) to determine, for example, what connection string to use for your ClickOnce application…based on the URL found in that application reference file (shortcut).

      Basically, you can set up different publishing websites that contain the words production, development, integration, etc.) within each publishing virtual directory name (the publishing website’s URL), then read the shortcut to determine if “production”, “development” is in the shortcut (once installed on the client), and have your program use the appropriate connection string for that environment.

  9. Anthony Says:

    Hi Robin,

    I followed your code on how to create desktop shortcut in clickonce. That is great, thank you for this method. But in my case I have one solution but two separate projects inside which have its own clickonce publishing. That is our internal and external version of application. In internal version this shortcut creation method works well but I tried it on our external version, though I put the publisher name same as the company and product name same as the description. And when I publish it, it didn’t show any error but it also didn’t create shortcut on the desktop.

    Do you have any idea why it’s not working on the external version?

    Many thanks,
    Anthony

  10. John C. Pachkoski Says:

    OK…

    I tested the code from your April 16, 2010 (5:07pm) blog entry, and that code does pass in arguments to a ClickOnce application from a separate, calling program by determining the location/path of the Start, All Programs
    shortcut, then using the following:

    System.Diagnostics.Process.Start(shortcutPath, argsToPass);

    The arguments are generated by the separate, calling program…so, if you intend to call your ClickOnce application
    using a separate, calling program (and intend to deploy/install that separate calling program to all your clients), that may be fine with you.

    An alternative, of course, would be to move the code from the calling program into the ClickOnce application (the code that finds the shortcut and constructs the command line parameters); but, then you are hard-coding command line parameters into the ClickOnce application, rather than putting them on the client…and the purpose is to be able to pass command line parameters into the ClickOnce application from something that is truly associated with the ClickOnce application (like the shortcut).

    Since you have been communicating with Microsoft regarding this issue, can you please ask them/determine whether it’s possible to have ClickOnce construct an application reference file (the shortcut) that contains command line parameters within itself, so you can launch the application by just clicking on the shortcut and have it (the shortcut) pass the command line parameters to the ClickOnce application…instead of having a separate program do it? What if a certain user/client is supposed to launch the application with a set of particular, command line parameters, while another is supposed to launch it with a different set of command line parameters? Can you publish and/or construct customized shortcuts, for different users, using the deployment features of ClickOnce?

    Also…as an aside, and with respect to the application reference file (the shortcut):
    It’s possible to open and read the contents of the application reference file (manually, using Notepad) and, also, parse (programmatically) what’s in the file to determine what connection string to use, for example, for whatever environment the ClickOnce application is installed…for example…if the application reference file contains the following, below, (since you have published and then installed from a website which you have specifically set up, on IIS, to use for production that contains the word, prod, for example:

    http://prod-companyname-apps/TestRunningWithArgs

    You can parse and find “prod” from above, and know that you should use the connection string to prod (your production environment).

    If you have published from a website that you use for development, that you have set up on IIS to contain the word, “dev”, for example:

    http://dev-companyname-apps/TestRunningWithArgs

    You can parse the above and know to use the connection string for dev (your development environment).

    Note that in the above two cases, you are not passing any command line arguments…just reading the application reference file, in order to determine what environment the install was intended for (and which connection string to use to your data).

    Best regards.

    John C. Pachkoski

    • robindotnet Says:

      Actually, I did ask the ClickOnce product lead about this. He said to try creating a shortcut that runs the shortcut with query parameters. I haven’t had time to test it yet. He advised against trying to programmatically create an appref-ms shortcut. For one thing, you never know when they might change the internals of that, just like they added the “Application Files” folder when moving from VS2005 to VS2008.

      • John C. Pachkoski Says:

        Robin,

        Trying creating a shortcut that runs the shortcut? WHAT???!!! That’s absurd.

        Also, if you have Visual Studio 2010 Service Pack 1, there’s an option in the Publish tab, Options, Manifests, Create desktop shortcut (checkbox), that will make a shortcut on the desktop. Right-click on the project to get there. I did not read the desktop shortcut, I read the one that ClickOnce makes in Start, All Programs, since I knew it would always be there. If you do check Create desktop shortcut, you can read that one, instead, since it will always be there, too. I decided not to programmatically create the desktop shortcut…just install Visual Studio 2010 Service Pack 1 and use the option.

        Here’s an idea…which is basically what I was trying to get you to ask Microsoft…
        If the Microsoft team could add an option (a checkbox)…that would enable a textbox where you can just enter command line parameters that ultimately would end up within the Start, All Programs shortcut of the ClickOnce application (parameters that can be passed when the shortcut is clicked) that would be good.

        • robindotnet Says:

          I’ve sent you an e-mail asking for more details. I did talk to the ClickOnce product team about your request, and they had some questions.

          • John C. Pachkoski Says:

            I received the email and sent you a response.

          • dips Says:

            Does the mentioned issue got resolved? i.e. i have a clickonce shortcut with extension appref.ms and i want to pass command line arguments by editing the shortcut itself like we do for simple desktop shortcut. Is it possible to do that without using other program (System.Diagnostics.Process.Start(shortcutPath, argsToPass);)

  11. Jörgen Says:

    Hi Robin

    I have just found your Blog and I like it. This is an great blog keep up the good work.

    I’m using clickonce and your VB code for creating a shortcut to the desktop. On my computer and on another developers computer it’s workin just fine no problem there, but if we using a “simpel users” computer the desktop icon doesn’t show.
    We are all using framework 3,5 with SP1. Platform XP professional.
    Please do you have any Idee how to find this error?

    ANY help would be greatly appreciated!
    Kind regards
    Jörgen

    • robindotnet Says:

      What is a “simpel users” computer? (I’m assuming you mean ‘simple’, but what do you mean by that? Just some user, or is there some special access granted?) Does he have write access to his desktop, and does it add the start menu options correctly?
      Robin

      • Jörgen Says:

        Hi Robin,
        I’m sorry for my english. It’s not my maternal language.
        By a “simple” user a meant a user that don’t have any VS 2008 installed on his/her computer.
        They have all adminitrator rights on there computer, so I can’t see any write problem there.’
        The icon in the start menu are created as it should. It’s only the icon on the desktop that doesn’t show.

        the code in applicationEvent.vb
        Private Shared Sub CheckForShortcut()
        Dim ad As System.Deployment.Application.ApplicationDeployment
        Dim jono As Boolean
        jono = System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed
        If (jono) Then
        ad = System.Deployment.Application.ApplicationDeployment.CurrentDeployment
        ‘Dim ad As ApplicationDeployment = ApplicationDeployment.CurrentDeployment
        ‘If (ad.IsFirstRun) Then ‘first time user has run the app since installation or update
        Dim code As Assembly = Assembly.GetExecutingAssembly()
        Dim company As String = String.Empty
        Dim description As String = String.Empty
        If (Attribute.IsDefined(code, GetType(AssemblyCompanyAttribute))) Then
        Dim ascompany As AssemblyCompanyAttribute = CType(Attribute.GetCustomAttribute(code, _
        GetType(AssemblyCompanyAttribute)), AssemblyCompanyAttribute)
        company = ascompany.Company
        End If
        If (Attribute.IsDefined(code, GetType(AssemblyDescriptionAttribute))) Then
        Dim asdescription As AssemblyDescriptionAttribute = CType(Attribute.GetCustomAttribute(code, _
        GetType(AssemblyDescriptionAttribute)), AssemblyDescriptionAttribute)
        description = asdescription.Description
        End If
        If (company.Length > 0 AndAlso description.Length > 0) Then
        Dim desktopPath As String = String.Empty
        desktopPath = String.Concat( _
        Environment.GetFolderPath(Environment.SpecialFolder.Desktop), “\”, description, “.appref-ms”)
        Dim shortcutName As String = String.Empty
        shortcutName = String.Concat( _
        Environment.GetFolderPath(Environment.SpecialFolder.Programs), “\”, company, “\”, _ description, “.appref-ms”)
        System.IO.File.Copy(shortcutName, desktopPath, True)
        End If
        ‘End If
        End If
        End Sub

        Kind regards
        Jörgen

        • robindotnet Says:

          Hi,
          Did you make sure your assembly info matches the info in the Options properties of your ClickOnce application? The assembly description should match the Product Name, and the assembly company should match the Publishing Company.
          Also make sure you are actually *calling* the subroutine somewhere.
          RobinDotNet

  12. balukrishnan Says:

    Hi,
    This is regarding clickonce installation. After I share a clickonce app for installation, is it possible someway to determine how many clients have used ths install? It would be best if we can make out which all client machines have installed the latest update. Any help is appreciated.

    Thanks In Advance
    Balu

    • robindotnet Says:

      This is not a feature of ClickOnce deployment. I will share with you how I handle this. I have an authentication/splash screen where the user has to enter credentials and it verifies with a web service that they are a valid user. At that time, I also update a field in the database telling what version he is using and when he last logged in. Some of our customers use our application all the time, some use it every now and then; this is the only way I could think of to figure out if everyone has updated their version.

      Another thing that helps is if you deploy the update as a required update, so they can’t skip it. To do this, go into the Updates dialog and at the bottom, check the box to apply a minimum version number, and set the version number to the version you are deploying. If you do this, it won’t even ask them if they want the update, it will just install it.

  13. balukrishnan Says:

    Thanks for the info. It would be great if you could share you application.

    Also I have noticed one case. I have the current version installed on a desktop. Then I upgraded the version in the installation location. I had selected the option “check for updates during application startup” while publishing. When I started the already installed application, it didnt check for the updates. I closed the app and started it again. Then it checked for updates and the latest updates got pulled. This is happening everytime. Do you clue as to why this would be happening?

    • robindotnet Says:

      I am Director of Engineering for GoldMail, and have written many parts of our product and am responsible for the deployment design (ClickOnce). We have a free version that you can download and use. Please check it out at http://www.goldmail.com. If you sign up and you like it and want to use it, if you post a comment here I can upgrade you to a 1-year GoldMail Business account for free.

    • robindotnet Says:

      Did you change the version number when you deployed the new version? You don’t have “specify how frequently application should check for updates” checked, do you? Does this happen every single time, or is it random? In other words, can you deploy a version, run the app and the update doesn’t get picked up, deploy another version, run the app and the update DOES get picked up?

  14. ROBERT CEZAR Says:

    Hi Robin,

    As I recall, I believe I was the one who started this Desktop Icon business…. way back when, and you were extremely helpful in getting me the code. Thanks again. I have one more question is this regard… sort of, but not quite.

    How can an external programme FIND the desktop icon, in order to launch our Its Your Plane (IYP) application… naturally respecting the most recent update of the IYP application? I hope this question is clearer than mud !!! Thanks in advance. Regards, Robert

  15. robindotnet Says:

    Here you go…

    shortcutName =
                      string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs),
                        “\\”, publisher_name, “\\”, product_name, “.appref-ms”);
    where publisher_name is the same as the Publisher Name in the Options dialog, and product_name is the same as the Product Name in the Options dialog.

    • Jamil Says:

      how to get the publisher_name and Product_name Values ???
      thank you for your support 🙂

      • robindotnet Says:

        The publisher name and product name are specified by you in the project properties. After bringing up the publish tab, click the Options button; they are in there.

        • Jamil Says:

          yes i know , but i want to retrieve its value in my code later , is this available ??
          hope that is it available , i want to use it to check the shortcut

          • robindotnet Says:

            No, it’s not. That’s why I assign the same values to the assembly attributes, and pull the info from the assembly instead, as noted in the article.

  16. Robert Cezar Says:

    As usual…. you make it look sooooooo eeasy!

    Thanks a lot Robin.

    Regards,

    Robert

  17. John C. Pachkoski Says:

    Robin,

    I’m copying the below from my previous blog entry from a long time ago…

    “Here’s an idea…which is basically what I was trying to get you to ask Microsoft…
    If the Microsoft team could add an option (a checkbox)…that would enable a textbox where you can just enter command line parameters that ultimately would end up within the Start, All Programs shortcut of the ClickOnce application (parameters that can be passed when the shortcut is clicked) that would be good.”

    Did Microsoft ever add the capability (the above option I suggested), so the shortcut that gets generated, upon deployment, can have parameters (within itself) that can be passed to the application?

    From what I recall, Microsoft was advising to create a shortcut that calls the shortcut…which is very strange.

    I’ve been developing other types of .NET applications the past year (not ClickOnce); but, thought I’d follow up on this and ask you.

    Thanks and best regards.

    John C. Pachkoski

  18. robindotnet Says:

    Hi John,
    There have been no additional changes made to ClickOnce that would make that feature available. I did, however, figure out how to find the desktop shortcut in order to invoke the application and pass parameters to it. You can use something like this: %userprofile%\Desktop\Your Shortcut Name Here.appref-ms arg1,arg2,arg3
    Make sure there are no spaces in the list of arguments — html encoding them as noted in my article on passing query parameters to an offline application is the safest method to use.
    Hope that helps!
    Robin

Leave a comment