Skip to content

Instantly share code, notes, and snippets.

@default-writer
Created June 16, 2022 09:29
Show Gist options
  • Save default-writer/8fca24db8f767afc56b671042593ac03 to your computer and use it in GitHub Desktop.
Save default-writer/8fca24db8f767afc56b671042593ac03 to your computer and use it in GitHub Desktop.
read/write Windows file attributes in build pipeline
import argparse
import os
import pandas as pd
import win32api
import json
import sys
from jsondiff import diff
#==============================================================================
def getFileProperties(fname):
#==============================================================================
"""
Read all properties of the given file return them as a dictionary.
"""
propNames = ('Comments', 'InternalName', 'ProductName',
'CompanyName', 'LegalCopyright', 'ProductVersion',
'FileDescription', 'LegalTrademarks', 'PrivateBuild',
'FileVersion', 'OriginalFilename', 'SpecialBuild')
props = {}
try:
# backslash as parm returns dictionary of numeric info corresponding to VS_FIXEDFILEINFO struc
fixedInfo = win32api.GetFileVersionInfo(file, '\\')
# props['FixedFileInfo'] = fixedInfo
if 'FileVersionMS' in fixedInfo and 'FileVersionLS' in fixedInfo:
props['FileVersion'] = "%d.%d.%d.%d" % (fixedInfo['FileVersionMS'] / 65536,
fixedInfo['FileVersionMS'] % 65536, fixedInfo['FileVersionLS'] / 65536,
fixedInfo['FileVersionLS'] % 65536)
if 'ProductVersionMS' in fixedInfo and 'ProductVersionLS' in fixedInfo:
props['ProductVersion'] = "%d.%d.%d.%d" % (fixedInfo['ProductVersionMS'] / 65536,
fixedInfo['ProductVersionMS'] % 65536, fixedInfo['ProductVersionLS'] / 65536,
fixedInfo['ProductVersionLS'] % 65536)
# \VarFileInfo\Translation returns list of available (language, codepage)
# pairs that can be used to retreive string info. We are using only the first pair.
lang, codepage = win32api.GetFileVersionInfo(file, '\\VarFileInfo\\Translation')[0]
# any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle
# two are language/codepage pair returned from above
for propName in propNames:
strInfoPath = u'\\StringFileInfo\\%04X%04X\\%s' % (lang, codepage, propName)
## print str_info
props[propName] = win32api.GetFileVersionInfo(file, strInfoPath)
except Exception:
pass
return props
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='shell runner')
parser.add_argument("-c", "--config", action="store", dest="config_file", default="config.yaml", help="Path to config file")
args = parser.parse_args()
config_file = args.config_file
print(config_file)
try:
directory = os.path.abspath(os.path.join('.','build'))
known_extensions = [".dll",".ocx"]
files_info = {}
for path, subdirs, files in os.walk(directory):
for name in files:
file = os.path.join(path, name)
for ext in known_extensions:
if file.endswith(ext):
id = file[len(directory)+len(os.path.sep):] if directory in path else file
props = getFileProperties(file)
props["FileName"] = name
files_info[id]=props
js_data = json.dumps(files_info, indent=4, sort_keys=True)
with open('deployment.json', 'w+') as f:
f.write(js_data)
with open('versions.json', 'r') as f:
versions_data = json.loads(f.read())
diff_json = json.loads(diff(files_info, versions_data, syntax='explicit', dump=True))
with open('diff.json', 'w+') as f:
f.write(json.dumps(diff_json, indent=4, sort_keys=True))
df_json = pd.read_json('diff.json')
df = df_json.transpose()
df.to_excel('diff.xlsx')
if len(diff_json) > 0:
raise ValueError
except Exception as ex:
print("ERROR")
sys.exit(1)
print("SUCCESS")
sys.exit(0)
import os
import pandas as pd
import win32api
import json
import sys
#==============================================================================
def getFileProperties(fname):
#==============================================================================
"""
Read all properties of the given file return them as a dictionary.
"""
propNames = ('Comments', 'InternalName', 'ProductName',
'CompanyName', 'LegalCopyright', 'ProductVersion',
'FileDescription', 'LegalTrademarks', 'PrivateBuild',
'FileVersion', 'OriginalFilename', 'SpecialBuild')
props = {}
try:
# backslash as parm returns dictionary of numeric info corresponding to VS_FIXEDFILEINFO struc
fixedInfo = win32api.GetFileVersionInfo(file, '\\')
# props['FixedFileInfo'] = fixedInfo
if 'FileVersionMS' in fixedInfo and 'FileVersionLS' in fixedInfo:
props['FileVersion'] = "%d.%d.%d.%d" % (fixedInfo['FileVersionMS'] / 65536,
fixedInfo['FileVersionMS'] % 65536, fixedInfo['FileVersionLS'] / 65536,
fixedInfo['FileVersionLS'] % 65536)
if 'ProductVersionMS' in fixedInfo and 'ProductVersionLS' in fixedInfo:
props['ProductVersion'] = "%d.%d.%d.%d" % (fixedInfo['ProductVersionMS'] / 65536,
fixedInfo['ProductVersionMS'] % 65536, fixedInfo['ProductVersionLS'] / 65536,
fixedInfo['ProductVersionLS'] % 65536)
# \VarFileInfo\Translation returns list of available (language, codepage)
# pairs that can be used to retreive string info. We are using only the first pair.
lang, codepage = win32api.GetFileVersionInfo(file, '\\VarFileInfo\\Translation')[0]
# any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle
# two are language/codepage pair returned from above
for propName in propNames:
strInfoPath = u'\\StringFileInfo\\%04X%04X\\%s' % (lang, codepage, propName)
## print str_info
props[propName] = win32api.GetFileVersionInfo(file, strInfoPath)
except Exception:
pass
return props
if __name__ == '__main__':
directory = os.path.abspath(os.path.join('.','build'))
known_extensions = [".dll",".ocx"]
files_info = {}
for path, subdirs, files in os.walk(directory):
for name in files:
file = os.path.join(path, name)
for ext in known_extensions:
if file.endswith(ext):
id = file[len(directory)+len(os.path.sep):] if directory in path else file
props = getFileProperties(file)
props["FileName"] = name
files_info[id]=props
js_data = json.dumps(files_info, indent=4, sort_keys=True)
with open('versions.json', 'w+') as f:
f.write(js_data)
df_json = pd.read_json('versions.json')
df = df_json.transpose()
df.to_excel('versions.xlsx')
sys.exit(0)
import os
import json
import sys
error = False
def remove_bom(fname):
global error
"""
Read all properties of the given file return them as a dictionary.
"""
try:
utf8_string = []
with open(fname, 'r', encoding='utf-8') as f:
utf8_string = f.read()
if len(utf8_string) > 0 and utf8_string[0] == '\ufeff':
utf8_string = utf8_string[1:]
#with open(fname, 'wb') as f:
# f.write()
"".join(utf8_string).encode('ascii')
except Exception as ex:
print("Error: " + ex.__str__())
print("File: " + fname)
error = True
if __name__ == '__main__':
error = False
try:
directory = os.path.abspath(os.path.join('.','src'))
known_extensions = [".cs",".vb",".vbproj"]
files_info = {}
for path, subdirs, files in os.walk(directory):
for name in files:
file = os.path.join(path, name)
for ext in known_extensions:
if file.endswith(ext):
remove_bom(file)
except Exception as ex:
print("ERROR")
sys.exit(1)
if error:
print("ERROR")
sys.exit(1)
print("SUCCESS")
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment