كيف أقوم بإنشاء إضافة اختصار (.lnk) لتطبيقي إلى مجلد بدء التشغيل برمجياً في .NET/C#

StackOverflow https://stackoverflow.com/questions/1036093

سؤال

سيحتوي تطبيقي على اختصار بدء التشغيل لكل جهاز (وليس لكل مستخدم).يمكنني إنشاء اختصار أثناء عملية التثبيت ولا توجد مشكلة.تأتي مشكلتي عندما يقوم المستخدم بإزالتها لاحقًا ثم يحاول إعادة تمكينها.بمعنى آخر، يقومون بإيقاف تشغيل RunOnStartup (الذي يحذف حبر بدء التشغيل) وفي وقت لاحق يقررون أنهم يريدون تشغيله عند بدء التشغيل حتى يعودوا إلى التفضيلات ويعيدوا التمكين.

على ما يبدو، هذه شكوى شائعة جدًا لدى .NET، حيث لا توجد طريقة أصلية لإنشاء الاختصارات.ولكن، لم يتم العثور على حل جيد للغاية.

الحلول التي وجدتها/فكرت فيها:

  • بدلاً من ذلك قم بإنشاء اختصار.فقط قم بنسخ واحدة.قد يكون هذا حلا جيدا.لا أستطيع الاعتماد على وجود رابط قائمة ابدأ.ولكن، أعتقد أنه ربما يمكنني إنشاء واحد والاحتفاظ به في دليل البرامج...يؤدي هذا إلى نقل المشكلة إلى برنامج التثبيت الخاص بي ليقوم بإنشاء الاختصار بالمسار المناسب الذي سيتم تحديده في وقت التثبيت.

  • افعل ما هذه الإجابة الأخرى لتدفق المكدس هو واستخدام كائن مجمع COM.أود تجنب COM.وقد كتب أيضا في عام 2003.لذا، لست متأكدًا من مدى جودة دعم نظام التشغيل Vista.سأجربها ولكن ليس لدي صندوق فيستا في متناول يدي.

  • استخدم التسجيل بدلاً من ذلك.وهذه هي الطريقة التي أفعلها حاليا..ولكن واجهت مشاكل في نظام التشغيل Vista.يبدو أن هناك إجماعًا عامًا على أن اختصارات قائمة بدء التشغيل هي الطريقة الصحيحة للقيام بذلك، وهذا هو هدفي.

يجب أيضًا أن أتعامل مع حالة محاولة مستخدم عادي (وليس مسؤولًا) تغيير هذا التفضيل.في هذه الحالة، أحتاج إلى الفشل بأمان أو في حالة نظام التشغيل Vista السماح للمستخدم بإدخال كلمة مرور المسؤول للحصول على رمز أمان المسؤول.الإجابة التي تأخذ هذه الحالة في الاعتبار بشكل صحيح ستكون رائعة.

أعتذر إذا تم تناول هذا الموضوع بالفعل.لقد بحثت حولي قبل النشر.

تحديث:يعد نسخ الاختصار الذي أنشأه برنامج التثبيت هو الحل الأفضل.سأقوم بنشر الرمز بمجرد الانتهاء ...واجهت بعض العقبات مع أ) عدم وجود إشارة إلى Environment.GetSpecialFolder إلى قائمة StartMenu التي تم حلها...لكنني الآن أتعامل مع رفع الأذونات لنسخ الملف إلى الموقع الصحيح.لقد قمت بإنشاء سؤال جديد لتدفق المكدس لهذا الموضوع: كيف يمكنني نسخ ملف باعتباره "مستخدمًا قياسيًا" في نظام التشغيل Vista (أي "تطبيق اختيار إداري") عن طريق مطالبة المستخدم ببيانات اعتماد المسؤول؟

هل كانت مفيدة؟

المحلول

كما اقترح جويل، الحل المناسب هو تثبيت اختصار في مجلد ملفات البرنامج الخاص بك في وقت التثبيت ثم نسخ ملف .lnk إلى مجلد بدء التشغيل.تعد محاولة إنشاء اختصار أكثر صعوبة.

الكود أدناه يفعل ما يلي:

  • فهو يحصل على المسار إلى مجلد بدء التشغيل لكافة المستخدمين.يعد Environment.GetSpecialFolder محدودًا إلى حد ما ولا يحتوي على إشارة إلى هذا المجلد ونتيجة لذلك تحتاج إلى إجراء اتصال بالنظام.
  • لديه طرق لنسخ وإزالة الاختصار.

في النهاية، أردت أيضًا التأكد من أنه تم التعامل معه بأمان على نظام التشغيل Vista إذا كان المستخدم الذي يقوم بتشغيل التطبيق مستخدمًا عاديًا، فستتم مطالبته بإدخال بيانات الاعتماد الخاصة به.لقد قمت بإنشاء منشور هنا حول هذا الموضوع، لذا تحقق من ذلك هنا إذا كان هذا مهمًا بالنسبة لك.كيف يمكنني نسخ ملف باعتباره "مستخدمًا قياسيًا" في نظام التشغيل Vista (أي "تطبيق اختيار إداري") عن طريق مطالبة المستخدم ببيانات اعتماد المسؤول؟

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Principal;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace BR.Util
{
public class StartupLinkUtil
{
    [DllImport("shell32.dll")]
    static extern bool SHGetSpecialFolderPath(IntPtr hwndOwner, [Out] StringBuilder lpszPath, int nFolder, bool fCreate);

    public static string getAllUsersStartupFolder()
    {
        StringBuilder path = new StringBuilder(200);
        SHGetSpecialFolderPath(IntPtr.Zero, path, CSIDL_COMMON_STARTUP, false);
        return path.ToString();
    }


    private static string getStartupShortcutFilename()
    {
        return Path.Combine(getAllUsersStartupFolder(), Application.ProductName) + ".lnk";
    }

   public static bool CopyShortcutToAllUsersStartupFolder(string pShortcutName)
    {
        bool retVal = false;
        FileInfo shortcutFile = new FileInfo(pShortcutName);
        FileInfo destination = new FileInfo(getStartupShortcutFilename());

        if (destination.Exists)
        {
            // Don't do anything file already exists.  -- Potentially overwrite?
        }
        else if (!shortcutFile.Exists)
        {
            MessageBox.Show("Unable to RunOnStartup because '" + pShortcutName + "' can't be found.  Was this application installed properly?");
        }
        else
        {
            retVal = copyFile(shortcutFile, destination);
        }
        return retVal;
    }

    public static bool doesShortcutExistInAllUsersStartupFolder()
    {
        return File.Exists(getStartupShortcutFilename());
    }

    public static bool RemoveShortcutFromAllUsersStartupFolder() {
        bool retVal = false;
        string path = Path.Combine(getAllUsersStartupFolder(), Application.ProductName) + ".lnk";
        if( File.Exists(path) ) {
            try
            {
                File.Delete(path);
                retVal = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("Unable to remove this application from the Startup list.  Administrative privledges are required to perform this operation.\n\nDetails: SecurityException: {0}", ex.Message), "Update Startup Mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        return retVal;
    }

    // TODO: Test this in vista to see if it prompts for credentials.
    public static bool copyFile(FileInfo pSource, FileInfo pDestination)
    {
        bool retVal = false;

        try
        {
            File.Copy(pSource.FullName, pDestination.FullName);
            //MessageBox.Show("File has successfully been added.", "Copy File", MessageBoxButtons.OK, MessageBoxIcon.Information);
            retVal = true;
        }
        catch (System.Security.SecurityException secEx)
        {
            MessageBox.Show(string.Format("SecurityException: {0}", secEx.Message), "Copy File", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        catch (UnauthorizedAccessException authEx)
        {
            MessageBox.Show(string.Format("UnauthorizedAccessException: {0}", authEx.Message), "Copy File", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Copy File", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        return retVal;
    }

    #region Special Folder constants
    const int CSIDL_DESKTOP = 0x0000;        // <desktop>
    const int CSIDL_INTERNET = 0x0001;        // Internet Explorer (icon on desktop)
    const int CSIDL_PROGRAMS = 0x0002;        // Start Menu\Programs
    const int CSIDL_CONTROLS = 0x0003;        // My Computer\Control Panel
    const int CSIDL_PRINTERS = 0x0004;        // My Computer\Printers
    const int CSIDL_PERSONAL = 0x0005;        // My Documents
    const int CSIDL_FAVORITES = 0x0006;        // <user name>\Favorites
    const int CSIDL_STARTUP = 0x0007;        // Start Menu\Programs\Startup
    const int CSIDL_RECENT = 0x0008;        // <user name>\Recent
    const int CSIDL_SENDTO = 0x0009;        // <user name>\SendTo
    const int CSIDL_BITBUCKET = 0x000a;        // <desktop>\Recycle Bin
    const int CSIDL_STARTMENU = 0x000b;        // <user name>\Start Menu
    const int CSIDL_MYDOCUMENTS = CSIDL_PERSONAL; //  Personal was just a silly name for My Documents
    const int CSIDL_MYMUSIC = 0x000d;        // "My Music" folder
    const int CSIDL_MYVIDEO = 0x000e;        // "My Videos" folder
    const int CSIDL_DESKTOPDIRECTORY = 0x0010;        // <user name>\Desktop
    const int CSIDL_DRIVES = 0x0011;        // My Computer
    const int CSIDL_NETWORK = 0x0012;        // Network Neighborhood (My Network Places)
    const int CSIDL_NETHOOD = 0x0013;        // <user name>\nethood
    const int CSIDL_FONTS = 0x0014;        // windows\fonts
    const int CSIDL_TEMPLATES = 0x0015;
    const int CSIDL_COMMON_STARTMENU = 0x0016;        // All Users\Start Menu
    const int CSIDL_COMMON_PROGRAMS = 0x0017;        // All Users\Start Menu\Programs
    const int CSIDL_COMMON_STARTUP = 0x0018;        // All Users\Startup
    const int CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019;        // All Users\Desktop
    const int CSIDL_APPDATA = 0x001a;        // <user name>\Application Data
    const int CSIDL_PRINTHOOD = 0x001b;        // <user name>\PrintHood
    const int CSIDL_LOCAL_APPDATA = 0x001c;        // <user name>\Local Settings\Applicaiton Data (non roaming)
    const int CSIDL_ALTSTARTUP = 0x001d;        // non localized startup
    const int CSIDL_COMMON_ALTSTARTUP = 0x001e;        // non localized common startup
    const int CSIDL_COMMON_FAVORITES = 0x001f;
    const int CSIDL_INTERNET_CACHE = 0x0020;
    const int CSIDL_COOKIES = 0x0021;
    const int CSIDL_HISTORY = 0x0022;
    const int CSIDL_COMMON_APPDATA = 0x0023;        // All Users\Application Data
    const int CSIDL_WINDOWS = 0x0024;        // GetWindowsDirectory()
    const int CSIDL_SYSTEM = 0x0025;        // GetSystemDirectory()
    const int CSIDL_PROGRAM_FILES = 0x0026;        // C:\Program Files
    const int CSIDL_MYPICTURES = 0x0027;        // C:\Program Files\My Pictures
    const int CSIDL_PROFILE = 0x0028;        // USERPROFILE
    const int CSIDL_SYSTEMX86 = 0x0029;        // x86 system directory on RISC
    const int CSIDL_PROGRAM_FILESX86 = 0x002a;        // x86 C:\Program Files on RISC
    const int CSIDL_PROGRAM_FILES_COMMON = 0x002b;        // C:\Program Files\Common
    const int CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c;        // x86 Program Files\Common on RISC
    const int CSIDL_COMMON_TEMPLATES = 0x002d;        // All Users\Templates
    const int CSIDL_COMMON_DOCUMENTS = 0x002e;        // All Users\Documents
    const int CSIDL_COMMON_ADMINTOOLS = 0x002f;        // All Users\Start Menu\Programs\Administrative Tools
    const int CSIDL_ADMINTOOLS = 0x0030;        // <user name>\Start Menu\Programs\Administrative Tools
    const int CSIDL_CONNECTIONS = 0x0031;        // Network and Dial-up Connections
    const int CSIDL_COMMON_MUSIC = 0x0035;        // All Users\My Music
    const int CSIDL_COMMON_PICTURES = 0x0036;        // All Users\My Pictures
    const int CSIDL_COMMON_VIDEO = 0x0037;        // All Users\My Video
    const int CSIDL_RESOURCES = 0x0038;        // Resource Direcotry
    const int CSIDL_RESOURCES_LOCALIZED = 0x0039;        // Localized Resource Direcotry
    const int CSIDL_COMMON_OEM_LINKS = 0x003a;        // Links to All Users OEM specific apps
    const int CSIDL_CDBURN_AREA = 0x003b;        // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
    const int CSIDL_COMPUTERSNEARME = 0x003d;        // Computers Near Me (computered from Workgroup membership)
    const int CSIDL_FLAG_CREATE = 0x8000;        // combine with CSIDL_ value to force folder creation in SHGetFolderPath()
    const int CSIDL_FLAG_DONT_VERIFY = 0x4000;        // combine with CSIDL_ value to return an unverified folder path
    const int CSIDL_FLAG_DONT_UNEXPAND = 0x2000;        // combine with CSIDL_ value to avoid unexpanding environment variables
    const int CSIDL_FLAG_NO_ALIAS = 0x1000;        // combine with CSIDL_ value to insure non-alias versions of the pidl
    const int CSIDL_FLAG_PER_USER_INIT = 0x0800;        // combine with CSIDL_ value to indicate per-user init (eg. upgrade)
    #endregion
}

بينما كنت أكتب هذا الحل، فكرت في طريقة أفضل للتعامل مع المشكلة والتي لن تتطلب من المستخدمين الحصول على امتيازات متصاعدة من أجل تعطيل التشغيل عند بدء التشغيل.كان الحل الخاص بي هو التحقق بمجرد تحميل البرنامج مما إذا كان هناك إعداد محدد للمستخدم يسمى RunOnStartup.لاكتشاف ما إذا كان التطبيق قد بدأ تشغيله عند تحميل النظام أو تسجيل الدخول، قمت بإضافة وسيطة إلى الاختصار الذي تتم إضافته إلى كافة المستخدمين -> مجلد بدء التشغيل المسمى الاختصار.

        // Quit the application if the per user setting for RunOnStartup is false.
            if (args != null && args.Length > 0 && args[0].Contains("startup"))
            {
                if (Settings1.Default.RunOnStartup == false)
                {
                    Application.Exit();
                }
            }

نصائح أخرى

يمكنك تثبيت اختصار لتطبيقك في مجلد ملفات البرنامج الخاص به، ثم قم بنسخ ملف .lnk هذا حسب الحاجة.

لقد انتهيت من هذا

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Shell32;
using IWshRuntimeLibrary;
using System.IO;

namespace CMS.data
{
    public class overall
    {
        public static void place_shortcut_on_desktop()
        {
            string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\YourName.lnk";
            string shortcutto = System.Reflection.Assembly.GetExecutingAssembly().Location;

            var wsh = new IWshShell_Class();
            IWshRuntimeLibrary.IWshShortcut shortcut = wsh.CreateShortcut(desktopPath) as IWshRuntimeLibrary.IWshShortcut;
            shortcut.TargetPath = shortcutto;
            shortcut.WorkingDirectory = Directory.GetParent(shortcutto).FullName;
            shortcut.Save();
        }
    }//class overall
}

تذكر "دليل العمل" فقد يسبب مشاكل بخلاف ذلك

يمكنك أيضًا إضافة الرمز بهذه الطريقة ولكن في حالتي لم أكن بحاجة إليه

إنها إجابتي الأولى هنا عند تجاوز سعة المكدس، لذا فإن الشكر سيساعدني حقًا

لقد كنت أستخدم هذا الحل منذ فترة ويبدو أنه يعمل بشكل جيد.

شللينك

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top