Getting No Output from my Powershell Functions - powershell

Sorry if you have seen this code but I did make some tweaks after I accepted the answer and got some interesting results and wasn't able to reopen previous thread for continuance.
My powershell seems to be running but the function calls are producing no result after $filestore in function execute. What is going on? Are my functions not reading the inputs due to lack of global variables?
$filestore = Import-Excel 'C:\594 Sample of Filestore.xlsx'
function Import-Excel
{
param (
[string]$FileName,
[string]$WorksheetName,
[bool]$DisplayProgress = $true
)
if ($FileName -eq "") {
throw "Please provide path to the Excel file"
Exit
}
if (-not (Test-Path $FileName)) {
throw "Path '$FileName' does not exist."
exit
}
$FileName = Resolve-Path $FileName
$excel = New-Object -com "Excel.Application"
$excel.Visible = $false
$workbook = $excel.workbooks.open($FileName)
if (-not $WorksheetName) {
Write-Warning "Defaulting to the first worksheet in workbook."
$sheet = $workbook.ActiveSheet
} else {
$sheet = $workbook.Sheets.Item($WorksheetName)
}
if (-not $sheet)
{
throw "Unable to open worksheet $WorksheetName"
exit
}
$sheetName = $sheet.Name
$columns = $sheet.UsedRange.Columns.Count
$lines = $sheet.UsedRange.Rows.Count
Write-Warning "Worksheet $sheetName contains $columns columns and $lines lines of data"
$fields = #()
for ($column = 1; $column -le $columns; $column ++) {
$fieldName = $sheet.Cells.Item.Invoke(1, $column).Value2
if ($fieldName -eq $null) {
$fieldName = "Column" + $column.ToString()
}
$fields += $fieldName
}
$line = 2
for ($line = 2; $line -le $lines; $line ++) {
$values = New-Object object[] $columns
for ($column = 1; $column -le $columns; $column++) {
$values[$column - 1] = $sheet.Cells.Item.Invoke($line, $column).Value2
}
$row = New-Object psobject
$fields | foreach-object -begin {$i = 0} -process {
$row | Add-Member -MemberType noteproperty -Name $fields[$i] -Value $values[$i]; $i++
}
$row
$percents = [math]::round((($line/$lines) * 100), 0)
if ($DisplayProgress) {
Write-Progress -Activity:"Importing from Excel file $FileName" -Status:"Imported $line of total $lines lines ($percents%)" -PercentComplete:$percents
}
}
$workbook.Close()
$excel.Quit()
}
function FindFiles {
param(
[string]$filestore
)
$length = $filestore.Length
$GuidArray = #()
for($line=0;$line -le $filestore.Count;$line++){
$check = $filestore[$line]
echo $check
$length2 = $check.Length
$fileGuid = $check | ForEach-Object{$_.FileGuid}
$GuidArray = $GuidArray + $fileGuid
}
write-host "-------------------------------------------------------------" -ForegroundColor Yellow
$filepath = Read-Host " Please Enter File Path to Search"
for ($counter=0;$counter -lt $GuidArray.Count;$counter++){
$fileArray = #()
$guidcheck = $GuidArray[$counter]
$file = Get-ChildItem -Recurse -Force $filePath -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -like "*$guidcheck*") } | Select-Object Directory,Name| Format-Table -AutoSize
$fileArray += $file
}
Write-Output $fileArray
}
function CopyFiles {
param(
[string]$fileArray
)
for ($counter = 0;$counter -lt $fileArrray.Count;$counter++){
echo $fileArray[$counter]
#Copy-Item
}
}
function execute {
$filestore = Import-Excel 'C:\594 Sample of Filestore.xlsx'
echo $filestore
$fileArray = #(FindFiles($fileArray))
echo "test"
echo $fileArray
#CopyFiles($fileArray)
}

At the end of FindFiles add this line:
Write-Output $GuidArray
This returns that variable to the standard output stream (the pipeline).
Similarily at the end of FindFiles2 you need to do:
Write-Output $fileArray

Related

Find and Replace multi-line string

I'm trying to find a string and add the string needed for a program.
I need the code to look to see if the action = run fast already exists and if so do nothing.
$Input = GetContent "${Env:ProgramFiles}\myprogram\file.conf"
$replace = #"
[MyAction_Log]
action = run fast
"#
$Input -replace ('action = run fast') -replace ('\[MyAction_Log\]',$replace) | set-content "${Env:ProgramFiles}\myprogram\file.conf"
I would check before wantonly replacing things you think exist. Also, never use $Input as a variable name; it's an automatic variable and won't do what you think it will (treat it as read-only).
$path = "$Env:ProgramFiles\prog\file.conf"
$file = Get-Content -Path $path
$replacementString = #'
[MyAction_Log]
action = run fast
'#
if ($file -notmatch 'action\s=\srun\sfast')
{
$file -replace '\[MyAction_Log\]', $replacementString |
Set-Content -Path $path
}
An alternative that's able to cope with the action key being located anywhere in the [MyAction_Log] section
$Inside = $False
$Modified = $False
$Path = "$( $env:ProgramFiles )\prog\file.conf"
$NewLines = Get-Content $Path |
ForEach-Object {
if( $_.Trim() -like "[*]" ) { $Inside = $False }
if( $_.Trim() -like "*[MyAction_Log]*" ) { $Inside = $True }
If( $Inside -and $_ -like "action = *" -and $_ -notlike "*run fast*" ) { $Modified = $True; "action = run fast" } else { $_ }
}
If( $Modified ) { $NewLines | Set-Content $Path }

How to Return Value to use in another function powershell

In the below code I am having trouble understanding why when I return FileArray why my other function is returning it as being empty?
I am looking to use copyfiles with FileArray. Am I just supposed to put all the steps into one huge function?
function Import-Excel
{
param (
[string]$FileName,
[string]$WorksheetName,
[bool]$DisplayProgress = $true
)
if ($FileName -eq "") {
throw "Please provide path to the Excel file"
Exit
}
if (-not (Test-Path $FileName)) {
throw "Path '$FileName' does not exist."
exit
}
$FileName = Resolve-Path $FileName
$excel = New-Object -com "Excel.Application"
$excel.Visible = $false
$workbook = $excel.workbooks.open($FileName)
if (-not $WorksheetName) {
Write-Warning "Defaulting to the first worksheet in workbook."
$sheet = $workbook.ActiveSheet
} else {
$sheet = $workbook.Sheets.Item($WorksheetName)
}
if (-not $sheet)
{
throw "Unable to open worksheet $WorksheetName"
exit
}
$sheetName = $sheet.Name
$columns = $sheet.UsedRange.Columns.Count
$lines = $sheet.UsedRange.Rows.Count
Write-Warning "Worksheet $sheetName contains $columns columns and $lines lines of data"
$fields = #()
for ($column = 1; $column -le $columns; $column ++) {
$fieldName = $sheet.Cells.Item.Invoke(1, $column).Value2
if ($fieldName -eq $null) {
$fieldName = "Column" + $column.ToString()
}
$fields += $fieldName
}
$line = 2
for ($line = 2; $line -le $lines; $line ++) {
$values = New-Object object[] $columns
for ($column = 1; $column -le $columns; $column++) {
$values[$column - 1] = $sheet.Cells.Item.Invoke($line, $column).Value2
}
$row = New-Object psobject
$fields | foreach-object -begin {$i = 0} -process {
$row | Add-Member -MemberType noteproperty -Name $fields[$i] -Value $values[$i]; $i++
}
$row
$percents = [math]::round((($line/$lines) * 100), 0)
if ($DisplayProgress) {
Write-Progress -Activity:"Importing from Excel file $FileName" -Status:"Imported $line of total $lines lines ($percents%)" -PercentComplete:$percents
}
}
$workbook.Close()
$excel.Quit()
}
function FindFiles {
param(
[string]$fiestore
)
$length = $filestore.Length
$GuidArray = #()
for($line=0;$line -le $filestore.Count;$line++){
$check = $filestore[$line]
$length2 = $check.Length
echo $check
$fileGuid = $check | ForEach-Object{$_.FileGuid}
$GuidArray = $GuidArray + $fileGuid
}
write-host "-------------------------------------------------------------" -ForegroundColor Yellow
$filepath = Read-Host " Please Enter File Path to Search"
for ($counter=0;$counter -lt $GuidArray.Count;$counter++){
$fileArray = #()
$guidcheck = $GuidArray[$counter]
echo $guidcheck
$file = Get-ChildItem -Recurse -Force $filePath -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -like "*$guidcheck*") } | Select-Object Directory,Name| Format-Table -AutoSize
$fileArray += $file
}
echo $fileArray
return $fileArray
}
function CopyFiles {
param(
[string]$filearray
)
echo $fileArray
for($counter = 0;$counter -lt $filearrray.Count;$counter++){
echo $filearray[$counter]
#Copy-Item
}
}
function execute {
$filestore = Import-Excel 'C:\594 Sample of Filestore.xlsx'
$fileArray = #()
FindFiles($filestore)
echo $fileArray
CopyFiles($fileArray)
}
$fileArray doesn't become available outside of the Function by doing Return, but you could make it accessible outside of the function by defining it with a Global scope (although this is not best practice): Return $Global:fileArray.
Instead, it becomes the value of the Function call itself, so in Execute you could do:
$filestore = Import-Excel 'C:\594 Sample of Filestore.xlsx'
$fileArray = #(FindFiles($filestore))
echo $fileArray
CopyFiles($fileArray)
However I think you also need to remove any echo statements from within the FindFiles function or they may be returned as well.
Note: This is untested code.

How to loop in powershell where loop value is combination of string and variable

$A1= get-content -path "File path a1"
$B1= get-content -path "File path b1"
$A2= get-content -path "File path a2"
$B2= get-content -path "File path B2"
$A3= get-content -path "File path a3"
$B3= get-content -path "File path B3"
#I want to select A.i and B.i in each loop
while ($i -le 5)
{
foreach ($line1 in "What to put here"))
{
$found = $false
foreach ($line2 in "What to put here"))
{
if ($line1 -eq $line2)
{
write-host "Do something"
}
}
I want to know what should I use in "what to put here" so that
a) first loop select a1 and b1 files
b) second loop selects a2 and b2 files
and so on
Hello,
The below code is taking too long for large files to print whats different in each file. Can you suggest some optimization?
$i = 1
while ($i -le 7)
{
$t1 = Get-Content -Path $(($oldpath) +($(Get-Variable "F$i").Value) +($Format))
$t2 = Get-Content -Path $(($NEWpath) +($(Get-Variable "F$i").Value) +($Format))
$list1 = new-object 'system.collections.generic.list[string]'
$list2 = new-object 'system.collections.generic.list[string]'
$listshared = new-object 'system.collections.generic.list[string]'
$found = $false
foreach ($line1 in $t1)
{
$found = $false
foreach ($line2 in $t2)
if (-not $found)
{
$list1.add($line1)
}
}
foreach ($line2 in $t2)
{
$found = $false
foreach ($line1 in $t1)
if (-not $found)
{
$list2.add($line2)
}
}
Write-Host "Things only in new txt file:" -foreground "magenta"
$list1
Write-Host "Things only in old txt file:" -foreground "magenta"
$list2
Remove-Variable "t1"
Remove-Variable "t2"
$i++
}
You can use for example:
Get-Variable -Name "A$i" |select Value
but it seems like a bad practice to use a variable for each file...
But you did not specify if you compare paths or files.
If files, combine with Get-Content.
UPDATE:
$i=1
while ($i -le 5)
{
$file1=Get-Content -Path $($(Get-Variable "A$i").Value)
$file2=Get-Content -Path $($(Get-Variable "B$i").Value)
foreach ($line1 in $file1)
{
$found = $false
foreach ($line2 in $file2)
{
if ($line1 -eq $line2)
{
write-host "Do something"
}
}
}
Remove-Variable "file1"
Remove-Variable "file2"
$i++
}
This is the version without Get-Content at every variable

Powershell - Read and Move mails to archive folder

Problem:
Outlook:Cannot move read e-mail to Archive folder.
Tried several options I found on the web but all to no avail... Anyone? :D
I already removed the .move property as it was not working, so please don't fuss about that.
Any help will be much appreciated!
Code:
start Outlook
Function Get-OutlookInBox
{
Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$outlook = new-object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
$folder.items |
Select -Property Subject, ReceivedTime, Importance, SenderName, body
} #end function Get-OutlookInbox
###################################################################################
cls
try {
$switches = get-outlookinbox | where subject -eq "Ip was blocked"
$e = $switches.body
$e = $e -replace 'Blocked IP:| for agent| |:\d{1,2}'
}
catch {
$switches = "Fail"
}
$f = $e |select -Unique |sort
ni $File -type file
$f | ac $File
(gc $File) | ? {$_.trim() -ne "" } | sc $File
$IPCount = (gc $File)
$IPCount = $IPCount.count
$index=0;
#Mark mails as read and delete.
function display( [string]$subject, [string]$color , [string]$out) {
# REQUIRED LENGTH OF STRING
$len = 20
# STRINGS THAT ARE LONGER WILL BE CUT DOWN,
# STRINGS THAT ARE TO SHORT WILL BE MADE LONGER
if ( $subject.length -lt 20 ){
$toadd=20-$subject.length;
for ( $i=0; $i -lt $toadd; $i++ ){
$subject=$subject+" ";
}
$len = $subject.length
}
else { $len = 20 }
$index=$index+1
Write -ForegroundColor $color -nonewline " |" ((($subject).ToString()).Substring(0,$len)).ToUpper()
}
$outlook = new-object -comobject outlook.application
#Define folders
$namespace = $outlook.GetNameSpace("MAPI")
$pst = $namespace.Stores
$pstRoot = $pst.GetRootFolder()
$pstFolders = $pstRoot.Folders
$Archive = $namespace.Folders | ?{$_.name -match "Archive"}
$DefaultFolder = $namespace.GetDefaultFolder(6)
$InboxFolders = $DefaultFolder.Folders
$DeletedItems = $namespace.GetDefaultFolder(3)
$Emails = $DefaultFolder.Items
#For($i=($emails.count-1);$i -ge 0;$i--){
# $($emails)[$i].Unread = $false
# $($emails)[$i].delete()
#}
For($i=($emails.count-1);$i -ge 0;$i--){
$($emails)[$i].Unread = $false
$($emails)[$i].move($Archive.Folders.Item("Inbox<Archive>"))
}
That's a different way to get the folders than I'm used to using. This should do it for you though:
$Archive = $namespace.Folders | ?{$_.name -match "Archive"}
And then in your For loop if you want to move it to your Inbox in the Archives you can do this:
For($i=($emails.count-1);$i -ge 0;$i--){
$($emails)[$i].Unread = $false
$($emails)[$i].move($Archive.Folders.Item("Inbox"))
}
If you want a subfolder you add more .Folders.Item("<Subfolder Name>) on after ("Inbox")

powershell edit file write in the middle

I want to create a powershell script that will edit a config file (apache httpd.conf) and if I find
#keyword
some data
#keyword
the I replace the data between the #keyword else I add the #keywords with the data.
Can someone give me some help
Thank you
$fileName = "..\..\apache\conf\extra\httpd-vhosts.conf"
$found = $false
$contains = $false
$kw = "##xceed.localhost"
$text = "A
BBBB
C"
(Get-Content ( $fileName )) |
Foreach-Object{
if($_ -match $kw)
{
if($found -eq $false)
{
$found=$true
}else
{
$found=$false
}
if($found -eq $true)
{
$contains=$true
#Add Lines after the selected pattern
$kw
$text
}
}
if($found -ne $true)
{
$_
}
} | Set-Content( $fileName )
if($contains -eq $false)
{
$value=($kw+"`r`n"+$text+"`r`n"+$kw)
Add-Content $fileName $value
}