Passing a CSV between multiple PowerShell scripts - powershell

I have a bunch of individual scripts to build various reports based off of a weekly Nessus scan. In each individual script I perform this:
Function Get-FileName($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "csv (*.csv)| *.csv"
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.FileName
}
Clear-Host
# Get the scan CSV
$inputData = Get-FileName "C:\users\$env.username\Downloads"
$data = Import-Csv $inputData
From here I do whatever work necessary in the individual script. I'd like to set it up to where I grab the file once and just pass the CSV between scripts:
$data = Import-Csv $inputData
#Call Installed Software script
". .\Build Software List (Test).ps1 $data"
#Call Most Prolific Vulnerabilities
#This continues until I've called all scripts
I've tried a few different ways to pass the CSV but none have worked yet. Can someone clue me in on what I'm missing?
Thanks!

In Build Software List (Test).ps1, make sure a positional parameter will accept the input:
param(
[Parameter(Mandatory=$true,Position=0)]
[psobject[]]$Data
)
# process items in $Data here
Then invoke it like:
& '.\Build Software List (Test).ps1' $Data
If you remove the spaces in the file name, you can void the call operator (&) and quotes:
.\Build-SoftwareList.ps1 $Data

I don't think you want to dot-source here.
Replace this line:
#Call Installed Software script
". .\Build Software List (Test).ps1 $data"
With:
#Call Installed Software script
& ".\Build Software List (Test).ps1" $data
This tells powershell to execute the script with the arguments, instead of importing it as part of the currently running script.
However, even if you did this, it would try and add the data to the argument list. Since $data is an object, and not a filename, you will probably want to use the pipeline instead:
$data | & ".\Build Software List (Test).ps1"

Related

How to use Aspose Cells dll in Powershell Script

I'm new to powershell, I want to perform some operations on excel. I'm able to do that by using Com Object. But i dont want to use Com Object , instead of that im trying to use aspose cells dll.
Could you please help how can i import or add this dll in my powershell script.
Below is code by using Com Object , i want to re-write it using aspose dll.
$Source = 'D:\Test' # the path to where the Excel files are
# create an Excel COM object
$excel = New-Object -ComObject Excel.Application
# find Excel files in the Source path and loop through.
# you may want to add the -Recurse switch here if the code should also look inside subfolders
$result = Get-ChildItem -Path $Source -Filter '*.xlsx' -File | ForEach-Object {
$workBook = $excel.Workbooks.Open($_.FullName)
$workSheet = $Workbook.Sheets.Item(1)
$count = 0
$label = $workSheet.Range('$A:$B').Find('*Animal count:*')
if ($label) {
# get the numeric value for the cell next to the label
# empty cells will translate to 0
$count = [int]$workSheet.Cells.Item($label.Row, $label.Column +2 ).Value()
}
# output a PSObject with the full filename and the animal count value
[PsCustomObject] #{
'File' = $_.FullName
'AnimalCount' = $count
}
$workBook.Close()
}
# quit Excel and clean up the used COM objects
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workSheet) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workBook) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
# output on screen
$result | Format-Table -AutoSize
#output to CSV file
$result | Export-Csv -Path 'D:\Test\AnimalCount.csv' -UseCulture -NoTypeInformation
e
Generally, you can use .NET libraries in PowerShell. Aspose.Cells for .NET is written in managed C#.NET, so it is a .NET assembly that can also be used in PowerShell environment (just to similar way as you use a custom .NET library) using standard approach. For example, please visit this link on how to use a .NET assembly in PowerShell. Please note, you have to accommodate/convert to PowerShell scripts by yourself.
Regarding your COM interop. sample code segments, please visit the following documents’ links using Aspose.Cells APIs for your reference for different tasks you are performing:
e.g.
(How to open different MS Excel file formats.)
https://docs.aspose.com/display/cellsnet/Opening+Different+Microsoft+Excel+Versions+Files
(How to find or search data in the worksheet)
https://docs.aspose.com/display/cellsnet/Find+or+Search+Data
(How to convert to CSV file format)
https://docs.aspose.com/display/cellsnet/Different+Ways+to+Save+Files#DifferentWaystoSaveFiles-SavingTextFileswithCustomSeparator
Hope, this helps a bit.
PS. I am working as Support developer/ Evangelist at Aspose.

PowerShell SFTP Download without Writing Files to Disk

I am trying to use PowerShell to Sync Payroll files stored on SFTP to SharePoint. I have most of the code written, the only thing I can't figure out is if there is a way to avoid temporarily downloading the file to the disk. Given the sensitivity of these files I would rather store the files as a variable not unlike how get-content works so no one on the Jenkins slave would be able to see its content or undelete temp files.
Here is my working code that does download the file:
$session = New-Object WinSCP.Session
$session.Open($sessionOptions)
$file = $session.ListDirectory("/") | select -ExpandProperty files | ? {$_.FileType -ne "D"} | select -First 1
$session.GetFiles($file, "c:\temp\$($file.name)", $False, $transferOptions)
$session.Close()
Is there something I can use in replacement of the second parameter of WinSCP.Session.GetFiles [C:\temp\$($file.name)] that would allow me to drop the file directly into memory so I can turn around and dump the to SharePoint?
If you were wondering how I would then get it into sharepoint I have used this with get-content without issue:
$fileToUpload = get-content c:\temp\test.csv -Encoding Byte
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.Content = $fileToUpload
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.Url = "test.csv"
$Upload = $Folder.Files.Add($FileCreationInfo)
$Ctx.Load($Upload)
$Ctx.ExecuteQuery()
WinSCP simply doesn't do it. I had been hoping for a downstream object to take the replcement of a file path but that does not seem to be possible. However I did figure this out. Moving to the posh-ssh module I was able to use the Get-SFTPContent command which allows me to read in the file to memory.
install-module posh-ssh
import-module posh-ssh
$Session = New-SFTPSession -ComputerName $SFTPHostName -Credential $SFTPcredential
Get-SFTPContent -SessionId $session.SessionId -Path $file.FullName -Encoding unicode -ContentType byte
Streaming a context of a remote file is supported since WinSCP 5.18 beta using the Session.GetFile method.
$stream = $session.GetFile($file)

How can I suppress/hide WMI output when using Setting an object? [duplicate]

I have a PS script:
script.ps1
[System.Xml.XmlDocument] $Config;
function Get-ScriptDirectory
{
Split-Path $script:MyInvocation.MyCommand.Path
}
function Load-Config
{
$configPath = Join-Path (Get-ScriptDirectory) config.xml
$global:Config = [xml](gc $configPath)
}
Load-Config
config.xml
<Configuration>
</Configuration>
Later in the script I'm working with $Config variable. When I run this script it writes the output to the console, which contains the root element of the xml. Something like:
Configuration
--------------
Is there exists any way how to suppress this output?
Thanks.
If you don't want the output of a command to be printed out to the console, you can discard it by piping it or redirecting it to Out-Null. For example both will work:
$Config | Out-Null
$Config > Out-Null
If you're familiar with Unix-like operating systems, Out-Null is conceptually equivalent to /dev/null.
Probably the output isn't caused by the assignment statement (a voidable statement), but by this line:
[System.Xml.XmlDocument] $Config;
In PowerShell, typically, all statements return a value (except for voidable statements). I think that the first time you run the script no output will be written to the console. However on subsequent runs $Config will still contain the value of the previous run, and its value will be written to the screen.
piping to the Out-Null cmdlet:
[System.Xml.XmlDocument] $Config | Out-Null
casting to void:
[void][System.Xml.XmlDocument]$Config
assigning to $null:
$null = $Config
or simply not 'declaring' the $Config variable
are ways to suppress this behaviour.
Somewhere you're dumping the variable from your script. As it falls out of the pipe it gets passed to Out-Host and that will yield the output you see.
The actual solution is to make sure you don't return anything from your script. As I cannot see your code I can't point to where, but somewhere there is a pipeline or statement that leaks the object into output. Are you sure you're using an assignment at every place you need?
A few Options:
# Pipe to the Out-Null cmdlet
$Config | Out-Null
# Cast to void
[void]$Config
# assign to $null
$null = $Config
# redirect to $null
$Config > $null

Use PowerShell to generate a list of files and directories

I'm writing a PowerShell script to make several directories and copy a bunch of files together to "compile" some technical documentation. I'd like to generate a manifest of the files and directories as part of the readme file, and I'd like PowerShell to do this, since I'm already working in PowerShell to do the "compiling".
I've done some searching already, and it seems that I need to use the cmdlet "Get-ChildItem", but it's giving me too much data, and I'm not clear on how to format and prune out what I don't want to get my desired results.
I would like an output similar to this:
Directory
file
file
file
Directory
file
file
file
Subdirectory
file
file
file
or maybe something like this:
+---FinGen
| \---doc
+---testVBFilter
| \---html
\---winzip
In other words, some kind of basic visual ASCII representation of the tree structure with the directory and file names and nothing else. I have seen programs that do this, but I am not sure if PowerShell can do this.
Can PowerShell do this? If so, would Get-ChildItem be the right cmdlet?
In your particular case what you want is Tree /f. You have a comment asking how to strip out the part at the front talking about the volume, serial number, and drive letter. That is possible filtering the output before you send it to file.
$Path = "C:\temp"
Tree $Path /F | Select-Object -Skip 2 | Set-Content C:\temp\output.tkt
Tree's output in the above example is a System.Array which we can manipulate. Select-Object -Skip 2 will remove the first 2 lines containing that data. Also, If Keith Hill was around he would also recommend the PowerShell Community Extensions(PSCX) that contain the cmdlet Show-Tree. Download from here if you are curious. Lots of powerful stuff there.
The following script will show the tree as a window, it can be added to any form present in the script
function tree {
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# create Window
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Files"
$Form.Size = New-Object System.Drawing.Size(390, 390)
# create Treeview-Object
$TreeView = New-Object System.Windows.Forms.TreeView
$TreeView.Location = New-Object System.Drawing.Point(48, 12)
$TreeView.Size = New-Object System.Drawing.Size(290, 322)
$Form.Controls.Add($TreeView)
###### Add Nodes to Treeview
$rootnode = New-Object System.Windows.Forms.TreeNode
$rootnode.text = "Root"
$rootnode.name = "Root"
[void]$TreeView.Nodes.Add($rootnode)
#here i'm going to import the csv file into an array
$array=#(Get-ChildItem -Path D:\personalWorkspace\node)
Write-Host $array
foreach ( $obj in $array ) {
Write-Host $obj
$subnode = New-Object System.Windows.Forms.TreeNode
$subnode.text = $obj
[void]$rootnode.Nodes.Add($subnode)
}
# Show Form // this always needs to be at the bottom of the script!
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
}
tree
In Windows, navigate to the directory of interest
Shift+ right click mouse -> Open PowerShell window here
Get-ChildItem | tree /f > tree.log
The best and clear way for me is:
PS P:\> Start-Transcript -path C:\structure.txt -Append
PS P:\> tree c:\test /F
PS P:\> Stop-Transcript
You can use command Get-ChildItem -Path <yourDir> | tree >> myfile.txt this will output tree-like structure of a directory and write it to "myfile.txt"

How to suppress PowerShell Get-Content output

I have a PS script:
script.ps1
[System.Xml.XmlDocument] $Config;
function Get-ScriptDirectory
{
Split-Path $script:MyInvocation.MyCommand.Path
}
function Load-Config
{
$configPath = Join-Path (Get-ScriptDirectory) config.xml
$global:Config = [xml](gc $configPath)
}
Load-Config
config.xml
<Configuration>
</Configuration>
Later in the script I'm working with $Config variable. When I run this script it writes the output to the console, which contains the root element of the xml. Something like:
Configuration
--------------
Is there exists any way how to suppress this output?
Thanks.
If you don't want the output of a command to be printed out to the console, you can discard it by piping it or redirecting it to Out-Null. For example both will work:
$Config | Out-Null
$Config > Out-Null
If you're familiar with Unix-like operating systems, Out-Null is conceptually equivalent to /dev/null.
Probably the output isn't caused by the assignment statement (a voidable statement), but by this line:
[System.Xml.XmlDocument] $Config;
In PowerShell, typically, all statements return a value (except for voidable statements). I think that the first time you run the script no output will be written to the console. However on subsequent runs $Config will still contain the value of the previous run, and its value will be written to the screen.
piping to the Out-Null cmdlet:
[System.Xml.XmlDocument] $Config | Out-Null
casting to void:
[void][System.Xml.XmlDocument]$Config
assigning to $null:
$null = $Config
or simply not 'declaring' the $Config variable
are ways to suppress this behaviour.
Somewhere you're dumping the variable from your script. As it falls out of the pipe it gets passed to Out-Host and that will yield the output you see.
The actual solution is to make sure you don't return anything from your script. As I cannot see your code I can't point to where, but somewhere there is a pipeline or statement that leaks the object into output. Are you sure you're using an assignment at every place you need?
A few Options:
# Pipe to the Out-Null cmdlet
$Config | Out-Null
# Cast to void
[void]$Config
# assign to $null
$null = $Config
# redirect to $null
$Config > $null