Passing xml vallues from windows events as a variables - windows

I appreciate any advice from Powershell wizards out there.
I am trying to setup an email alert that will be triggered on event but having problems passing values as a variable so I can use it later in the body and subject of an email.
I have a few lines of script that pulls an event and stores it as XML but have no luck converting the value to variable to call it later.
$event = wevtutil qe 'Microsoft-Windows-Base-Filtering-Engine-Connections/Operational' /rd:true /c:1 /q:"*[System[(EventID=2000)]]" /f:renderedxml
$xmlresults = [xml]$event
$eventDate = $xmlresults.event.system.timecreated.systemtime
$eventTime = get-date $eventDate -Format ('dd-MM-yyyy hh:mm:ss')
Now when calling $xmlresults.event.eventdata.data I can see all values in a table:
PS C:\Windows\system32> $xmlresults.Event.EventData.Data
Name #text
---- -----
ConnectionId 1324000000003942
MachineAuthenticationMethod 2
RemoteMachineAccount DOMAIN\COMPUTERNAME$
UserAuthenticationMethod 2
RemoteUserAcount DOMAIN\USERNAME$
RemoteIPAddress XXXX:XXXXX:XXXX:XXXX:XXXXX:XXX:XXXX
LocalIPAddress XXXXX:XXXX:XXXX:XXXX::1
TechnologyProviderKey {XXXXXX-XXXX-XXXXX-XXXX-XXXXXXXXXX}
IPsecTrafficMode 1
DHGroup 0
StartTime 2021-05-17T13:52:38.103Z
How do I store the values of RemoteMachineAccount and RemoteUserAccount as a variable so I can call upon it later in the script when composing email alert and log input by simply using something along the lines of $computer and $user?
Any help greatly appreciated.

If you just need a few specifically named properties, you can use the .Where({}) method to filter the nodes returned by the XML provider and grab the text from that specific property:
$RemoteMachineAccount = $xmlresults.Event.EventData.Data.Where({$_.Name -eq 'RemoteMachineAccount'}).InnerText
$RemoteUserAccount = $xmlresults.Event.EventData.Data.Where({$_.Name -eq 'RemoteUserAccount'}).InnerText
If you need to discover/use them dynamically, another option is to convert the node list into a hashtable:
$eventData = #{}
$xmlresults.Event.EventData.Data.ForEach({ $eventData[$_.Name] = $_.InnerText })
At which point you can dereference the individual property values by name:
$eventData["RemoteUserAccount"]

Related

Fetch and process oldest email in the inbox using EWS Managed API

I'm using the script below along with EWS Managed API 2.2 to grab emails and read To and Sender property. It works fine for all emails, but i want to make it fetch, process oldest email (1x at the time), then move/delete it. Is there a way to set filters or arrange it to achieve the below, or anyone has ever worked on something like this?
##########
$mail= "useraa#domain.com"
$password="password"
# Set the path to your copy of EWS Managed API
$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
# Load the Assemply
[void][Reflection.Assembly]::LoadFile($dllpath)
# Create a new Exchange service object
$service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService
#These are your O365 credentials
$Service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($mail,$password)
# Autodiscover using the mail address set above
$service.AutodiscoverUrl($mail)
# create Property Set to include body and header of email
$PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
# set email body to text
$PropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;
# Set how many emails we want to read at a time
$numOfEmailsToRead = 1
# Index to keep track of where we are up to. Set to 0 initially.
$index = 0
# Do/while loop for paging through the folder
do
{
# Set what we want to retrieve from the folder. This will grab the first $pagesize emails
$view = New-Object Microsoft.Exchange.WebServices.Data.ItemView($numOfEmailsToRead,$index)
# Retrieve the data from the folder
$findResults = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$view)
foreach ($item in $findResults.Items)
{
# load the additional properties for the item
$item.Load($propertySet)
# Output the results
$To = $($item.ToRecipients)
$From = $($item.Sender)
}
# Increment $index to next block of emails
$index += $numOfEmailsToRead
} while ($findResults.MoreAvailable) # Do/While there are more emails to retrieve
##############
Any help is very much appreciated.
Thanks
In your ItemVeiw you can use OrderBy and sort it ascending eg after the line
$view = New-Object Microsoft.Exchange.WebServices.Data.ItemView($numOfEmailsToRead,$index)
add
$view.OrderBy.add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,[Microsoft.Exchange.WebServices.Data.SortDirection]::Ascending)

Not able to update the tester name in a Test Set from vbscript

I am been trying to search online for a solution but due to lack of knowledge in HP ALM I am not able to search proper hit tags
Set RunFactory = tsTest.RunFactory
Set obj_theRun = RunFactory.AddItem(CStr(testrunname))
obj_theRun.Status = sExecutionStatus '"Passed" '-- Status to be updated
obj_theRun.Tester = strTesterName
Getting error in this line object does not support obj_theRun.Tester
I just want to update the Tester column(Not Responsible tester) in Test set via vbscript. Please refer to the attached image at the very last column (TesterAny help is appreciated. Thank you in advance.
The documentation for ALM says the Tester Name can be specified by passing an array as the argument to AddItem.
https://admhelp.microfocus.com/alm/api_refs/ota/Content/ota/topic8805.html?Highlight=tester
An array consisting of the following elements:
Name - The name of the run (string. required).
Tester - The name of the user responsible (string. optional)
Location - The host name (string. optional). The default is the host name of the current machine
So change your code to this:
Set runFactory = tsTest.RunFactory
Dim newRunArgs(3)
newRunArgs(0) = testrunname ' `testrunname` is already a string so you don't need CStr.
newRunArgs(1) = "tester name goes here"
Set newRunArgs(2) = Nothing
Set newRun = RunFactory.AddItem( newRunArgs )
newRun.Status = sExecutionStatus '"Passed" '-- Status to be updated

WinCC export screen data to xls/csv

I am using TIA portal V13, with WinCC RT Advanced. I have been given a running project and need to export some values to excel for the client daily, monthly and yearly using a script. I have a screen with a table control that displays values of tags. The values are logged periodically.
How can I access the values from the screen or data logs using vbs? There is this command in the manual for accessing the dataLogs
HMIRuntime.Logging.DataLogs
But I cannot find how to access the data and save it to a file.
There is already a vbs script in the project(begin and end times are defined earlier in the script)but it just exports an empty csv with the column names but no values.
Set obj1 = obj.ScreenItems("Table view_1")
obj1.TimeColumnRangeType = 1
obj1.TimeColumnBeginTime = sBeginTime
obj1.TimeColumnEndTime = sEndTime
FolderName = "C:\Folder_name"
FileDate = sDay &"_" &sMonth &"_" &sYear
obj1.ExportDirectoryChangeable = True
obj1.ExportDirectoryname = FolderName
obj1.ExportFilenameChangeable = True
obj1.ExportFilename = "Filename " &FileDate
obj1.Export()

AWS AMI -Filter Latest Version

Maybe I am trying to use AWS EC2 incorrectly, please help me out. I would like to make a base ami via a user data script, this is no problem, it works. However, the next step is to make an image, however since the object is untagged its kind of a pain to filter for it, I can add criteria for region, vpc, security group and state, this would find the object and I could build the image.
However I do not want to overwrite the existing image, so ideally i need to tag this with a name and version, no problem. But then I need the child images to find that image, and i would like to find via name and version, but dynamically, i.e. latest. In docker it is pretty straight forward as long as the container is tagged, to use latest the version can be omitted and it will auto pull the latest. Is there a similar technique here? What do you guys use? Am I possibly using this wrong?
Here is what I did:
Note: although this is for is tagging an instance, it can easily be modified to work with images.
Note: I am not a powershell power user, so if you see a glaring inefficiency, please let me know.
I use Jenkins to build the machine, as such it has environment variables that I use for the tagging, however it calls a powershell script that has this signature, so you could manually call or call it via another script:
param(
...
[Parameter(Mandatory=$true)][string]$Tag_Name,
[Parameter(Mandatory=$true)][string]$Tag_Version
)
Inside of this script, I set the instance tags like so:
#Get metadata from ec2 service
$identityDocument = (Invoke-WebRequest http://169.254.169.254/latest/dynamic/instance-identity/document/).Content | ConvertFrom-Json
$tags = #(
#{Key = "Name"; Value = $Tag_Name},
#{Key = "Version"; Value = $Tag_Version}
)
New-EC2Tag -Resource $identityDocument.instanceId -Tag $tags
In another script, I can query by name, find all instances, parse the result into a hash table of [InstanceId, Version], sort by Version and get the top one.
$instanceName = "hello-world"
$instances = GetHashTableOfFilteredInstances $instanceName
$instanceId = GetNewestInstance($instances)
Write-Host 'Information for ' $instanceName
Write-Host '================='
Write-Host 'The newest instance is ' $instanceId
Write-Host '================='
function GetHashTableOfFilteredInstances($tagName){
$instances = Get-EC2Instance -Filter #( `
#{name='tag:Name'; values=$tagName};`
) | Select-Object -ExpandProperty instances
$actInstances= #{}
foreach($instance in $instances){
foreach($tag in $instance.Tag){
if ($tag.Key -ne "Version") {
Continue;
}
$actInstances.Add($tag.Value, $instance.InstanceId)
}
}
return $actInstances
}
function GetNewestInstance($instances){
return ($instances.GetEnumerator() | Sort-Object Key -descending)[0].Value
}

Powershell - Add (default display) object property values from pipe to string

Update 2: I ended up figuring this out while writing it. I figured I'd post it for anyone else muddling through. See sub-heading 'Resolution - Get only default properties', or the answer. Please feel free to respond with alternate (especially better!) methods or comments.
Update 1: I started out without a way to do this, I've since found a way for ALL properties. I've left the build-up for anyone else confused like I was, but my current problem is that I want JUST the default display properties - see sub-heading 'Get all Properties'
Let's say I have a collection of objects in powershell - the specific example I'm working with is a collection of events acquired using the get-winevent cmdlet.
Does anyone know an elegant way to get the values of all the (default) properties of each object, from the pipeline, and add them to the end of a string? Especially a way that doesn't involve needing to know which properties you want.
For example, using variable $events containing some event log entries, if I simply call $events powershell will make some assumptions about the properties I want and format them as a list:
PS C:\> $events
TimeCreated ProviderName Id Message
----------- ------------ -- -------
11/09/2014 3:59:... Microsoft-Window... 4634 An account was l...
11/09/2014 3:58:... Microsoft-Window... 4634 An account was l...
However, if I try to precede the returned entries with a string, I get the property names rather than values:
PS C:\> $events | %{"NEW RECORD" + $_}
NEW RECORDSystem.Diagnostics.Eventing.Reader.EventLogRecord
NEW RECORDSystem.Diagnostics.Eventing.Reader.EventLogRecord
PS C:\> $events | %{"NEW RECORD" + $_.properties}
NEW RECORDSystem.Diagnostics.Eventing.Reader.EventProperty System.Diagnostics.E
venting.Reader.EventProperty System.Diagnostics.Eventing.Reader.EventProperty S
ystem.Diagnostics.Eventing.Reader.EventProperty System.Diagnostics.Eventing.Rea
der.EventProperty
The easiest work around I could think of involved using (and therefore knowing) the property values, and also losing the notation that format-table or format-list would provide:
PS C:\> $events | %{"NEW RECORD - TimeCreated: " + $_.TimeCreated + "; ProviderName: "`
+ $_.ProviderName + "; ID: " + $_.ID + "; Message: " + $_.message}
NEW RECORD - TimeCreated: 09/11/2014 15:58:08; ProviderName: Microsoft-Windows-
Security-Auditing; ID: 4672; Message: Special privileges assigned to new logon.
Subject:
Security ID: S-*-*-**-*********-**********-**********-*****
Account Name: **********
Account Domain: **********
Logon ID: 0x**********
Privileges: SeSecurityPrivilege
Get all Properties
So I've discovered I CAN get ALL the properties, and their names, like this:
PS C:\> $events | %{"NEW RECORD" + ($_.psobject.properties | %{$_.name ; ":" ; $_.value})}
NEW RECORDMessage : Special privileges assigned to new logon.
Subject:
Security ID: S-*-*-**-*********-**********-**********-*****
Account Name: **********
Account Domain: **********
Logon ID: 0x**********
Privileges: SeSecurityPrivilege Id : 4672 Version : 0 Qualifiers :
Level : 0 <and so on>
However, I'm now pulling a bunch of stuff the consumers of my data won't need, since I only need the default properties and their names, plus a self-defined delimiter.
Is anyone aware of a notation that will return all values of all default display properties without said properties needing to be spelled out? Either a generic container for values (eg. $_.properties.value, though I tried that and it didn't work), or something like expand-property only without needing to specify a particular property name?
Resolution - Get only default properties
So it turns out I was overthinking this. FOREACH (%{}) can obviously preserve data from the pipeline across statements, so if I use two statements I can achieve the desired effect:
PS C:\> $events | format-list | %{"NEW RECORD" ; $_}
NEW RECORD
Message : An account was successfully logged on.
<and etc>
I answered this while writing it, the details are above. In order to collect all properties from an object and their values, and include both as part of a string:
PS C:\> $events | %{"NEW RECORD" + ($_.psobject.properties | %{$_.name ; ":IMASTRING:" ; $_.value})}
The above method owes a lot to the answer by Shay Levy to this question.
To include only the default properties and their values, preceded by a string:
PS C:\> $events | format-list | %{"NEW RECORD" ; $_}
To include all properties and their values, preceded by a string but retain the default formatting:
PS C:\> $events | select-object * | format-list | %{"NEW RECORD"; $_}
I think you've done things the easy and maybe best way for your situation. There actually is a way to know the names of the default properties
PS Scripts:\> $x = gwmi -Class win32_operatingsystem
PS Scripts:\> $x.psstandardmembers
PSStandardMembers {DefaultDisplayPropertySet}
PS Scripts:\> $x.psstandardmembers.DefaultDisplayPropertySet
ReferencedPropertyNames : {SystemDirectory, Organization, BuildNumber, RegisteredUser...}
MemberType : PropertySet
Value : DefaultDisplayPropertySet {SystemDirectory, Organization, BuildNumber, RegisteredUser,
SerialNumber, Version}
TypeNameOfValue : System.Management.Automation.PSPropertySet
Name : DefaultDisplayPropertySet
IsInstance : False
PS Scripts:\> $x.psstandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames
SystemDirectory
Organization
BuildNumber
RegisteredUser
SerialNumber
Version
This is the post that I found this information on PSStandard Members.

Resources