Variable Question

by Lery at 2013-04-03 14:50:08

My goal is to return the Display Name and Installed Date for installed programs. These installed programs can be located in either the 32-bit and 64-bit hives, or just one. I then need to take the results and put them into an XML file that is already formatted due to the software provider providing a COM object.

Here is my code that helpful users helped me with earlier today. This works perfectly as I need it to.

#32-bit
if (Test-Path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall) {
$32inv = Get-ChildItem -Path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where {$.DisplayName} | Select-Object DisplayName, @{Name=‘Installed’;Expression={"$($.installdate.Substring(4,2))-$($.installdate.Substring(6,2))-$($.installdate.Substring(0,4))"}}
}

#64-bit
if (Test-Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall) {
$64inv = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where {$.DisplayName} | Select-Object DisplayName, @{Name=‘Installed’;Expression={"$($.installdate.Substring(4,2))-$($.installdate.Substring(6,2))-$($.installdate.Substring(0,4))"}}
}


I understand that you folks do not have the COM object I’m talking about. Therefore, I’ll provide a code snippet from something completely different that works so that you can see what I mean by the COM object:


#This creates a variable named NSE and then connects to the ComObject called Altiris.AeXNSEvent
#It then sets the variable nse to the To property of Altiris.AeXNSEvent and feeds it a static string GUID
#It then sets the variable nse to the Priority property with a value of 1
#Do not change this section. It is always static.
$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1
###########################################################

#Modify this varaible with the custom data class guid
$strDataClassGuid = "{49798405-bd7f-43a5-b711-f8a9023320ee}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

#Add new row of data
$objDataRow = $objDataclass.AddRow()

#Create a variable called data. Then checks the state of the service AexSVC

$data = get-wmiobject -query "select state from win32_service where Name = ‘EFS’"

#Some conditional formating. If the state of the service is running it will put that into the NSE.
#If the state is not running, defined by the else, it will put whatever the state is for the service into the NSE.
if ($data.State -eq "Running") {
$objDataRow.SetField(0, $data.State)
}
else
{$objDataRow.SetField(0, $data.State)
}

#Away goes the NSE
$nse.SendQueued()


My question is around the piece $objDataRow.SetField(0, $data.State) This is the piece that writes my data to the XML file. Notice the $data.State specifically? That is just putting the State value into the XML file. How can I do that using the code from above? Essentially I’m trying to say $data.. but of course . does not work. I just need to get everything and put it in there.
by DonJ at 2013-04-03 23:18:23
So $data is a WMI object.

($data | Select-Object -Property )

would return every property of the WMI object. "State" is one of those properties. However, "
" is not a valid property name, and "." would only be applicable to a file path. But, using Select-Object -Property may not work. If your $objDataRow only wants a single value for its second argument, then you can’t give it an entire multi-property object. I don’t know enough about how it works to tell you that.
by Lery at 2013-04-04 07:13:42
[quote="DonJ"]So $data is a WMI object.

($data | Select-Object -Property )

would return every property of the WMI object. "State" is one of those properties. However, "
" is not a valid property name, and "
." would only be applicable to a file path. But, using Select-Object -Property may not work. If your $objDataRow only wants a single value for its second argument, then you can’t give it an entire multi-property object. I don’t know enough about how it works to tell you that.[/quote]

I’ll try it out soon Don and let you know. Here is a VB script example so that you can see how the $data is being set for multiple rows.

‘Following is a sample custom inventory sript gathering information about processor of a machine and posting data
‘to NS using Altiris NSE Component
’===================================================================================================================
’ On Error Resume Next

Set oShell = CreateObject( "WScript.Shell" )
compName=oShell.ExpandEnvironmentStrings("%ComputerName%")

‘Create instance of Wbem service object and connect to namespace
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\" & strComputer & "\root\CIMV2")

‘Fire WMI Query
Set objCIMObj = objWMIService.ExecQuery("select * from Win32_UserAccount Where Domain =’" & compName & "’")

‘===================================================================================================================

‘Create instance of Altiris NSE component
dim nse
set nse = WScript.CreateObject ("Altiris.AeXNSEvent")

’ Set the header data of the NSE
’ Please don’t modify this GUID
nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
nse.Priority = 1

'Create Inventory data block. Here assumption is that the data class with below guid is already configured on server
dim objDCInstance
set objDCInstance = nse.AddDataClass ("{57f75526-ee25-4e9a-b8bb-c67c7c0e2da2}")

dim objDataClass
set objDataClass = nse.AddDataBlock (objDCInstance)

For each objInfo in objCIMObj

'Add a new row
dim objDataRow
set objDataRow = objDataClass.AddRow
'Set columns
objDataRow.SetField 0, objInfo.AccountType
objDataRow.SetField 1, objInfo.Caption
objDataRow.SetField 2, objInfo.Description
objDataRow.SetField 3, objInfo.Disabled
objDataRow.SetField 4, objInfo.Domain
objDataRow.SetField 5, objInfo.FullName
objDataRow.SetField 6, objInfo.LocalAccount
objDataRow.SetField 7, objInfo.Lockout
objDataRow.SetField 8, objInfo.Name
objDataRow.SetField 9, objInfo.PasswordChangeable
objDataRow.SetField 10, objInfo.PasswordExpires
objDataRow.SetField 11, objInfo.PasswordRequired
objDataRow.SetField 12, objInfo.SID
objDataRow.SetField 13, objInfo.Status

by Lery at 2013-04-04 07:47:46
I got a littler further but not there yet. Here is what I have:


$query = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |<br>Get-ItemProperty | Where {$_&#46;DisplayName} |
Select-Object DisplayName, @{Name=‘Installed’;Expression={"$($.installdate.Substring(4,2))-$($.installdate.Substring(6,2))-$($.installdate.Substring(0,4))"}}

foreach ($objinfo in $query) {
$objDataRow.SetField(0, $objInfo.Displayname)
$objDataRow.SetField(1, $objInfo.Installed)
}


The resulting XML file I get only contains one row from the query. For example: 7-Zip 9.20 (x64 edition) 11-08-2012

The query returns 173 rows. That could change per computer of course.

I’m guessing my loop isn’t right and needs adjusting. Any ideas?
by DonJ at 2013-04-04 08:05:11
You’re using $objInfo (which used to be $data) correctly.

You don’t need the backtick after the pipe characters.

Not sure what you’re doing with the InstallDate field - ($
.ConvertToDateTime($.InstallDate)).ToShortDate() should give you a normally formatted datetime.

I’m assuming $objDataRow needs to be incremented somehow, and I don’t see where you’re doing that. Otherwise, aren’t you just writing each item of data to the same row, meaning only the last item written will actually be kept?
by nohandle at 2013-04-04 08:16:31
So are we talking about Altiris or something different here? Would this work?
$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1
###########################################################

#Modify this varaible with the custom data class guid
$strDataClassGuid = "{49798405-bd7f-43a5-b711-f8a9023320ee}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

#Add new row of data
$objDataRow = $objDataclass.AddRow()

#Create a variable called data. Then checks the state of the service AexSVC

#change here to *
$data = get-wmiobject -query "select * from win32_service where Name = 'EFS'"

#give me list of meaningful properties
[array]$dataProperties = $data.psadapted |
Get-Member -MemberType Properties |
where {$
.name -notlike "__
"} |
select -ExpandProperty name

#add each meaningful property
if ($dataProperties)
{
for ($index=0; $index -lt $dataProperties.count; $index++)
{ #or addfield?
$objDataRow.SetField($index, $data.($dataProperties[$index]))
}
}

#Away goes the NSE
#commented out -----> $nse.SendQueued()


btw what?
#Some conditional formating. If the state of the service is running it will put that into the NSE.
#If the state is not running, defined by the else, it will put whatever the state is for the service into the NSE.
if ($data.State -eq "Running") {
$objDataRow.SetField(0, $data.State)
}
else
{$objDataRow.SetField(0, $data.State)
}
by Lery at 2013-04-04 10:12:27
[quote="nohandle"]So are we talking about Altiris or something different here? Would this work?
$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1
###########################################################

#Modify this varaible with the custom data class guid
$strDataClassGuid = "{49798405-bd7f-43a5-b711-f8a9023320ee}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

#Add new row of data
$objDataRow = $objDataclass.AddRow()

#Create a variable called data. Then checks the state of the service AexSVC

#change here to
$data = get-wmiobject -query "select * from win32_service where Name = 'EFS'"

#give me list of meaningful properties
[array]$dataProperties = $data.psadapted |
Get-Member -MemberType Properties |
where {$_.name -notlike "__
"} |
select -ExpandProperty name

#add each meaningful property
if ($dataProperties)
{
for ($index=0; $index -lt $dataProperties.count; $index++)
{ #or addfield?
$objDataRow.SetField($index, $data.($dataProperties[$index]))
}
}

#Away goes the NSE
#commented out -----> $nse.SendQueued()

[/quote]

Yes, I’m using Altiris. I’m not sure everyone would know what that is, so I was trying to not be specific.

[quote]
btw what?
#Some conditional formating. If the state of the service is running it will put that into the NSE.
#If the state is not running, defined by the else, it will put whatever the state is for the service into the NSE.
if ($data.State -eq "Running") {
$objDataRow.SetField(0, $data.State)
}
else
{$objDataRow.SetField(0, $data.State)
}
[/quote]

The code you’re asking about was just an example of a working script I made. It uses a WMI query to look for the state of a service. If the state is running it will populate $data with state. If it’s not running it still does the same. Those notes are just my crazy notes. Sorry for the confusion they added. I know I do not have to do it that way and I could just right whatever the state result is into $data.state.

Re-read my comment from Thu Apr 04, 2013 10:47 am as it might help you understand more. If not, I apologize for not explaining it properly.
by Lery at 2013-04-04 10:22:02
[quote="DonJ"]
Not sure what you’re doing with the InstallDate field - ($.ConvertToDateTime($.InstallDate)).ToShortDate() should give you a normally formatted datetime.
[/quote]

I’m doing that because when I query HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, it returns the installed date in the format of 20110823 for example. Instead of 08-23-2011. I posted in another thread and some helpful person gave me that code.

[quote]
I’m assuming $objDataRow needs to be incremented somehow, and I don’t see where you’re doing that. Otherwise, aren’t you just writing each item of data to the same row, meaning only the last item written will actually be kept?[/quote]

That is exactly what is happening Don. I do not want it to do that. I need it to write all the data.

If you run this, minus the back tick that you said, you will see the results I’m after. Depending on the computer, you could have 20 results or 500+ results. You never know.

Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |<br>Get-ItemProperty | Where {$_&#46;DisplayName} |
Select-Object DisplayName, @{Name=‘Installed’;Expression={"$($.installdate.Substring(4,2))-$($.installdate.Substring(6,2))-$($.installdate.Substring(0,4))"}}


Instead of running the command above, I’m putting it into a variable called $query. I’m doing this because I think I have to, not because I’m sure. I think i have to put it into the query because I need to reference it later on.

I was hoping this would work to write all the data, but as you said and I experienced, it just writes the last line.

foreach ($objinfo in $query) {
$objDataRow.SetField(0, $objInfo.Displayname)
$objDataRow.SetField(1, $objInfo.Installed)


As an example, my XML contains the following:
<body>
<inventory>
<dataClass guid="{49798405-bd7f-43a5-b711-f8a9023320ee}">
<data>
<resource partialUpdate="false">
<row c0="SQL Server 2008 R2 SP2 Database Engine Services" c1="11-08-2012" hash="WBW70VRADyOdHfrkRBsWtw=="/>
</resource>
</data>
</dataClass>
</inventory>
</body>


There should be 150 or so rows in that XML file. Not one.

I’ve gone from no rows, to one row. So I must be getting close! :slight_smile:
by nohandle at 2013-04-04 10:29:40
The btw was just btw, i was not if the confirion is useless or i just can’t read. That is it.
Anyway, look at the code i posted, i changet the resulting set of properties the wmi query returns and tried to add them similarly as in the vbscript code.
by Lery at 2013-04-04 11:03:38
[quote="nohandle"]get-wmiobject -query "select * from win32_service where Name = ‘EFS’"[/quote][quote="nohandle"]The btw was just btw, i was not if the confirion is useless or i just can’t read. That is it.
Anyway, look at the code i posted, i changet the resulting set of properties the wmi query returns and tried to add them similarly as in the vbscript code.[/quote]

Thank you. It looks like you’re editing the query for this code
get-wmiobject -query "select * from win32_service where Name = ‘EFS’"

I have that working already. I have no problem adding one result to my output. My problem is when the result is many rows. As in my reply to Don. In that, you can see the query I’m now running is this:

Get-ItemProperty | Where {$
.DisplayName} |Select-Object DisplayName, @{Name=‘Installed’;Expression={"$($.installdate.Substring(4,2))-$($.installdate.Substring(6,2))-$($.installdate.Substring(0,4))"}}

That gives me about 150+ lines. I need all of it written to my file.
by Lery at 2013-04-04 14:38:47
This is very frustrating. I can get it working in Powershell. The problem happens when I introduce this custom COM object. Which I must say I’m not very experienced with. For example this works great!
Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where {$
.DisplayName} |
Select-Object DisplayName > software.csv


This works great:

foreach ($i in Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where {$.DisplayName} |
Select-Object DisplayName) {$i.DisplayName}


When I start using the COM object I get output into an XML file with one row instead of many.
by Lery at 2013-04-04 15:18:17
This works populates the file with the following: <row c0="KB976902"


$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1

$strDataClassGuid = "{daed7083-873c-4455-8110-9dec010344e3}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)


$objDataRow = $objDataclass.AddRow()

$data = Get-HotFix -Id KB976902

$objDataRow.SetField(0, $data.HotfixID)

$nse.SendQueued()


This does not work and populates the XML file with: <row c0="[NULL()]"


$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1

$strDataClassGuid = "{daed7083-873c-4455-8110-9dec010344e3}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

$objDataRow = $objDataclass.AddRow()

$data = Get-HotFix

$objDataRow.SetField(0, $data.HotfixID)

$nse.SendQueued()


If it helps the vendors documentation for the Setfield method says this:

[quote]SetField Sets the value of the indexed field.
index VARIANT Required The index of the field to set, this may be an integer index or the name of the field.
value VARIANT Optional The value of the field. This may be a string, a number, a GUID, a resource object to reference another resource defined in the event, NULL to represent a database NULL value, or omitted to represent the
default value (the default value is specified for the column when the dataclass is configured on the NS.)[/quote]
by nohandle at 2013-04-05 07:34:52
$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1
###########################################################

#Modify this varaible with the custom data class guid
$strDataClassGuid = "{49798405-bd7f-43a5-b711-f8a9023320ee}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

#add the same data three times
1…3 | foreach {
#Add new row of data
$objDataRow = $objDataclass.AddRow()
$data = get-wmiobject -query "select name, state from win32_service where Name = 'EFS'"
[array]$dataProperties = $data.psadapted |
Get-Member -MemberType Properties |
where {$
.name -notlike "__
"} |
select -ExpandProperty name

#if there are any properties
if ($dataProperties)
{
for ($index=0; $index -lt $dataProperties.count; $index++)
{
$objDataRow.SetField($index, $data.($dataProperties[$index]))
}
}
}
#Away goes the NSE
$nse
#commented out -----> $nse.SendQueued()


To : {1592B913-72F3-4C36-91D2-D4EDA21D2F96}
Priority : 1
Guid : {30106414-B2A0-4614-9F38-23FBE9B53002}
DefaultResource : System.ComObject
Xml : <?xml version="1.0"?>
<message>
<to>{1592B913-72F3-4C36-91D2-D4EDA21D2F96}</to>
<priority>1</priority>
<msgId>{30106414-B2A0-4614-9F38-23FBE9B53002}</msgId>
<time>20130405163127.324000-120</time>
<from>
<resource typeGuid="{493435F7-3B17-4C4C-B07F-C23E7AB7781F}" guid="{8A3E1EA9-46
96-400E-A230-EA60A60A36F5}" name="fqdn-edited—1">
<key name="name.domain" value="fqdn-edited—"/>
<key name="fqdn" value="fqdn-edited—"/>
<key name="uniqueid" value="UbpWutfzfzSwi/SilxS/4A=="/>
<key name="uniqueid" value="6qhWRcgoQZjCCxkmRqJuiw=="/>
</resource>
</from>
<body>
<inventory>
<dataClass guid="{49798405-bd7f-43a5-b711-f8a9023320ee}">
<data>
<resource partialUpdate="false">
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
</resource>
</data>
</dataClass>
</inventory>
</body>
</message>

XmlBody : <body>
<inventory>
<dataClass guid="{49798405-bd7f-43a5-b711-f8a9023320ee}">
<data>
<resource partialUpdate="false">
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
</resource>
</data>
</dataClass>
</inventory>
</body>

Hash : aWwAqFN48hqX6XyP4ad/FQ==


Iterating on the addRow, setField adds more rows. This is the output you are after? (with correct data of course)
by MasterOfTheHat at 2013-04-05 07:58:23
[quote="Lery"]This works populates the file with the following: <row c0="KB976902"


$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1

$strDataClassGuid = "{daed7083-873c-4455-8110-9dec010344e3}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)


$objDataRow = $objDataclass.AddRow()

$data = Get-HotFix -Id KB976902

$objDataRow.SetField(0, $data.HotfixID)

$nse.SendQueued()


This does not work and populates the XML file with: <row c0="[NULL()]"


$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1

$strDataClassGuid = "{daed7083-873c-4455-8110-9dec010344e3}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

$objDataRow = $objDataclass.AddRow()

$data = Get-HotFix

$objDataRow.SetField(0, $data.HotfixID)

$nse.SendQueued()


If it helps the vendors documentation for the Setfield method says this:

[quote]SetField Sets the value of the indexed field.
index VARIANT Required The index of the field to set, this may be an integer index or the name of the field.
value VARIANT Optional The value of the field. This may be a string, a number, a GUID, a resource object to reference another resource defined in the event, NULL to represent a database NULL value, or omitted to represent the
default value (the default value is specified for the column when the dataclass is configured on the NS.)[/quote][/quote]

The difference is that in the first example, "Get-HotFix -Id KB976902" returns a single ManagementBaseObject object, but in the second example, "Get-HotFix" returns an array of ManagementBaseObject objects. Consider this:
PS F:\Storage\Scripts\Windows\AD> $data = Get-HotFix
PS F:\Storage\Scripts\Windows\AD> $data1 = Get-HotFix -Id KB976902
PS F:\Storage\Scripts\Windows\AD> $data.gettype()

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array


PS F:\Storage\Scripts\Windows\AD> $data1.gettype()

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True ManagementObject System.Management.ManagementBaseObject
by Lery at 2013-04-05 08:50:53
[quote="nohandle"]$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1
###########################################################

#Modify this varaible with the custom data class guid
$strDataClassGuid = "{49798405-bd7f-43a5-b711-f8a9023320ee}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

#add the same data three times
1…3 | foreach {
#Add new row of data
$objDataRow = $objDataclass.AddRow()
$data = get-wmiobject -query "select name, state from win32_service where Name = 'EFS'"
[array]$dataProperties = $data.psadapted |
Get-Member -MemberType Properties |
where {$_.name -notlike "
*"} |
select -ExpandProperty name

#if there are any properties
if ($dataProperties)
{
for ($index=0; $index -lt $dataProperties.count; $index++)
{
$objDataRow.SetField($index, $data.($dataProperties[$index]))
}
}
}
#Away goes the NSE
$nse
#commented out -----> $nse.SendQueued()


To : {1592B913-72F3-4C36-91D2-D4EDA21D2F96}
Priority : 1
Guid : {30106414-B2A0-4614-9F38-23FBE9B53002}
DefaultResource : System.__ComObject
Xml : <?xml version="1.0"?>
<message>
<to>{1592B913-72F3-4C36-91D2-D4EDA21D2F96}</to>
<priority>1</priority>
<msgId>{30106414-B2A0-4614-9F38-23FBE9B53002}</msgId>
<time>20130405163127.324000-120</time>
<from>
<resource typeGuid="{493435F7-3B17-4C4C-B07F-C23E7AB7781F}" guid="{8A3E1EA9-46
96-400E-A230-EA60A60A36F5}" name="fqdn-edited—1">
<key name="name.domain" value="fqdn-edited—"/>
<key name="fqdn" value="fqdn-edited—"/>
<key name="uniqueid" value="UbpWutfzfzSwi/SilxS/4A=="/>
<key name="uniqueid" value="6qhWRcgoQZjCCxkmRqJuiw=="/>
</resource>
</from>
<body>
<inventory>
<dataClass guid="{49798405-bd7f-43a5-b711-f8a9023320ee}">
<data>
<resource partialUpdate="false">
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
</resource>
</data>
</dataClass>
</inventory>
</body>
</message>

XmlBody : <body>
<inventory>
<dataClass guid="{49798405-bd7f-43a5-b711-f8a9023320ee}">
<data>
<resource partialUpdate="false">
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
<row c0="EFS" c1="Stopped" hash="NFbNtyk03WIju9nHKeS4fQ=="/>
</resource>
</data>
</dataClass>
</inventory>
</body>

Hash : aWwAqFN48hqX6XyP4ad/FQ==


Iterating on the addRow, setField adds more rows. This is the output you are after? (with correct data of course)[/quote]

Yes, that would be the correctly formatted data.
by nohandle at 2013-04-06 01:17:42
If the previous was correct then this should give you what you need:
$query = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |
Get-ItemProperty |
Where {$.DisplayName} |
Select-Object DisplayName, @{Name='Installed';Expression={"$($
.installdate.Substring(4,2))-$($.installdate.Substring(6,2))-$($.installdate.Substring(0,4))"}} -First 2


$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1

#Modify this varaible with the custom data class guid
$strDataClassGuid = "{49798405-bd7f-43a5-b711-f8a9023320ee}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

$query | foreach {
$objDataRow = $objDataclass.AddRow()

$objDataRow.SetField(0, $.Displayname)
$objDataRow.SetField(1, $
.Installed)
}

$nse
#commented out -----> $nse.SendQueued()
by Lery at 2013-04-06 08:01:23
[quote="nohandle"]If the previous was correct then this should give you what you need:
$query = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |
Get-ItemProperty |
Where {$.DisplayName} |
Select-Object DisplayName, @{Name='Installed';Expression={"$($
.installdate.Substring(4,2))-$($.installdate.Substring(6,2))-$($.installdate.Substring(0,4))"}} -First 2


$nse = New-Object -ComObject Altiris.AeXNSEvent
$nse.To = "{1592B913-72F3-4C36-91D2-D4EDA21D2F96}"
$nse.Priority = 1

#Modify this varaible with the custom data class guid
$strDataClassGuid = "{49798405-bd7f-43a5-b711-f8a9023320ee}"

$objDCInstance = $nse.AddDataClass($strDataClassGuid)
$objDataclass = $nse.AddDataBlock($objDCInstance)

$query | foreach {
$objDataRow = $objDataclass.AddRow()

$objDataRow.SetField(0, $.Displayname)
$objDataRow.SetField(1, $
.Installed)
}

$nse
#commented out -----> $nse.SendQueued()
[/quote]

Success! Thank you. It worked perfectly. Now I just need to digest what you did. It’s interesting to see that position of the code did not matter. You have the actual query running first. I was connecting to the COM object first. Thanks again.
by nohandle at 2013-04-06 08:17:16
Nothing special really. Just get the data into the query variable. Create the "nse" object. add a data class. then for each item (software info) in the query variable add one row and fill it with data.