Microsoft MVP성태의 닷넷 이야기
C#으로 만든 DLL 배포하기 [링크 복사], [링크+제목 복사],
조회: 20807
글쓴 사람
cab2da (cab2da at naver.com)
홈페이지
첨부 파일
 

안녕하세요?

질문이 있어 글 남깁니다.

목적 :
 C#을 이용해 만든 dll 을
 EXCEL 에서 사용할려고 합니다.

수작업으로 아래와 같이 실행해 주면 사용이 가능해 집니다.
  1. 해당 dll 파일을 사용자의 컴퓨터에 저장
  2. RegAsm.exe 파일이 있는 경로에서 명령프롬프트 실행(관리자 권한으로)
  3. 아래 명령문 실행
     C:\Program Files (x86)\...path...\Tools>RegAsm /codebase C:\DLL\ExcelTest.dll

수작업으로 배포하는 부분을 자동화하고 싶습니다.
즉 C#으로 프로젝트를 만들어서 사용자의 컴퓨터에서 setup.exe를 실행하면 dll 을 사용할 수 있게 하고 싶습니다.

감사합니다

-----------------------------------------------------------------------------------
ExcelTest.dll 은 Resources 폴더에 추가한 상태고 빌드 작업을 [포함 리소스]로 설정한 상태입니다.

ExcelTest.dll 소스코드
namespace ExcelTest
{
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class CSharpTools
    {
        [ComVisible(true)]
        public string AddBrackets(string value)
        {
            return "[" + value + "]";
        }

    }
}

DLL 배포하기 위해 작업한 소스 코드
using System;
using System.Diagnostics;
using System.IO;
using System.Security.Principal;
using System.Windows.Forms;

namespace RegisterTest
{
    static class Program
    {
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main()
        {
            //ClickOnce - 관리자 권한 상승하는 방법
            //출처 : https://www.sysnet.pe.kr/2/0/950
            if (IsAdministrator() == false)
            {
                try
                {
                    ProcessStartInfo procInfo = new ProcessStartInfo();
                    procInfo.UseShellExecute = true;
                    procInfo.FileName = Application.ExecutablePath;
                    procInfo.WorkingDirectory = Environment.CurrentDirectory;
                    procInfo.Verb = "runas";
                    Process.Start(procInfo);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message.ToString());
                }

                return;
            }

            // 컴파일 배포시 단이 exe 로 배포하고 , 참조하는 dll은 리소스 파일에 추가하여 (참조리소스)
            // 단일 실행파일로 만들어 배포함.
            // 프로그램은 실행시 참조 dll 파일을 생성하고 리소스 파일에 있는 원 파일을 읽어서 대체함.
            string strDllPath = "";
            string strFullFileName = "";
            try
            {
                strDllPath = Application.ExecutablePath.Replace("/", "\\");
                int intPos = strDllPath.LastIndexOf("\\");
                if (intPos >= 1)
                    strDllPath = strDllPath.Substring(0, intPos).Trim('\\');

                strFullFileName = strDllPath + "\\ExcelTest.dll";
                FileInfo fileinfo = new FileInfo(strFullFileName);
                if (fileinfo.Exists == false)
                {
                    byte[] aryData = Resource1.ExcelTest; //리소드 디자인에 저장한 이름
                    FileStream fileStream = new FileStream(fileinfo.FullName, FileMode.CreateNew);
                    fileStream.Write(aryData, 0, aryData.Length);
                    fileStream.Close();
                }
                // 출처: https://lovelypang.tistory.com/73 [코코몽과 토토몽]
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }

            // dll 파일 레지스트리에 등록하기
            // 출처: https://developer-joe.tistory.com/148
            try
            {
                Console.WriteLine("This program is registering .TLB to Windows registry.");

                var proc = new ProcessStartInfo();

                // .dll을 이용해서 .tlb생성 및 레지스트리 등록 명령어
                // regasm의 사용법은 DOS창(커맨더 창)에서 regasm /?을 하면
                // regasm을 아래와같이 이 파일의 경로를 표시하지 않으면 현재의 프로그램의 실행 파일과 같은 위치에
                // regasm.exe가 있어야 된다.
                //string mCmd = "regasm ExcelTest.dll /tlb:ExcelTest.tlb";
                string mCmd = "regasm ExcelTest.dll /tlb:ExcelTest.tlb";
                proc.UseShellExecute = true;

                //아래 경로에 .DLL가 있어야하고 .tlb가 이 위치에 생성이 되고 regasm.exe도 이 위치에서
                //작업을 하게된다.
                proc.WorkingDirectory = @strDllPath;

                //위의 regasm EthernetClientLib.dll /tlb:EthernetClientLib.tlb를 실행시킬 명령어
                proc.FileName = "cmd.exe";

                //아래 속성의 runas 자체가 관리자 권한으로 실행시키겠다는 설정값이다.
                proc.Verb = "runas";
                proc.Arguments = "/C " + mCmd;
                proc.WindowStyle = ProcessWindowStyle.Hidden;
                Process rt = Process.Start(proc);

                Debug.WriteLine("##### .tlb 생성 및 레지스트리 등록을 마쳤습니다.");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
        }

        public static bool IsAdministrator()
        {
            WindowsIdentity identity = WindowsIdentity.GetCurrent();

            if (null != identity)
            {
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }

            return false;
        }

    }
}

-----------------------------------------------------------------------------------
참고한 사이트
C# 코드상에서 .tlb 생성 및 레지스트리 등록하는 법
https://developer-joe.tistory.com/148

regasm.exe로 어셈블리 등록 시 시스템 변경 사항 (1) - .NET 2.0 + x86/x64/AnyCPU
; https://www.sysnet.pe.kr/2/0/1286
 
regasm.exe로 어셈블리 등록 시 시스템 변경 사항 (2) - .NET 4.0 + .NET 2.0
; https://www.sysnet.pe.kr/2/0/1287

regasm.exe로 어셈블리 등록 시 시스템 변경 사항 (3) - Type Library
; https://www.sysnet.pe.kr/2/0/1288








[최초 등록일: ]
[최종 수정일: 4/9/2019]


비밀번호

댓글 작성자
 



2019-04-09 07시38분
수작업 1~3단계를 잘 구현하신 것 같은데... 어떤 문제가 있는 건가요?
정성태
2019-04-10 10시41분
[cab2da] 수작업으로 하면 사용자 컴퓨터에서 dll을 정상적으로 사용을 할 수 있는데
setup.exe를 이용해 실행하면 오류는 발생하지 않는데
dll 을 인식하지 못해 사용할 수 없습니다.
엑셀 VBA 편집기에서 참조를 눌러보면
수작업으로 배포한 컴퓨터에선 ExcelTest가 보이고
자동 배포한 컴퓨터에선 보이지 않습니다.

[guest]
2019-04-11 11시37분
이런 경우에는 원칙을 생각하시면 됩니다. 딱히 수작업이나 코드로 하는 거나 다를 바가 없기 때문에 안 된다는 것은 어딘가 오류가 있다는 것입니다. 따라서, 1) 파일이 로컬에 있는지 확인하고 2) regasm으로 인한 등록이 레지스트리에 잘 되었는지 확인하면 됩니다. 그냥 보면 regasm 과정 중에 오류가 있을 듯한데, 어쨌든 중요한 것은 코드로 했다고 달라질 만한 작업은 아닙니다.
정성태
2019-04-11 12시10분
[cab2da] 안녕하세요?

setup 파일을 실행하면 dll 파일도 포함되는지 궁금하여
strDllPath 에 있는 경로로 가보니 해당 파일이 있었습니다.
(숨긴 항목도 보이게 하니 AppData 폴더의 하위 폴더에 있더군요)

레지스트로에 잘 되었는지는 확인하는 방법을 찾아셔 확인해 보겠습니다.

아무래도 regasm.exe를 찾아서 해당 경로에서 실행하는 것으로 해야 할 듯 합니다.
(오류가 발생하지 않고 등록을 마쳤다고 하니...)

감사합니다

[guest]
2019-04-11 01시33분
그런데... 설마 "Debug.WriteLine("##### .tlb 생성 및 레지스트리 등록을 마쳤습니다.");" 코드가 수행되었다고 해서 regasm이 성공했다고 생각하는 건 아니죠?
정성태
2019-04-15 02시39분
[cab2da] 코드 중 일부를 아래처럼 수정하고
레지스트리 편집기에서
[EXCELTEST]를 찾기했는데...
찾지를 못하는군요.
무엇인가를 놓치고 있는 듯 합니다

string mCmd = @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe /codebase " + strFullFileName;


[guest]
2019-04-15 02시54분
FileName부터 cmd.exe를 주었는데 왜 그런 식으로 한 거죠?

이런 경우, FileName = "regasm.exe"로 하고 Arguments에 "/codebase …[dll_path]…"로 설정해야 합니다.

그리고 정상적으로 명령어가 실행되었는지 proc.StandardOutput을 이용해 확인하세요.
정성태
2019-04-16 10시47분
[cab2da] 안녕하세요?

아래의 코드로 테스트 해 보니
proc.StandardOutputEncoding 이 null로 나오는군요.

검토해 주셔서 감사합니다.

try
{
    ProcessStartInfo proc = new ProcessStartInfo();
    proc.UseShellExecute = true;
    proc.FileName = "RegAsm.exe";
    proc.WorkingDirectory = @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\";
    proc.Verb = "runas";
    proc.Arguments = "/codebase " + strFullFileName;
    proc.WindowStyle = ProcessWindowStyle.Hidden;
    Process.Start(proc);

    string result = "";
    if (proc.StandardOutputEncoding != null)
        result = proc.StandardOutputEncoding.ToString();
    else
        result = "null";
    MessageBox.Show(result);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message.ToString());
}
[guest]
2019-04-16 04시22분
아래의 글을 참고하세요.

Process.Start로 실행한 콘솔 프로그램의 출력 결과를 얻는 방법
; http://www.sysnet.pe.kr/2/0/11870

정성태
2019-04-18 03시51분
[cab2da] 아래처럼 구문을 수정하고 실행하니 catch 부분에서 메세지박스가 출력되네요.
오류 : 지정된 파일을 찾을 수 없다

아마도
Process proc = Process.Start(psi);
이 구문에서 오류가 발생하는 듯 합니다.

소중한 시간 할애하여 검토해 주셔서 감사합니다.


----------------------------------------------------------
try
{
    ProcessStartInfo psi = new ProcessStartInfo();
    psi.FileName = "RegAsm.exe";
    psi.WorkingDirectory = @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\";
    psi.Verb = "runas";
    psi.Arguments = "/codebase " + strFullFileName;
    psi.WindowStyle = ProcessWindowStyle.Hidden;
    psi.RedirectStandardOutput = true;
    psi.UseShellExecute = false;

    MessageBox.Show("시작" + strFullFileName);

    Process proc = Process.Start(psi);
    string txt = proc.StandardOutput.ReadToEnd();

    MessageBox.Show(txt);
}
catch (Exception ex)
{
    MessageBox.Show("오류 : " + ex.Message.ToString());
}

----------------------------------------------------------

[guest]

... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
852임동찬1/6/201015441base.OnStart(agrs) [1]
851한귀순1/6/201020902oracle & transaction 질문 [5]
850박한주12/31/200918089COM과 C#간 권한 문제에 관해 여쭤봅니다. [5]
848날쌘돌이12/22/200918953C#으로 개발하는 ActiveX 디버깅 문제 [5]
847최승문12/16/200917836winform에서 웹서비스를 이용할때, 객체가 전송안되는 문제... [2]
846이강구12/14/200916775ATL COM 제작 문의 [3]
845김재영12/9/200919607ClickOnce에서 WinForm을 배포시 변동되는 Args값을 넘길 수 있나요? [3]파일 다운로드1
843김재영12/2/200917123Hyper-V 사용에 대해여 질문이 있습니다. [2]
842한귀순12/1/200919963Attempted to read or write protected memory [2]
841장근배11/30/200921547첨부 파일 Download시 한글 Name [2]
844장근배12/3/200916108    답변글 [답변]: 첨부 파일 Download시 한글 Name파일 다운로드1
840박영민11/20/200915940웹 애플리케이션 질문입니다. [1]
837left...10/21/200916807아래 게시글 관련하여 추가 질문 [3]
836left...10/19/200917807ActiveX 상에서 암시적 dll 로드 [1]
832김우진10/15/200914498C# 에서 swa + security 구현 방법이 없을까요?
833정성태10/15/200918587    답변글 [답변]: C#에서 swa + security 구현 방법이 없을까요? [1]
834김우진10/15/200914608        답변글 예제 메시지 올려드릴께요. [2]파일 다운로드1
838이영우10/30/200914514            답변글 국세청 전자세금계선서에 관하여 문의드립니다.
831채승수10/13/200916800스마트 클라이언트 GAC 등록 문제 여쭤봅니다... [2]
829박찬용10/9/200929288WebBrowser 컨트롤 사용시 새창을 띄울시 세션/쿠키 공유가 왜 안될까요?? [1]파일 다운로드1
827송창훈9/24/200914325[질문]CAS 설정
828정성태9/28/200917671    답변글 [답변]: [질문]CAS 설정 [1]
825김재영9/18/200915253프레임워크별 비트 지원에 대해서 문의를 드립니다. [2]
821채승수8/27/200914713클릭원스를 비스타에서 실행시 [1]
822채승수8/28/200919612    답변글 [답변]: 클릭원스를 비스타에서 실행시 [2]
818개발돌이8/14/200917261ActiveX개발한 dll을 임베디드 할때 UI에 대한 질문 [1]파일 다운로드1
... 61  62  63  64  65  66  67  68  [69]  70  71  72  73  74  75  ...