반응형

기존에 ClickOnce로 배포했던 앱을 여러 이유로 새로운 명칭과 설치 URL 변경 등으로 새로 만들어서 배포를 할 경우, 기존 ClickOnce 앱의 삭제를 사용자에게 맡길 것인가 아니면 자동으로 삭제하고 설치도 자동으로 하고 싶을 경우 어떻게 하면 될까?

여러가지 방법이 있을 수 있다. 

기존 ClickOnce 배포 앱을 삭제하기 위한 스크립트를 만들어서 스크립트 실행을 통해서 삭제 또는 설치할 수가 있다.

이럴경우 스크립트 파일(WScript)의 디버깅이나 제어가 여러가지로 불편할 수가 있고, 편집기로 쉽게 스크립트 내용을 볼 수 있는 단점이 있다.

스크립트 파일로 삭제/설치도 좋지만 요즘 보안이다 뭐다 해서 주요 정보들을 스크립트로 제공하는 것도 문제가 될 수 있다.

아래는 이러한 문제를 개선한 실행 앱(exe)을 통해서 기존의 ClickOnce 앱을 삭제하고 설치하는 소스이다.

public class ClickOnceRemoveInstall
    {        
        public static void Main(string[] args)
        {
            //CMD 창을 숨긴다.
            var handle = GetConsoleWindow();
            ShowWindow(handle, SW_HIDE); // 숨기기

            //활성화된 ClickOnce App. Kill            
            Process.Start("taskkill", "/F /IM ClickOnce앱명칭*");
            Process killProc = Process.GetProcessesByName("taskkill").FirstOrDefault();
            killProc.WaitForExit();
            killProc.Close();
            
            //기존 설치된 ClickOnce App. 제거
            string app = "dfshim.dll,ShArpMaintain ClickOnceAppName.application, Culture=neutral, PublicKeyToken=e5ccc1554e61cee3, processorArchitecture=x86";
            Process.Start("rundll32.exe", app);
            Process removeProc = Process.GetProcessesByName("dfsvc").FirstOrDefault();
            System.Threading.Thread.Sleep(3500); //제거 창이 뜰때까지 잠깐 대기
            if (removeProc != null)
            {
                IntPtr h = removeProc.MainWindowHandle;               
                SetForegroundWindow(h);                
                SendKeys.SendWait("O"); //제거 창에서 확인 버튼 클릭을 위해 Key 입력
                removeProc.Close();                
            }
            
            System.Threading.Thread.Sleep(500);
            
            //새로운 ClickOnce App. 설치
            string appUrl = "http://ClickOnce배포서버명 또는 접속URL/ClickOnceAppName.application";
            Process.Start("rundll32.exe", "dfshim.dll,ShOpenVerbApplication " + appUrl);
            Process installProc = Process.GetProcessesByName("dfsvc").FirstOrDefault();
            System.Threading.Thread.Sleep(2500); //설치 창이 뜰때까지 잠깐 대기
            if (installProc != null)
            {
                IntPtr h = installProc.MainWindowHandle;                
                SetForegroundWindow(h);                                
                SendKeys.SendWait("I"); //설치 창에서 설치 버튼 클릭을 위해 Key 입력               
                installProc.Close();
            }            
        }
        
        [DllImport("User32.dll")]
        static extern int SetForegroundWindow(IntPtr point);
        
        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        const int SW_HIDE = 0; // 숨기기
        const int SW_SHOW = 1; // 보이기
    }

 

반응형

+ Recent posts