설치 서명에 사용 된 인증서가 만료 된 후 Visual Studio 2005 ClickOnce 응용 프로그램을 업데이트 하려고 하면 오류 메시지가 나타난다

증상

설치를 서명 하는 데 사용 된 인증서가 만료 된 후에 Microsoft Visual Studio 2005 ClickOnce 응용 프로그램을 업데이트 하려고 하면 다음과 같은 오류 메시지가 나타납니다.
배포 id는 구독을 일치 하지 않습니다.

원인

디지털 인증서를 사용 하 여 모든 ClickOnce 배포에 서명 해야 때문에이 문제가 발생 합니다. ClickOnce 응용 프로그램을 서명 하려면 만료 된 인증서를 사용할 수 없습니다. 만료 된 인증서가 응용 프로그램에 업데이트를 배포 하려면 응용 프로그램 새 인증서를 할당 해야 합니다. 새 인증서 원본 인증서와 일치 하지 않는 경우 "현상" 절에 나와 있는 오류 메시지가 나타납니다.

해결 방법

이 문제를 해결하려면, 다음 방법 중 하나를 사용합니다.

방법 1

ClickOnce 응용 프로그램은 Microsoft에 설치 되어 있는 클라이언트 컴퓨터를 업데이트 합니다..NET Framework 2.0 서비스 팩 1 (SP1) 또는 이후 버전.

Windows Vista

.NET Framework 3.5 또는.NET Framework 3.5 s P 1 적용 합니다.

참고: .NET Framework 3.5에는 3.0 및.NET Framework 2.0에 점진적으로 구축 하는 새로운 기능이 많이 포함 되어 있습니다. .NET Framework 3.5는.NET Framework 2.0 s p 1과.NET Framework 3.0 s p 1을 포함합니다.

다음 파일은 Microsoft 다운로드 센터에서 다운로드할 수 있습니다.

Download .NET Framework 3.5 패키지를 지금 다운로드 하십시오.

Download .NET Framework 3.5 서비스 팩 1 패키지를 지금 다운로드 하십시오.

Microsoft 지원 파일을 다운로드하는 방법에 대한 자세한 내용을 보려면 Microsoft 기술 자료의 다음 문서 번호를 클릭합니다.
119591 온라인 서비스 로부터 Microsoft 지원 파일을 구하는 방법
Microsoft는 이 파일에 대해 바이러스 검사를 시행하였습니다. Microsoft는 파일이 게시된 날짜에 사용할 수 있었던 최신 바이러스 검색 소프트웨어를 사용했습니다. 파일은 파일을 무단으로 변경할 수 없도록 보안이 강화된 서버에 저장됩니다.

Windows XP

.NET Framework 2.0 SP1 또는.NET Framework 2.0 서비스 팩 2 (SP2)를 적용 합니다.

다음 파일은 Microsoft 다운로드 센터에서 다운로드할 수 있습니다.

Download .NET Framework 2.0 서비스 팩 1 (x86) 패키지를 지금 다운로드 하십시오.

Download .NET Framework 2.0 서비스 팩 1 (x64) 패키지를 지금 다운로드 하십시오.

Download .NET Framework 2.0 서비스 팩 2 패키지를 지금 다운로드 하십시오.

Microsoft 지원 파일을 다운로드하는 방법에 대한 자세한 내용을 보려면 Microsoft 기술 자료의 다음 문서 번호를 클릭합니다.
119591 온라인 서비스 로부터 Microsoft 지원 파일을 구하는 방법
Microsoft는 이 파일에 대해 바이러스 검사를 시행하였습니다. Microsoft는 파일이 게시된 날짜에 사용할 수 있었던 최신 바이러스 검색 소프트웨어를 사용했습니다. 파일은 파일을 무단으로 변경할 수 없도록 보안이 강화된 서버에 저장됩니다.

방법 2

만료 된 인증서로 서명 된 ClickOnce 응용 프로그램을 제거 합니다. 그런 다음 새 인증서를 사용 하는 업데이트 된 ClickOnce 응용 프로그램을 다시 설치 하십시오.

방법 3

인증서를 업데이트 하는 명령줄 어셈블리를 만듭니다. 이렇게 하려면, 다음 단계를 수행하십시오.

Microsoft는 모든 보증, 그림에 대 한 묵시적인 보증. 이 포함 되지만 상품성 또는 특정 목적에의 적합성의 묵시적된 보증에 국한 되지는 않습니다. 이 문서는 작성 하 고 프로시저를 디버깅할 데 사용 되는 도구 및 여기서 설명 하는 프로그래밍 언어에 익숙한 가정 합니다. Microsoft 지원 엔지니어는 특정 프로시저의 기능을 설명할 수 있습니다. 그러나이 예제에서는 추가 기능을 제공 하거나 특정 요구 사항에 맞도록 프로시저를 구성 하려면 수정 하지 않습니다.
  1. Visual Studio 2005의 파일 메뉴에서 새로 만들기 를 클릭 한 다음 프로젝트를 클릭 합니다.

  2. Visual C++, Win32 콘솔 응용 프로그램, 이름 상자에 RenewCert 를 입력 한 다음 확인을 누릅니다.

  3. Win32 응용 프로그램 마법사 대화 상자에서 마침을 클릭 합니다.

  4. RenewCert.cpp 파일에서 기존 코드를 다음 코드로 바꿉니다.
    #include "stdafx.h"
    void ReadPFXFile(LPCWSTR fileName, CRYPT_DATA_BLOB *pPFX)

    {

    HANDLE hCertFile = NULL;

    DWORD cbRead = 0;

    DWORD dwFileSize = 0, dwFileSizeHi = 0;

    hCertFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

    dwFileSize = GetFileSize(hCertFile, &dwFileSizeHi);

    pPFX->pbData = (BYTE *) CryptMemAlloc(dwFileSize*sizeof(BYTE));

    pPFX->cbData = dwFileSize;

    ReadFile(hCertFile, pPFX->pbData, pPFX->cbData, &cbRead, NULL);

    CloseHandle(hCertFile);

    }

    void GetPrivateKey(CRYPT_DATA_BLOB pPFX, LPCWSTR szPassword, HCRYPTPROV *hCPContext)

    {

    HCERTSTORE hCertStore = NULL;

    PCCERT_CONTEXT hCertContext = NULL;

    DWORD dwKeySpec = AT_SIGNATURE;

    BOOL bFreeCertKey = TRUE;

    hCertStore = PFXImportCertStore(&pPFX, szPassword, CRYPT_EXPORTABLE);

    hCertContext = CertEnumCertificatesInStore(hCertStore, NULL);

    CryptAcquireCertificatePrivateKey(hCertContext, 0, NULL, hCPContext, &dwKeySpec, &bFreeCertKey);

    CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);

    }

    void PrintContainerName(HCRYPTPROV hCPContext)

    {

    DWORD containerNameLen = 0;

    CHAR *szContainerName = NULL;

    CryptGetProvParam(hCPContext, PP_CONTAINER, NULL, &containerNameLen, 0);

    szContainerName = (CHAR *)CryptMemAlloc(sizeof(BYTE)*containerNameLen);

    CryptGetProvParam(hCPContext, PP_CONTAINER, (BYTE *)szContainerName, &containerNameLen, 0);

    printf("This certificate's container name is: %s", szContainerName);

    }

    void MakeNewCert(HCRYPTPROV hCPContext, LPCWSTR szCertName, LPCWSTR szPassword, CRYPT_DATA_BLOB *pPFX)

    {

    CERT_NAME_BLOB certNameBlob = {0,NULL};

    PCCERT_CONTEXT hCertContext = NULL;

    SYSTEMTIME certExpireDate;

    HCERTSTORE hTempStore = NULL;

    CertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szCertName, CERT_OID_NAME_STR, NULL, NULL, &certNameBlob.cbData, NULL);

    certNameBlob.pbData = (BYTE *)CryptMemAlloc(sizeof(BYTE)*certNameBlob.cbData);

    CertStrToName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szCertName, CERT_OID_NAME_STR, NULL, certNameBlob.pbData, &certNameBlob.cbData, NULL);

    GetSystemTime(&certExpireDate);

    certExpireDate.wYear += 5;

    hCertContext = CertCreateSelfSignCertificate(hCPContext, &certNameBlob, 0, NULL, NULL, NULL, &certExpireDate, NULL);

    hTempStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, 0);

    CertAddCertificateContextToStore(hTempStore, hCertContext, CERT_STORE_ADD_NEW, NULL);

    PFXExportCertStoreEx(hTempStore, pPFX, szPassword, NULL, EXPORT_PRIVATE_KEYS);

    pPFX->pbData = (BYTE *)CryptMemAlloc(sizeof(BYTE)*pPFX->cbData);

    PFXExportCertStoreEx(hTempStore, pPFX, szPassword, NULL, EXPORT_PRIVATE_KEYS);

    CryptMemFree(certNameBlob.pbData);

    CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG);

    CertFreeCertificateContext(hCertContext);

    }

    void WritePFX(CRYPT_DATA_BLOB pPFX, LPCWSTR szOutputFile)

    {

    HANDLE hOutputFile = NULL;

    DWORD cbWritten = 0;

    hOutputFile = CreateFile(szOutputFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

    WriteFile(hOutputFile, pPFX.pbData, pPFX.cbData, &cbWritten, NULL);

    CloseHandle(hOutputFile);

    }

    int _tmain(int argc, _TCHAR* argv[])

    {

    LPCWSTR szCertFileName = NULL;

    CRYPT_DATA_BLOB pPFX;

    LPCWSTR szPassword = NULL;

    HCRYPTPROV hCPContext = NULL;

    LPCWSTR szCertName = L"CN=NewCert";

    CRYPT_DATA_BLOB pPfxOutputBlob = {0,NULL};

    LPCWSTR szOutFile = NULL;

    // Parse the command line.

    if(argc == 1)

    {

    printf("renewcert <PFX File> <new cert filename> <new cert friendly name> [optional]<password>\n");

    printf("Example: renewcert oldcert.pfx newcert.pfx \"CN=MyNewCert\" MySuperSecretPassword");

    return 0;

    }

    if(argc >= 2)

    szCertFileName = argv[1];

    if(argc >= 5)

    szPassword = argv[4];

    // Uncomment this block to add <new cert filename> and <new cert friendly name> as parameters

    // NOTE: <new cert friendly name> must be of format "CN=<name>"

    if(argc >= 3)

    szOutFile = argv[2];

    if(argc >= 4)

    szCertName = argv[3];

    ReadPFXFile(szCertFileName, &pPFX);

    GetPrivateKey(pPFX, szPassword, &hCPContext);

    //PrintContainerName(hCPContext);

    // Uncomment this section to make a new PFX rather than just printing the container name.

    // Make sure you also uncomment the command line parameter section above.

    MakeNewCert(hCPContext, szCertName, szPassword, &pPfxOutputBlob);

    WritePFX(pPfxOutputBlob, szOutFile);

    // Clean up.

    CryptReleaseContext(hCPContext, 0);

    CryptMemFree(pPfxOutputBlob.pbData);

    CryptMemFree(pPFX.pbData);

    return 0;

    }

  5. Stdafx.h 파일에서 기존 코드를 다음 코드로 바꿉니다.
    // stdafx.h : include file for standard system include files,
    // or project specific include files that are used frequently, but

    // are changed infrequently.

    //

    #pragma once

    #define WIN32_LEAN_AND_MEAN // Exclude rarely used material from Windows headers.

    #include <stdio.h>

    #include <tchar.h>

    #include <windows.h>

    #include <wincrypt.h>

  6. 프로젝트 메뉴에서이 프로젝트에 대 한 속성 페이지를 열려면 속성 클릭 합니다.
  7. 링커 노드를 확장 한 다음 입력을 클릭 합니다.
  8. 추가 종속성, 오른쪽의 빈 창을 누르고 (...) 종속성 추가 대화 상자를 열려면 줄임표 단추를 클릭 합니다.
  9. 새 창에서 Crypt32.lib입력 하 고 확인을 클릭 합니다.
  10. 적용을 클릭 하 고 속성 페이지를 닫으려면 확인 클릭 합니다.
  11. 빌드 메뉴에서 솔루션 빌드를 클릭 합니다.

  12. 솔루션 빌드 후에 인증서를 업데이트 하려면 다음 명령을 실행 합니다.
    renewcert <OldCertificate>.pfx <NewCertificate>.pfx \"CN=<NewCertificateName>\" <Password>
    참고: < OldCertificate > 은 이전 인증서 자리 표시자 < NewCertificate > 새 인증서에 대 한 자리 표시자는 < NewCertificateName > 새 인증서의 이름에 대 한 자리 표시자입니다 및 < 암호 > 암호 자리 표시자입니다.

자세한 내용

이 문제를 재현 하는

  1. Visual Studio 2005를 시작 합니다.
  2. 파일메뉴에서 새로 만들기클릭 한 다음 프로젝트를 클릭 합니다.
  3. C#, Windows 응용 프로그램, WindowsApplication1 에 입력 하면
    이름 을 입력 한 다음 확인을 클릭 합니다.
  4. 솔루션 탐색기에서 WindowsApplication1마우스 오른쪽 단추로 클릭 한 다음 속성을 클릭 합니다.
  5. 서명클릭 한 다음 곧 만료 될 인증서를 할당 합니다.
  6. 솔루션 탐색기에서 WindowsApplication1마우스 오른쪽 단추로 클릭 한 다음 게시를 클릭 합니다. 게시 마법사가 시작 됩니다.
  7. 응용 프로그램을 게시 하는 데 사용할 위치? 페이지 유효한 URL을 입력 하 고 다음을 클릭 합니다. URL은 다음 형식을 사용 하십시오.
    http://ServerName/FolderName
  8. 응용 프로그램을 오프 라인으로 사용할 수 있습니까? 페이지에서 적절 한 옵션을 클릭 합니다.

    참고
    • 사용자가 네트워크 연결이 끊어졌을 때 응용 프로그램을 실행할 수 있도록 하려면 예,이 응용 프로그램은 온라인 또는 오프 라인으로 사용할 수를 클릭 합니다. 마법사는 시작 메뉴에서 응용 프로그램에 대 한 바로 가기를 만듭니다.
    • 응용 프로그램을 게시 위치에서 직접 실행 하려면 아니요,이 응용 프로그램은 온라인 으로만 사용할 수를 클릭 합니다. 마법사는 시작 메뉴 바로 가기를 만들지 않습니다.
  9. 다음 을 클릭 합니다.
  10. 응용 프로그램을 게시 하려면 마침 을 클릭 합니다.
  11. Http://ServerName에서 ClickOnce 응용 프로그램을 설치 /FolderName/publish.htm URL입니다.
  12. 인증서가 만료 된 후 응용 프로그램을 다시 게시 하려면 6-10 단계를 반복 합니다.
  13. Http://ServerName에서 ClickOnce 응용 프로그램 업데이트를 설치 하려고 /FolderName/publish.htm URL입니다.
속성

문서 ID: 925521 - 마지막 검토: 2017. 2. 7. - 수정: 1

피드백