Удаление приложения ClickOnce без вывода сообщений - PullRequest
14 голосов
/ 14 февраля 2011

У нас есть производственное приложение, которое развертывается с помощью встроенного в Visual Studio инструмента развертывания ClickOnce. Я пишу командный файл для удаления приложения:

rundll32.exe dfshim.dll,ShArpMaintain AppName.application, Culture=neutral,
PublicKeyToken=XXXXXX, processorArchitecture=x86

Пакетный файл работает и вызывается деинсталляция приложения. Тем не менее, я хочу сделать это молча. Я пытался /Q /q /S /s /Silent, но без радости.

Как я могу это сделать?


Я не хочу скрыть окно командного файла. Только окно ClickOnce .

Ответы [ 5 ]

24 голосов
/ 07 мая 2013

Поскольку для этого, похоже, не было хорошего решения, я реализовал новый деинсталлятор ClickOnce. Его можно вызывать из командной строки, из .NET или интегрировать в проект установки WiX как пользовательское действие.

https://github.com/6wunderkinder/Wunder.ClickOnceUninstaller

Мы использовали это для нашего выпуска Wunderlist 2.1, где мы переключились с ClickOnce на пакет установщика Windows. Он интегрирован в процесс установки и полностью прозрачен для пользователя.

3 голосов
/ 19 сентября 2013

Я могу подтвердить, что WMIC не работает для приложений ClickOnce. Их там просто нет в списке ...

Я подумал о том, чтобы поместить это здесь, так как я уже долгое время работал над поиском решения этой проблемы и не мог найти полное решение.

Я довольно новичок во всем этом программировании, но я думаю, что это может дать представление о том, как действовать.

Он в основном проверяет, запущено ли приложение в настоящее время, и если да, то убивает его. Затем он проверяет реестр, чтобы найти строку удаления, поместить ее в пакетный файл и дождаться окончания процесса. Затем он делает Sendkeys автоматически согласиться на удаление. Вот и все.

namespace MyNameSpace
{
    public class uninstallclickonce
    {
        [System.Runtime.InteropServices.DllImport("user32.dll")]

        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [System.Runtime.InteropServices.DllImport("user32.dll")]

        private static extern bool SetForegroundWindow(IntPtr hWnd);

        private Process process;
        private ProcessStartInfo startInfo;

        public void isAppRunning()
        {
            // Run the below command in CMD to find the name of the process
            // in the text file.
            //
            //     WMIC /OUTPUT:C:\ProcessList.txt PROCESS get Caption,Commandline,Processid
            //
            // Change the name of the process to kill
            string processNameToKill = "Auto-Crop"; 

            Process [] runningProcesses = Process.GetProcesses();

            foreach (Process myProcess in runningProcesses)
            {
                // Check if given process name is running
                if (myProcess.ProcessName == processNameToKill)
                {
                    killAppRunning(myProcess);
                }
            }
        }

        private void killAppRunning(Process myProcess)
        {
            // Ask the user if he wants to kill the process
            // now or cancel the installation altogether
            DialogResult killMsgBox =
                MessageBox.Show(
                    "Crop-Me for OCA must not be running in order to get the new version\nIf you are ready to close the app, click OK.\nClick Cancel to abort the installation.",
                    "Crop-Me Still Running",
                    MessageBoxButtons.OKCancel,
                    MessageBoxIcon.Question);

            switch(killMsgBox)
            {
                case DialogResult.OK:
                    //Kill the process
                    myProcess.Kill();
                    findRegistryClickOnce();
                    break;
                case DialogResult.Cancel:
                    //Cancel whole installation
                    break;
            }
        }

        private void findRegistryClickOnce()
        {
            string uninstallRegString = null; // Will be ClickOnce Uninstall String
            string valueToFind = "Crop Me for OCA"; // Name of the application we want
                                                    // to uninstall (found in registry)
            string keyNameToFind = "DisplayName"; // Name of the Value in registry
            string uninstallValueName = "UninstallString"; // Name of the uninstall string

            //Registry location where we find all installed ClickOnce applications
            string regProgsLocation = 
                "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";

            using (RegistryKey baseLocRegKey = Registry.CurrentUser.OpenSubKey(regProgsLocation))
            {
                //Console.WriteLine("There are {0} subkeys in here", baseLocRegKey.SubKeyCount.ToString());

                foreach (string subkeyfirstlevel in baseLocRegKey.GetSubKeyNames())
                {
                   //Can be used to see what you find in registry
                   // Console.WriteLine("{0,-8}: {1}", subkeyfirstlevel, baseLocRegKey.GetValueNames());

                    try
                    {
                        string subtest = baseLocRegKey.ToString() + "\\" + subkeyfirstlevel.ToString();

                        using (RegistryKey cropMeLocRegKey =
                                 Registry.CurrentUser.OpenSubKey(regProgsLocation + "\\" + subkeyfirstlevel))
                        {
                            //Can be used to see what you find in registry
                            //  Console.WriteLine("Subkey DisplayName: " + cropMeLocRegKey.GetValueNames());

                            //For each
                            foreach (string subkeysecondlevel in cropMeLocRegKey.GetValueNames())
                            {
                                // If the Value Name equals the name application to uninstall
                                if (cropMeLocRegKey.GetValue(keyNameToFind).ToString() == valueToFind)
                                {
                                    uninstallRegString = cropMeLocRegKey.GetValue(uninstallValueName).ToString();

                                    //Exit Foreach
                                    break;
                                }
                            }
                        }
                    }
                    catch (System.Security.SecurityException)
                    {
                        MessageBox.Show("security exception?");
                    }
                }
            }
            if (uninstallRegString != null)
            {
                batFileCreateStartProcess(uninstallRegString);
            }
        }

        // Creates batch file to run the uninstall from
        private void batFileCreateStartProcess(string uninstallRegstring)
        {
            //Batch file name, which will be created in Window's temps foler
            string tempPathfile = Path.GetTempPath() + "cropmeuninstall.bat";

            if (!File.Exists(@tempPathfile))
            {
                using (FileStream createfile = File.Create(@tempPathfile))
                {
                    createfile.Close();
                }
            }

            using (StreamWriter writefile = new StreamWriter(@tempPathfile))
            {
                //Writes our uninstall value found earlier in batch file
                writefile.WriteLine(@"Start " + uninstallRegstring);
            }

            process = new Process();
            startInfo = new ProcessStartInfo();

            startInfo.FileName = tempPathfile;
            process.StartInfo = startInfo;
            process.Start();
            process.WaitForExit();

            File.Delete(tempPathfile); //Deletes the file

            removeClickOnceAuto();
        }

        // Automation of clicks in the uninstall to remove the
        // need of any user interactions
        private void removeClickOnceAuto()
        {
            IntPtr myWindowHandle = IntPtr.Zero;

            for (int i = 0; i < 60 && myWindowHandle == IntPtr.Zero; i++)
            {
                Thread.Sleep(1500);

                myWindowHandle = FindWindow(null, "Crop Me for OCA Maintenance");
            }

            if (myWindowHandle != IntPtr.Zero)
            {
                SetForegroundWindow(myWindowHandle);

                SendKeys.Send("+{TAB}"); // Shift + TAB
                SendKeys.Send("{ENTER}");
                SendKeys.Flush();
            }
        }
    }
}
2 голосов
/ 14 февраля 2011

Вы можете попробовать использовать Скрытый старт .

1 голос
/ 16 февраля 2011

Вы не можете отключить диалоговое окно удаления для приложения ClickOnce. Вы можете написать небольшое приложение .NET , чтобы удалить приложение ClickOnce и программно нажать кнопку в диалоговом окне, чтобы пользователь не предпринимал никаких действий. Это самое лучшее, что ты можешь сделать.

0 голосов
/ 23 марта 2012

Не усложняйте и сохраняйте это простым - это работает на обоих Windows XP & 7:

Перейдите на Add/Remove Programs и запишите точное название программы.Откройте Notepad и вставьте следующий текст:

wmic product, где name = "ИМЯ ПРОГРАММЫ". Удалите

, но обязательно введите точное имя программы вмежду кавычками и выберите Save As /All Files и назовите файл Uninstall.bat, а затем протестируйте его, чтобы убедиться, что он работает.

...