# Returning Data from a PS script

**URL:** <https://forum.ansible.com/t/returning-data-from-a-ps-script/23761>\
**Category:** Ansible Project\
**Created:** [February 17, 2017, 6:13pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761 "2017-02-17T18:13:09Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Strung6013](https://avatars.discourse-cdn.com/v4/letter/s/85f322/32.png) [@Strung6013](https://forum.ansible.com/u/Strung6013)\
**Post date:** [February 17, 2017, 6:13pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/1 "2017-02-17T18:13:09Z")

</div>

Hello all,

I am having an issue to where I am executing a powershell script on a group of hosts and cannot get the data to be returned in the way that I want it so that I can iterate over it further down in my playbook. I am pretty sure that I need to build the JSON object in powershell before I return it, but it’s just not working. Please feel free to ask me for any clarification and I will be glad to try and provide any info needed.

---

<div class="post-metadata">

**Author:** ![j.r.hawkesworth](https://avatars.discourse-cdn.com/v4/letter/j/a3d4f5/32.png) [@j.r.hawkesworth](https://forum.ansible.com/u/j.r.hawkesworth)\
**Post date:** [February 18, 2017, 7:16am UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/2 "2017-02-18T07:16:05Z")

</div>

Best way to so this is to write a module. This isn't as hard as it might sound. Have a look at win\_environment.ps1 it's only about 30 lines of code. First bit checks the module parameters and sets up a $results variable, then the module does its thing and either returns a failure or adds info the the $results variable and completes, passing the results back to the ansible controller where they can be registered and used later in your playbook.

If you still want to write a script, most likely thing that might be messing things up is the fact that you need to be aware that PowerShell has the concept of an output pipe which can contain objects of varying types, and by default many PowerShell built in functions (also called CmdLets) default to sending objects to the output pipe. That's why sometimes you will see

> Out-Null

on the ends of some lines of the module code. Thus throws away unwanted objects and lets you control what is in the output pipe, so that only the things you need are converted into json to be returned to the ansible controller.

Hope this helps,

Jon

---

<div class="post-metadata">

**Author:** ![Strung6013](https://avatars.discourse-cdn.com/v4/letter/s/85f322/32.png) [@Strung6013](https://forum.ansible.com/u/Strung6013)\
**Post date:** [February 20, 2017, 2:30pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/3 "2017-02-20T14:30:42Z")

</div>

Before you had sent the message back I think we got started along the right path there. I’m sure there are some things we aren’t doing correctly, but would appreciate your input to help with this. I think we might have a working prototype soon, and once we get it going, then I think it could potentially be extended to become an extras module. Maybe that’s just me being hopeful, but I do think it would be extendable in that manner.

---

<div class="post-metadata">

**Author:** ![Strung6013](https://avatars.discourse-cdn.com/v4/letter/s/85f322/32.png) [@Strung6013](https://forum.ansible.com/u/Strung6013)\
**Post date:** [February 20, 2017, 5:57pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/4 "2017-02-20T17:57:57Z")

</div>

Maybe I was a tad over zealous in my last post. Basically what I am trying to do is gather a bunch of entries about multiple files such that I get the following information returned so that I can then iterate over it and call a different module using the “path” and gather the information using win\_file\_version.

{  
“name”: “Create USB Recovery”,  
“path”: “C:\Windows\System32\RecoveryDrive.exe”  
},  
{  
“name”: “Task Manager”,  
“path”: “C:\WINDOWS\system32\taskmgr.exe”

},

I have looked at the win\_environment.ps1 file, but I don’t see that it adds multiple entries to the returned data. I know I am doing a pisspoor excuse explaining what I am trying to do, but any help could be appreciated.

---

<div class="post-metadata">

**Author:** ![Strung6013](https://avatars.discourse-cdn.com/v4/letter/s/85f322/32.png) [@Strung6013](https://forum.ansible.com/u/Strung6013)\
**Post date:** [February 20, 2017, 9:26pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/5 "2017-02-20T21:26:15Z")

</div>

So here is the script that I am trying to do. rough form of it is

query installed programs  
get display name and target\_exe  
add to variable to be returned by module  
iterate over returned paths and do win\_file\_version on target\_exe

Rough code as of now is…

`

#!powershell

# WANT\_JSON

# POWERSHELL\_COMMON

$path = “C:\ProgramData\Microsoft\Windows\Start Menu\Programs”  
$items = Get-ChildItem -Recurse -Path $path -Include \*.lnk  
$Shell = New-Object -ComObject WScript.Shell  
$result = @{  
changed = $false  
installed\_progs = @{}  
}  
$intalled\_programs = New-Object System.Collections.Arraylist

foreach ($item in $items) {

$object = new-object psobject @{  
name = $item.BaseName.tolower()  
path = $Shell.CreateShortcut($item).targetpath.tolower()  
}

if ($object.path.endswith(‘exe’)) {  
$result.installed\_progs.add($item.BaseName.toLower(), $Shell.CreateShortcut($item).targetpath.tolower())  
}  
}

[Runtime.InteropServices.Marshal]::ReleaseComObject($Shell) | Out-Null  
Exit-Json $result

`

---

<div class="post-metadata">

**Author:** ![Strung6013](https://avatars.discourse-cdn.com/v4/letter/s/85f322/32.png) [@Strung6013](https://forum.ansible.com/u/Strung6013)\
**Post date:** [February 20, 2017, 9:28pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/6 "2017-02-20T21:28:51Z")

</div>

Didn’t state explicitly, but the code above is not working and is the Module that I am trying to get integrated.

---

<div class="post-metadata">

**Author:** ![Paul\_Markham](https://avatars.discourse-cdn.com/v4/letter/p/9d8465/32.png) [@Paul\_Markham](https://forum.ansible.com/u/Paul_Markham)\
**Post date:** [February 20, 2017, 10:12pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/7 "2017-02-20T22:12:12Z")

</div>

I don’t know anything about Power Shell, but to return variables to Ansible, you need to return them in JSON format under the ‘ansible\_facts’ key. See [http://docs.ansible.com/ansible/dev\_guide/developing\_modules\_general.html#module-provided-facts](http://docs.ansible.com/ansible/dev_guide/developing_modules_general.html#module-provided-facts)

---

<div class="post-metadata">

**Author:** ![Strung6013](https://avatars.discourse-cdn.com/v4/letter/s/85f322/32.png) [@Strung6013](https://forum.ansible.com/u/Strung6013)\
**Post date:** [February 22, 2017, 1:53pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/8 "2017-02-22T13:53:32Z")

</div>

So here’s the script and data as I have them and while not 100% correct with the output it’s close enough until I can figure it out properly.

`

#!powershell

# WANT\_JSON

$path = “C:\ProgramData\Microsoft\Windows\Start Menu\Programs”  
$items = Get-ChildItem -Recurse -Path $path -Include \*.lnk  
$Shell = New-Object -ComObject WScript.Shell  
$result = @{  
changed = $false  
installed\_progs = @()  
}

foreach ($item in $items) {

$object = new-object psobject @{  
name = $item.BaseName.tolower()  
path = $Shell.CreateShortcut($item).targetpath.tolower()  
}

if ($object.path.endswith(‘exe’) -and $object.path -like “_Program_”) {  
$result.installed\_progs+=$object  
}  
}

[Runtime.InteropServices.Marshal]::ReleaseComObject($Shell) | Out-Null

echo $result | convertto-json -compress -depth 99

`

and the play that I run to get the data out as I am doing it via module

`

---

<div class="post-metadata">

**Author:** ![Strung6013](https://avatars.discourse-cdn.com/v4/letter/s/85f322/32.png) [@Strung6013](https://forum.ansible.com/u/Strung6013)\
**Post date:** [February 22, 2017, 1:56pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/9 "2017-02-22T13:56:57Z")

</div>

and the final output of the bottom part of the play to output the gathered data

`

ok: [REMOVED] =\> (item={u’\_ansible\_parsed’: True, u’changed’: False, u’\_ansible\_no\_log’: False, u’\_ansible\_item\_result’: True, u’win\_file\_version’: {u’file\_private\_part’: u’0’, u’file\_build\_part’: u’0’, u’file\_version’: u’2, 3, 0, 0’, u’product\_version’: u’2.3 beta 2’, u’path’: u’c:\program files\teracopy\teracopy.exe’, u’file\_major\_part’: u’2’, u’file\_minor\_part’: u’3’}, u’item’: {u’path’: u’c:\program files\teracopy\teracopy.exe’, u’name’: u’teracopy’}, u’invocation’: {u’module\_name’: u’win\_file\_version’}}) =\> {  
“\<type ‘dict’\>”: “VARIABLE IS NOT DEFINED!”,  
“item”: {  
“changed”: false,  
“invocation”: {  
“module\_name”: “win\_file\_version”  
},  
“item”: {  
“name”: “teracopy”,  
“path”: “c:\program files\teracopy\teracopy.exe”  
},  
“win\_file\_version”: {  
“file\_build\_part”: “0”,  
“file\_major\_part”: “2”,  
“file\_minor\_part”: “3”,  
“file\_private\_part”: “0”,  
“file\_version”: “2, 3, 0, 0”,  
“path”: “c:\program files\teracopy\teracopy.exe”,  
“product\_version”: “2.3 beta 2”  
}  
}  
}

`

---

<div class="post-metadata">

**Author:** ![Paul\_Markham](https://avatars.discourse-cdn.com/v4/letter/p/9d8465/32.png) [@Paul\_Markham](https://forum.ansible.com/u/Paul_Markham)\
**Post date:** [February 22, 2017, 9:06pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/10 "2017-02-22T21:06:02Z")

</div>

You need to return your variables under the “ansible\_facts” key. Something like:

`{ "changed": false, "ansible_facts": { "applications": { "installed_progs": [ { "name": "7-zip file manager", "path": "c:\\program files\\7-zip\\7zfm.exe" }, } } }`

---

<div class="post-metadata">

**Author:** ![j.r.hawkesworth](https://avatars.discourse-cdn.com/v4/letter/j/a3d4f5/32.png) [@j.r.hawkesworth](https://forum.ansible.com/u/j.r.hawkesworth)\
**Post date:** [February 25, 2017, 6:15pm UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/11 "2017-02-25T18:15:40Z")

</div>

I know i suggested writing a module, but one thing you can do which might be close to what you are trying is using a script to add custom facts to your systems. There's a nice write up of doing this here. [http://hindenes.com/trondsworking/2016/11/05/using-ansible-as-a-software-inventory-db-for-your-windows-nodes/](http://hindenes.com/trondsworking/2016/11/05/using-ansible-as-a-software-inventory-db-for-your-windows-nodes/)  
This might be easier as you don't have to create an entire module.  
As you have seen, you can return data from a script, but by extending facts, it is more straightforward to use the extra info you have gathered later in your playbook.

Hope this helps,

Jon

---

<div class="post-metadata">

**Author:** ![Strung6013](https://avatars.discourse-cdn.com/v4/letter/s/85f322/32.png) [@Strung6013](https://forum.ansible.com/u/Strung6013)\
**Post date:** [February 26, 2017, 9:43am UTC](https://forum.ansible.com/t/returning-data-from-a-ps-script/23761/12 "2017-02-26T09:43:04Z")

</div>

That’s the road I have been digging in to. Been busy with some life things for the past few days. I am going to be able to double down and be able to properly flesh this out. Realistically it should be easy enough(… I hope). Will post back when I can.
