Complete beginner here.
Below script runs fine on PC1, but not on PC2. I receive the below:
Traceback (most recent call last):
File "C:\Users\sgreene\Documents\indices.py", line 44, in <module>
if msg.SentOn.strftime('20%y-%m-%d') == str(date.today() + datetime.timedelta(lagdays)):
File "C:\Program Files\Python36-32\lib\site-packages\win32com\client\dynamic.py", line 527, in __getattr__
raise AttributeError("%s.%s" % (self._username_, attr))
AttributeError: <unknown>.SentOn
As far as I know, both versions of pypiwin32 (win32com) are the same on both PCs, (version 223), so I am unsure as to how to deal with this.
Note: I also am looking to search a particular mail folder. At the moment I have it set to the default inbox (6). How do I make the script search a specifically named mail folder?
from win32com.client import Dispatch
import xml.etree.ElementTree as ET
from datetime import date
import pandas as pd
import datetime
import openpyxl as px
import os
file_location = r'C:\Users\Stefa\Documents\XMLfiles'
excel_location = r'C:\Users\Stefa\Documents\indices.xlsx'
sheet_code = 'Sheet1'
lag = 3
d = str(date.today())
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder("6")
all_inbox = inbox.Items
sub_today = ['test1', 'test2', 'test3', 'test4']
attach_strings = ['CMSIA', 'CMSRA']
sheet = pd.read_excel(excel_location)
wb = px.load_workbook(excel_location)
ws = wb[sheet_code]
for lagdays in range(-lag,1):
day = (date.today() + datetime.timedelta(lagdays)).weekday()
newfolder = file_location + '\\' + str(date.today() + datetime.timedelta(lagdays))
if not os.path.exists(newfolder):
if day<5:
os.makedirs(newfolder)
for i in sub_today:
for x in attach_strings:
for msg in all_inbox:
if msg.SentOn.strftime('20%y-%m-%d') == str(date.today() + datetime.timedelta(lagdays)):
if msg.Subject == i:
for att in msg.Attachments:
if x in att.FileName:
att.SaveAsFile(file_location + '\\' + str(date.today() + datetime.timedelta(lagdays)) + '\\' + i + x + '.xml')
tree = ET.parse(file_location + '\\' + str(date.today() + datetime.timedelta(lagdays)) + '\\' + i + x + '.xml')
root = tree.getroot()
for child in root:
for u in range(1,ws.max_column):
if str(child[1].text) == str(ws.cell(row=1, column=u).value):
for n in range(1,ws.max_row):
if str(ws.cell(row=n, column=1).value) == str(date.today() + datetime.timedelta(lagdays)) + ' 00:00:00':
if x == 'CMSIA':
ws.cell(row=n, column=u).value = child[4].text
else:
ws.cell(row=n, column=u).value = child[2].text
wb.save(r'C:\Users\Stefa\Documents\SMindices.xlsx')
You are assuming you only have MailItem objects in the Inbox. You can also have ReportItem or MeetingItem objects - they do not expose the SentOn property. Check the Class property first (it is exposed by all OOM objects) - for the MailItem object, it is 43 (OlObjectClass.olMail).
for msg in all_inbox:
if msg.Class = 43 Then
...
End If
Related
I am writing a Python script that will use the .getsessiontoken() method and write the new temporary credentials to the aws credentials file at ~/.aws/credentials. The profile, in my case will be named [temp-token].
I can write to the file successfully, but then I thought, what if that profile already exists. I would have to find and replace subsequent lines after the profile name. I'm still new to Python and trying to understand what the problem is:
import os
import boto3 as b
mfa_serial_number = "arn:aws:iam::xxxxxxxxxxxx:mfa/your-iam-user-here"
mfa_otp = input("Enter your otp:" )
def get_sts(mfa_serial_number, mfa_otp):
session = b.Session(profile_name='default', region_name='us-east-1')
sts = session.client('sts')
if mfa_serial_number is not None:
response = sts.get_session_token(
SerialNumber=mfa_serial_number, TokenCode=mfa_otp)
else:
response = sts.get_session_token()
temp_credentials = response['Credentials']
print(temp_credentials)
token_reponse = ["[temp-token] \n", "aws_access_key_id = " + temp_credentials["AccessKeyId"], "\n", "aws_secret_access_key = " + temp_credentials["SecretAccessKey"],"\n", "aws_session_token = " + temp_credentials["SessionToken"],"\n"]
# Look for the temp-token profile
pfile = "[temp-token]"
with open("/Users/YOUR USER/.aws/credentials", "r") as credentials:
aws_credential_file = credentials.readlines()
#print(aws_credential_file)
for line in aws_credential_file:
if line.find(pfile) != -1:
print('Profile Exists!')
#Prints the line number where the word was found
profile_line = aws_credential_file.index(line)
new_aws_access_key_line_num = profile_line + 1
new_secret_access_key_line_num = profile_line + 2
new_session_token_key_line_num = profile_line + 3
print("its still working", profile_line)
print(new_aws_access_key_line_num)
aws_credential_file[new_aws_access_key_line_num] = "aws_access_key_id = " + temp_credentials["AccessKeyId"], "\n"
# aws_credential_file[new_secret_access_key_line_num] = "aws_secret_access_key = " + temp_credentials["SecretAccessKey"],"\n"
# aws_credential_file[new_session_token_key_line_num] = "aws_session_token = " + temp_credentials["SessionToken"],"\n"
#print()
else:
aws_credential_file.writelines(token_reponse)
credentials.close()
get_sts(mfa_serial_number, mfa_otp)
The error I get is:
its still working 3
4
Traceback (most recent call last):
File "/Users/YOUR USER/code/sts.py", line 49, in
get_sts(mfa_serial_number, mfa_otp)
File "/Users/YOUR USER/code/sts.py", line 29, in get_sts
if line.find(pfile) != -1:
AttributeError: 'tuple' object has no attribute 'find'
Is there a better way to do this?
It's because of the ,\n in aws_credential_file
How do you make it so that an already compiled python script that was turned into a .exe import a config file?
Here is what I have:
#Rest of code that show the display and options are above ^
if __name__ == "__main__":
cwd = os.getcwd()
variableCheck = Path(cwd + '/config.py')
print(variableCheck)
print(cwd)
variableCheck.is_file()
if variableCheck.is_file():
from config import *
#Next print uses variables from config
print("ssh = " + ssh + "\nftp = " + ftp + "\nproftpd = " + proftpd + "\nvsftpd = " + vsftpd + "\nweb = " + web + "\napaweb = " + apaweb + "\nnginweb = " + nginweb + "\nhttps = " + https + "\nsmb = " + smb + "\nsql = " + sql + "\nrsnc = " + rsnc)
print('Configuration file has been loaded...')
app = QApplication(sys.argv)
main = Mainstart()
main.show()
sys.exit(app.exec_())
else:
print('Ello, you have some configurations to do!')
app = QApplication(sys.argv)
main = fconfStart()
main.show()
sys.exit(app.exec_())
I didn't add the functions fconfStart() or Mainstart() because 1) they are really long and 2) they are not the problem because they aren't even called yet when I get an error saying "cannot import config"
fconfStart function creates the config.py file.
First time the script is run you create the configurations file then you close and reopen the program to load with the configuration file that is config.py
How the config file is created in the first time startup of the script.
This is what happens when the confirm button is created (if it helps, I am using PyQt5 in this program):
#Rest of configuration options that users answer are above this piece of code ^
def confirmBTTN():
if self.ssh != '' and self.ftp != '' and self.proftpd != '' and self.vsftpd != '' and self.web != '' and self.apaweb != '' and self.nginweb != '' and self.https != '' and self.smb != '' and self.sql != '' and self.rsnc != '':
print('saving configurations\n')
print("ssh=" + self.ssh + ", ftp=" + self.ftp + ", proftpd=" + self.proftpd + ", vsftpd=" + self.vsftpd + ", web=" + self.web + ", apaweb=" + self.apaweb + ", nginweb=" + self.nginweb + ", https=" + self.https + ", smb=" + self.smb + ", sql=" + self.sql + ", rsnc=" + self.rsnc)
f = open("./config.py", "a+")
f.write("ssh = " + '"{}"'.format(self.ssh) + "\nftp = " + '"{}"'.format(self.ftp) + "\nproftpd = " + '"{}"'.format(self.proftpd) + "\nvsftpd = " + '"{}"'.format(self.vsftpd) + "\nweb = " + '"{}"'.format(self.web) + "\napaweb = " + '"{}"'.format(self.apaweb) + "\nnginweb = " + '"{}"'.format(self.nginweb) + "\nhttps = " + '"{}"'.format(self.https) + "\nsmb = " + '"{}"'.format(self.smb) + "\nsql = " + '"{}"'.format(self.sql) + "\nrsnc = " + '"{}"'.format(self.rsnc))
f.close()
RESTART = QMessageBox()
RESTART.setWindowTitle("Hey! Listen!")
RESTART.setText("Reopen the program to continue.")
RESTART.setIcon(QMessageBox.Information)
RESTART.setWindowIcon(QtGui.QIcon('HEY.png'))
RESTART.setStandardButtons(QMessageBox.Close)
RESTART.buttonClicked.connect(lambda: sys.exit(0))
x = RESTART.exec_()
else:
HEY = QMessageBox()
HEY.setWindowTitle('Hey! Listen!')
HEY.setText("Hey! You have not finished filling in all of the choices!")
HEY.setIcon(QMessageBox.Critical)
HEY.setWindowIcon(QtGui.QIcon('HEY.png'))
x = HEY.exec_()
Example Config.py
ssh = "yes"
ftp = "yes"
proftpd = "yes"
vsftpd = "no"
web = "yes"
apaweb = "yes"
nginweb = "no"
https = "yes"
smb = "yes"
sql = "yes"
rsnc = "no"
(If I need to use a different type of config file please let me know)
This is what the script creates. Then when I reopen script to use this newly created config file I get the error:
Traceback (most recent call last):
File "ScriptGUIrunner.py", line 380, in <module>
from config import *
ModuleNotFoundError: No module named 'config'
[20724] Failed to execute script ScriptGUIrunner
Can anyone help me with this problem?
Any help is greatly appreciated!
If you need me to add something to help clarify the problem I will gladly do so.
When you convert a python script to .exe you take away the ability to dynamically load python files (plus it can cause silent errors).
In general if you want to save information permanently then you should use any type of file (for example .txt) but it is better to use a pre-established format (such as .ini, .yaml, .csv, etc) and use a library that read safely such as ConfigParser, QSettings, etc.
On the other hand you should not use getcwd() but you should obtain the information dynamically as the answers to this question suggest.
We are getting this below error while migrating the data from slack channel to a file, when we execute the script for fetching the data for one day, it executing perfectly.
But when we execute the script for 2 months data, it gives 10 days data in separate file but getting throwing an error on particular date. It might be possible that the source data on slack is bit different from expected
Traceback (most recent call last):
File "C:\Users\Slack SCript\script.py", line 218, in <module>
main()
File "C:\Users\Slack SCript\script.py", line 201, in main
parse(message['text'])
File "C:\Users\Slack SCript\script.py", line 114, in parse
size = float(elements[1])
ValueError: could not convert string to float:
As per the source data we found that some value is 0 maybe the error we got because of this value. is there any way to skip or continue future.
from slackclient import SlackClient
import time
import os
import sys
import datetime
from dateutil.relativedelta import relativedelta
servers = ("fd2a", "ff1a", "hh3b", "kw1a", "kw1b", "lo8a", "os5a", "os5b", "sg2a", "sg2b", 'sy1a', 'va1a', 'va1b')
types = ("", "nfs", "cluster")
currser = "d"
currtype = ""
used = {}
total = {}
available = {}
ts = 0
dir_name = "data"
def savedata(dir_path, filename, data):
f = open(dir_path + filename, "w") # opens file with name of "test.txt"
print(dir_path + filename)
f.write(data)
f.close()
def reset_data():
print("datareset")
for i in range(0, len(servers)):
for j in range(0, len(types)):
used[servers[i] + types[j]] = 0
total[servers[i] + types[j]] = 0
available[servers[i] + types[j]] = 0
def write_data(ts):
datastr = ''
global used
global total
ttotaltotalsum = 0
for j in range(0, len(types)):
datastr += types[j] + '\n'
datastr += "Name\t" + "Region\t" + "total(TB)\t" + "used(TB)\t" + "available(TB)\t" + "Used(%)\n"
for i in range(0, len(servers)):
tused = used[servers[i] + types[j]]
ttotal = total[servers[i] + types[j]]
ttotaltotalsum += ttotal
if (ttotal != 0):
datastr += (
servers[i][0:len(servers[i]) - 1] + "\t\t" +
servers[i][len(servers[i]) - 1] + "\t\t" +
"{:.1f}".format(ttotal / 1024) + " \t\t" +
"{:.1f}".format(tused / 1024) + " \t\t" +
"{:.1f}".format((ttotal - tused) / 1024) +"\t\t"+
"{:.1f}".format(tused / ttotal * 100) + " \t\t" +
" \n")
print("..")
if (ttotaltotalsum > 0):
hour= datetime.datetime.fromtimestamp(int(ts)).hour
day= datetime.datetime.fromtimestamp(int(ts)).day
month= datetime.datetime.fromtimestamp(int(ts)).month
year=datetime.datetime.fromtimestamp(int(ts)).year
if hour < 12:
savedata("data/", "Storage-Update-M-" +
str(day) + "-" +
str(month) + "-" +
str(year) + ".txt", datastr)
else:
savedata("data/", "Storage-Update-E-" +
str(day) + "-" +
str(month) + "-" +
str(year) + ".txt", datastr)
def parse(text):
global currser
global currtype
global used
global total
global available
global ts
content = text.split("\n")
for line in content:
line = line[:len(line)]
if line.__contains__("Netapp Cluster"):
for server in servers:
if line.__contains__(server):
currser = server
for type in types:
if line.__contains__(type):
currtype = type
# print(line)
if line.__contains__("Total available capacity"):
# print(line)
# print ("contains","Total available capacity------")
elements = line.split(":")
# print (elements)
size = float(elements[1])
# print(size)
total[currser + currtype] += size
# print(size,"TOTAL capacity",total)
elif line.__contains__("size provisioned"):
# print(line)
# print("contains", "Total LUN size provisioned------- ")
elements = line.split(":")
# print(elements)
size = float(elements[1])
# print(size)
used[currser + currtype] += size
# print(size, "Used", used)
# print( currser)
# print( currtype)
# print( used)
# print(total)
# print(available)
return (used, total)
def make_dir(dir_name):
if not os.path.exists(dir_name):
os.makedirs(dir_name)
def main():
slack_token = ""
channel_name = ''
time_on_last_message = time.time()
channel_id = ""
ts = 0.000
threshmins = 20
channels_call = SlackClient(slack_token).api_call("channels.list")
print(channels_call)
print(channels_call.keys())
for channel in channels_call["channels"]:
if channel["name"] == channel_name:
channel_id = channel["id"]
print(channel)
make_dir(dir_name)
print(channel_id)
reset_data()
time_since_last_update = time.time() - time_on_last_message
print("Waiting for new data....", time.time() - time_on_last_message)
if time_since_last_update > threshmins * 60:
write_data(ts)
reset_data()
sc = SlackClient(slack_token)
date_after_month = datetime.datetime.now() + relativedelta(months=-6)
date_after_month=date_after_month.timestamp()
while True:
breakflag=0
data = sc.api_call(
"channels.history",
channel=channel_id,
oldest=date_after_month,
count=1000,
)
if (data['ok'] == True):
messages = data['messages']
for message in reversed(messages):
# print(message['ts'])
if float(message['ts']) > ts:
print("difference=", float(message['ts']) - ts)
if float(message['ts']) - ts > (threshmins * 60):
print("greater diffrrece>reset................")
write_data(ts)
print(ts)
reset_data()
time_on_last_message = time.time()
ts = float(message['ts'])
parse(message['text'])
if (data["has_more"] == True):
print("has more")
date_after_month=message['ts']
else:
breakflag=1
else:
print("No data returned or error")
time.sleep(1) # in Seconds
if(breakflag==1):
break
main()
Based on the error message, elements[1] is empty. And Python cannot convert an empty string to float:
>>> float("")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: could not convert string to float:
The elements[1] element is a string that can't be parsed to a float. The easiest way would be to attach a debugger and investigate what is being parsed. Then change your code to parse it better.
The second easiest way would be to binary search for the record that makes it fail and fix your code to parse it better.
The totally absolutely preferred way would be to, when you found what the case was that your code didn't support, you would write a test that proves that that case was added:
def test_parse_xyz():
assert [("blablabla", None)] == parse(["blablabla: -certainly_not_a_float"])
These tests can automatically be detected by e.g. pytest:
$ pytest parser.py
I have created a program to merge TIFs into multipage tifs with an rather old version of FreeImagePy from 2009. It actually works pretty well but I have one little hitch. As best I can tell it's not freeing up the memory and eventually crashes. Can anyone tell me what I am missing?
Using Ptyhon 2.7.
import urllib
import FreeImagePy as FIPY
import os.path
import time
# set source files
sourceFile = open('C:\\temp\AGetStatePlats\\PlatsGenesee.csv','r')
# logfile currently gets totally replaced at each run
logFile = open('C:\\temp\\AGetStatePlats\\PlatTifMerge.txt','w')
sourcePath = "c:\\temp\subdownload2\\"
destPath = 'C:\\temp\\subtifMerge\\'
for row in sourceFile:
# prepare filenames
subPath = row.split(',',1)[0]
platID = subPath.split('/',1)[1]
curDocument = sourcePath + platID + '01.tif'
curPage = 0
# check if base file is out there
if not os.path.isfile(destPath + platID + '.tif'):
outImage = FIPY.Image()
outImage.new(multiBitmap = destPath + platID +'.tif')
print (destPath + platID +'.tif')
for n in range (1,100):
#build n
nPad = "{:0>2}".format(n)
if os.path.isfile(sourcePath + platID + nPad + '.tif'):
# delay in case file system is not keeping up may not be needed
time.sleep (1.0/4.0)
outImage.appendPage(sourcePath + platID + nPad + '.tif')
curPage = curPage + 1
else:
outImage.deletePage(0)
outImage.close()
del outImage
logFile.write(sourcePath + platID + '.tif' + '\r')
logFile.write(platID + " PageCount = " + str(curPage) + '\r' )
break
else:
logFile.write(platID + " already exists" + '\r')
# cleanup
sourceFile.close()
logFile.close()
print("Run Complete!")
Here's the error messages:
C:\temp\subtifMerge\05848.tif ('Error returned. ', 'TIFF', 'Warning: parsing error. Image may be incomplete or contain invalid data !') Traceback (most recent call last): File "C:\temp\AGetStatePlats\PlatTIFcombine.py", line 43, in outImage.appendPage(sourcePath + platID + nPad + '.tif') File "C:\Python27\ArcGIS10.4\lib\site-packages\FreeImagePy\FreeIm??agePy.py", line 2048, in appendPage bitmap = self.genericLoader(fileName) File "C:\Python27\ArcGIS10.4\lib\site-packages\FreeImagePy\FreeIm??agePy.py", line 1494, in genericLoader dib = self.Load(fif, fileName, flag); File "C:\Python27\ArcGIS10.4\lib\site-packages\FreeImagePy\FreeIm??agePy.py", line 188, in Load return self.__lib.Load(typ, fileName, flags)
WindowsError: exception: priviledged instruction >>>
Guys do anyone know how to read event log file in C:\Windows\System32\winevt\Logs with .evtx extension?
I have already tried to open it using notepad and read using python but notepad says access is denied...
Do anyone know how to do it? Thanks in advance..
This is how you would read the file "Forwarded Events" from the event viewer. You need admin access so I would run it as admin but I it will prompt you for a password if you don't.
import win32evtlog
import xml.etree.ElementTree as ET
import ctypes
import sys
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if is_admin():
# open event file
query_handle = win32evtlog.EvtQuery(
'C:\Windows\System32\winevt\Logs\ForwardedEvents.evtx',
win32evtlog.EvtQueryFilePath)
read_count = 0
a = 1
while a == 1:
a += 1
# read 1 record(s)
events = win32evtlog.EvtNext(query_handle, 1)
read_count += len(events)
# if there is no record break the loop
if len(events) == 0:
break
for event in events:
xml_content = win32evtlog.EvtRender(event, win32evtlog.EvtRenderEventXml)
# parse xml content
xml = ET.fromstring(xml_content)
# xml namespace, root element has a xmlns definition, so we have to use the namespace
ns = '{http://schemas.microsoft.com/win/2004/08/events/event}'
substatus = xml[1][9].text
event_id = xml.find(f'.//{ns}EventID').text
computer = xml.find(f'.//{ns}Computer').text
channel = xml.find(f'.//{ns}Channel').text
execution = xml.find(f'.//{ns}Execution')
process_id = execution.get('ProcessID')
thread_id = execution.get('ThreadID')
time_created = xml.find(f'.//{ns}TimeCreated').get('SystemTime')
#data_name = xml.findall('.//EventData')
#substatus = data_name.get('Data')
#print(substatus)
event_data = f'Time: {time_created}, Computer: {computer}, Substatus: {substatus}, Event Id: {event_id}, Channel: {channel}, Process Id: {process_id}, Thread Id: {thread_id}'
print(event_data)
user_data = xml.find(f'.//{ns}UserData')
# user_data has possible any data
else:
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
input()
.evtx is the extension for Windows Eventlog files. It contains data in a special binary format designed by Microsoft so you cannot simply open it in a text editor.
The are open source tools to read .evtx and the NXLog EE can also read .evtx files. (Disclaimer: I'm affiliated with the latter).
I modified the accepted answer a bit as following, so it becomes reusable:
import xml.etree.ElementTree as Et
import win32evtlog
from collections import namedtuple
class EventLogParser:
def __init__(self, exported_log_file):
self.exported_log_file = exported_log_file
def get_all_events(self):
windows_events = []
query_handle = win32evtlog.EvtQuery(str(self.exported_log_file),
win32evtlog.EvtQueryFilePath | win32evtlog.EvtQueryReverseDirection)
while True:
raw_event_collection = win32evtlog.EvtNext(query_handle, 1)
if len(raw_event_collection) == 0:
break
for raw_event in raw_event_collection:
windows_events.append(self.parse_raw_event(raw_event))
return windows_events
def parse_raw_event(self, raw_event):
xml_content = win32evtlog.EvtRender(raw_event, win32evtlog.EvtRenderEventXml)
root = Et.fromstring(xml_content)
ns = "{" + root.tag.split('}')[0].strip('{') + "}"
system = root.find(f'{ns}System')
event_id = system.find(f'{ns}EventID').text
level = system.find(f'{ns}Level').text
time_created = system.find(f'{ns}TimeCreated').get('SystemTime')
computer = system.find(f'{ns}Computer').text
WindowsEvent = namedtuple('WindowsEvent',
'event_id, level, time_created, computer')
return WindowsEvent(event_id, level, time_created, computer)
I use the "python-evtx" library, you can install it using this command:
pip install python-evtx
In my case, I'm not interested in reading records with the "Information" level.
import os
import codecs
from lxml import etree
import Evtx.Evtx as evtx
def evtxFile(absolutePath, filenameWithExt, ext, _fromDate, _toDate):
print("Reading: " + filenameWithExt)
outText = ""
channel = ""
#read the windows event viewer log and convert its contents to XML
with codecs.open(tempFilePath, "a+", "utf-8", "ignore") as tempFile:
with evtx.Evtx(absolutePath) as log:
for record in log.records():
xmlLine = record.xml()
xmlLine = xmlLine.replace(" xmlns=\"http://schemas.microsoft.com/win/2004/08/events/event\"", "")
xmlParse = etree.XML(xmlLine)
level = parseXMLtoString(xmlParse, ".//Level/text()")
if not level == "0" and not level == "4":
providerName = parseXMLtoString(xmlParse, ".//Provider/#Name")
qualifiers = parseXMLtoString(xmlParse, ".//EventID/#Qualifiers")
timestamp = parseXMLtoString(xmlParse, ".//TimeCreated/#SystemTime")
eventID = parseXMLtoString(xmlParse, ".//EventID/text()")
task = parseXMLtoString(xmlParse, ".//Task/text()")
keywords = parseXMLtoString(xmlParse, ".//Keywords/text()")
eventRecordID = parseXMLtoString(xmlParse, ".//EventRecordID/text()")
channel = parseXMLtoString(xmlParse, ".//Channel/text()")
computer = parseXMLtoString(xmlParse, ".//Computer/text()")
message = parseXMLtoString(xmlParse, ".//Data/text()")
if level == "1":
level = "Critical"
elif level == "2":
level = "Error"
elif level == "3":
level = "Warning"
date = timestamp[0:10]
time = timestamp[11:19]
time = time.replace(".", "")
_date = datetime.strptime(date, "%Y-%m-%d").date()
if _fromDate <= _date <= _toDate:
message = message.replace("<string>", "")
message = message.replace("</string>", "")
message = message.replace("\r\n", " ")
message = message.replace("\n\r", " ")
message = message.replace("\n", " ")
message = message.replace("\r", " ")
outText = date + " " + time + "|" + level + "|" + message.strip() + "|" + task + "|" + computer + "|" + providerName + "|" + qualifiers + "|" + eventID + "|" + eventRecordID + "|" + keywords + "\n"
tempFile.writelines(outText)
with codecs.open(tempFilePath, "r", "utf-8", "ignore") as tempFile2:
myLinesFromDateRange = tempFile2.readlines()
#delete the temporary file that was created
os.remove(tempFilePath)
if len(myLinesFromDateRange) > 0:
createFolder("\\filtered_data_files\\")
outFilename = "windows_" + channel.lower() + "_event_viewer_logs" + ext
myLinesFromDateRange.sort()
#remove duplicate records from the list
myFinalLinesFromDateRange = list(set(myLinesFromDateRange))
myFinalLinesFromDateRange.sort()
with codecs.open(os.getcwd() + "\\filtered_data_files\\" + outFilename, "a+", "utf-8", "ignore") as linesFromDateRange:
linesFromDateRange.seek(0)
if len(linesFromDateRange.read(100)) > 0:
linesFromDateRange.writelines("\n")
linesFromDateRange.writelines(myFinalLinesFromDateRange)
del myLinesFromDateRange[:]
del myFinalLinesFromDateRange[:]
else:
print("No data was found within the specified date range.")
print("Closing: " + filenameWithExt)
I hope it helps you or someone else in the future.
EDIT:
The "tempFilePath" can be anything you want, for example:
tempFilePath = os.getcwd() + "\\tempFile.txt"
I collected some information first before calling the "evtxFile" function:
The "From" and the "To" dates are in the following format: YYYY-MM-DD
Converted the dates to "date" data type:
_fromDate = datetime.strptime(fromDate, "%Y-%m-%d").date()
_toDate = datetime.strptime(toDate, "%Y-%m-%d").date()
Divided the directory where the .evtx files are located into different parts:
def splitDirectory(root, file):
absolutePathOfFile = os.path.join(root, file)
filePathWithoutFilename = os.path.split(absolutePathOfFile)[0]
filenameWithExt = os.path.split(absolutePathOfFile)[1]
filenameWithoutExt = os.path.splitext(filenameWithExt)[0]
extension = os.path.splitext(filenameWithExt)[1]
return absolutePathOfFile, filePathWithoutFilename, filenameWithExt, filenameWithoutExt, extension
for root, subFolders, files in os.walk(directoryPath):
for f in files:
absolutePathOfFile, filePathWithoutFilename, filenameWithExt,
filenameWithoutExt, extension = splitDirectory(root, f)
if extension == ".evtx":
evtxFile(absolutePathOfFile, filenameWithExt, ".txt", _fromDate, _toDate)