func (vi *VersionInfo) SetProductVersionString(s string) error {
	v, err := common.ParseVersionString(s)
	if err != nil {
		return errors.Wrap(err, "failed to parse version string")
	}
	vi.fixedFileInfo.productVersion = v
	return nil
}
SetProductVersionString sets product version in string, returns error
if s is not in a form "Major.Minor.Patch.Build".
package versioninfo
import (
	"encoding/binary"
	"fmt"
	"io"
	"unicode/utf16"
	"github.com/hallazzang/syso/pkg/common"
	"github.com/pkg/errors"
)
type VersionInfo struct {
	length         uint16
	valueLength    uint16
	fixedFileInfo  fixedFileInfo  
	stringFileInfo *stringFileInfo
	varFileInfo    *varFileInfo
}
type rawVersionInfo struct {
	Length      uint16
	ValueLength uint16
	Type        uint16
	Key         [16]uint16
	Padding     [2]byte
	Value       rawFixedFileInfo
}
func New() *VersionInfo {
	return &VersionInfo{
		fixedFileInfo: fixedFileInfo{
			fileFlagsMask: 0x0000003f,  
			fileOS:        0x00040004,
			fileType:      0x00000001,
		},
	}
}
func (vi *VersionInfo) freeze() {
	if vi.stringFileInfo != nil {
		vi.stringFileInfo.freeze()
	}
	if vi.varFileInfo != nil {
		vi.varFileInfo.freeze()
	}
	vi.valueLength = uint16(binary.Size(rawFixedFileInfo{}))
	vi.length = uint16(binary.Size(rawVersionInfo{}))
	if vi.stringFileInfo != nil {
		vi.length += vi.stringFileInfo.length
	}
	vi.length += paddingLength(vi.length)
	if vi.varFileInfo != nil {
		vi.length += vi.varFileInfo.length
	}
}
func (vi *VersionInfo) WriteTo(w io.Writer) (int64, error) {
	vi.freeze()
	written, err := common.BinaryWriteTo(w, rawVersionInfo{
		Length:      vi.length,
		ValueLength: vi.valueLength,
		Type:        0,
		Key:         [16]uint16{0x56, 0x53, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x00},  
		Value: rawFixedFileInfo{
			Signature:        0xFEEF04BD,
			StrucVersion:     0x00010000,  
			FileVersionMS:    uint32(vi.fixedFileInfo.fileVersion >> 32),
			FileVersionLS:    uint32(vi.fixedFileInfo.fileVersion & 0xffffffff),
			ProductVersionMS: uint32(vi.fixedFileInfo.productVersion >> 32),
			ProductVersionLS: uint32(vi.fixedFileInfo.productVersion & 0xffffffff),
			FileFlagsMask:    vi.fixedFileInfo.fileFlagsMask,
			FileFlags:        vi.fixedFileInfo.fileFlags,
			FileOS:           vi.fixedFileInfo.fileOS,
			FileType:         vi.fixedFileInfo.fileType,
			FileSubtype:      vi.fixedFileInfo.fileSubtype,
			FileDateMS:       uint32(vi.fixedFileInfo.fileDate >> 32),
			FileDateLS:       uint32(vi.fixedFileInfo.fileDate & 0xffffffff),
		},
	})
	if err != nil {
		return written, err
	}
	if vi.stringFileInfo != nil {
		n, err := vi.stringFileInfo.WriteTo(w)
		if err != nil {
			return written, err
		}
		written += n
	}
	if padding := paddingLength(uint16(written)); padding > 0 {  
		n, err := common.WritePaddingTo(w, int(padding))
		if err != nil {
			return written, err
		}
		written += n
	}
	if vi.varFileInfo != nil {
		n, err := vi.varFileInfo.WriteTo(w)
		if err != nil {
			return written, err
		}
		written += n
	}
	return written, nil
}
func (vi *VersionInfo) FileVersion() uint64 {
	return vi.fixedFileInfo.fileVersion
}
func (vi *VersionInfo) FileVersionString() string {
	return common.FormatVersionString(vi.fixedFileInfo.fileVersion)
}
func (vi *VersionInfo) SetFileVersion(v uint64) {
	vi.fixedFileInfo.fileVersion = v
}
func (vi *VersionInfo) SetFileVersionString(s string) error {
	v, err := common.ParseVersionString(s)
	if err != nil {
		return errors.Wrap(err, "failed to parse version string")
	}
	vi.fixedFileInfo.fileVersion = v
	return nil
}
func (vi *VersionInfo) ProductVersion() uint64 {
	return vi.fixedFileInfo.productVersion
}
func (vi *VersionInfo) ProductVersionString() string {
	return common.FormatVersionString(vi.fixedFileInfo.productVersion)
}
func (vi *VersionInfo) SetProductVersion(v uint64) {
	vi.fixedFileInfo.productVersion = v
}