본문으로 건너뛰기

MS VC++ 재배포가능 패키지 존재여부 체크

보통 윈도 API를 쓰는 프로그램을 개발해서 배포를할 경우에 .. 적절한 시스템 DLL 이 존재하지 않으면 .. 프로그램이 그냥 죽어버립니다 ㅎㅎ 그래서 많은 프로그램들이 위와같은 .. 재배포가능 패키지를 같이 설치하곤 합니다만 ..

여튼간에 ;; 개발을 하다보면 시스템에 재배포가능 패키지가 존재하는지 안하는지를 ;; 버전 상관 없이 ..

한놈만 있음 되는 그런 상황이 오게 되지요 ..

레지스트리를 다 뒤져서 .. 찾거나 해야하는 문제라 ..

조금 많이 귀찮습니다 ㅋㅋ 

그리하야 ;; 모두의 프린터에서 사용중인 .. 코드를 몇줄 적어둡니다.

Go
package main

import (
	"fmt"
	"io"
	"path/filepath"
	"runtime"
	"strings"

	"golang.org/x/sys/windows/registry"
)

/
*	HasVcRedist
/
func HasVcRedist() bool {
	if fv,  := FindVCRedist(false); fv {
		return fv
	}
	if fv,  := FindVCRedist(true); fv {
		return fv
	}
	return false
}

/
*	GetSubKeyList
/
func GetUninstallSubKeys(isWow bool) ([]string, error) {
	var k registry.Key
	var err error

	if isWow {
		k, err = registry.OpenKey(registry.LOCAL_MACHINE, </span><span style="color: #A3BE8C">SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall</span><span style="color: #ECEFF4">, registry.ALL_ACCESS)
	} else {
		k, err = registry.OpenKey(registry.LOCAL_MACHINE, </span><span style="color: #A3BE8C">SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall</span><span style="color: #ECEFF4">, registry.ALL_ACCESS)
	}

	if err != nil {
		return nil, err
	}
	defer k.Close()

	names, namesErr := k.ReadSubKeyNames(512)

	if namesErr != nil {
		if namesErr != io.EOF {
			return nil, namesErr
		}
	}

	return names, nil
}

/
*
/
func GetUninstallDispalyName(isWow bool, subName string) string {
	var k registry.Key
	var err error

	if isWow {
		k, err = registry.OpenKey(registry.LOCAL_MACHINE, </span><span style="color: #A3BE8C">SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\</span><span style="color: #ECEFF4">+subName, registry.ALL_ACCESS)
	} else {
		k, err = registry.OpenKey(registry.LOCAL_MACHINE, </span><span style="color: #A3BE8C">SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\</span><span style="color: #ECEFF4">+subName, registry.ALL_ACCESS)
	}

	if err != nil {
		return ""
	}
	defer k.Close()

	dn, ,  := k.GetStringValue("DisplayName")
	return dn
}

/
*	FindVCRedist
/
func FindVCRedist(isWow bool) (bool, error) {
	sl, slErr := GetUninstallSubKeys(isWow)
	if slErr != nil {
		return false, slErr
	}

	for _, k := range sl {
		dn := GetUninstallDispalyName(isWow, k)

		if dn != "" {
			if strings.Contains(dn, "Microsoft Visual C++") && strings.Contains(dn, "Redistributable") {
				if runtime.GOARCH == "amd64" && strings.Contains(dn, "x64") {
					return true, nil
				} else if runtime.GOARCH == "386" && strings.Contains(dn, "x86") {
					return true, nil
				}
			}
		}
	}
	return false, nil
}

64비트 윈도가 나오면서 32비트 프로그램과 64비트 프로그램이 사용하는 레지스트리 경로가 좀 상황별로 다릅니다.. 흔히 WOW 라고 ㅎㅎ 하는 ㅎㅎ ;; 여튼간에 경우의수를 다 따지긴 매우 귀찮은 관계로 .. 

전통적인 경로와 WOW6432Node 에 해당하는 경로를 다 뒤져서 재배포가능 패키지가 단 하나라도 시스템에 설치되어 있는지를 확인해 줍니다.

HasVcRedist 함수가 true 를 리턴하면 재배포 패키지가 존재하는거고 false 를 리턴하면 .. 암것도 없는거니 설치를 하도록 유도하면 되겠습니다.