trying to run .bat file along with some conditional loops in a .ps1 file - powershell

i want to run some conditional looping code along with other task like running a .bat file in one .ps1 file. I dont have sound knowledge in poweershell but i am trying to do this.
i tried to run the file but only batch file is executing successfully but not the code that needs to perform a different tasks in the process.
i tried using this command to run .batch file
cmd.exe /k ""c:\Users\ADM_SPANCHADULA\Desktop\status_check\status.bat" & powershell"
which is executing fine. but the remaining part
cd C:\Users\ADM_SPANCHADULA\Desktop\status_check
cmd.exe /c "c:\Users\ADM_SPANCHADULA\Desktop\status_check\status.bat"
"hello world " | Out-Host
$a=0
Do {
$output1 = Compare-Object (get-content "Job_status.txt") (get-content "done.txt")
$output2 = Compare-Object (get-content "Job_status.txt") (get-content "warn.txt")
if ( $output1 = "" ) {
$a = 1
$a|Out-Host
} elseif ( $output2 = "" ) {
$a = 1
$a|Out-Host
} else {
echo "looping "
}
} while ( $a -gt 0 )
is not executing .
can someone please help me out.

Related

Submitting parameters to Invoke-Expression

I've written a sample Powershell Script with name C:\Script\Scrip1.ps1
Below is the code
Function Testfunction(){
Param(
$Node1,
$Node2
)
$SQLNodes = #($Node1, $Node2)
foreach ($node in $SQLNodes)
{
#Some code below is dummy code
"$node" | Out-File C:\File1.txt -Append
}
}
When i try to call this function using invoke-Expression it doesn't work
Used below method with no luck
$string = 'C:\Script\Script1.ps1 Testfunction -Node1 "test" -Node2 "test2"'
Invoke-Expression $string
I have opened a PS Window and ran below command without luck
.\Script1.ps1 -Node1 Hello -Node2 Aquib
or
.\Script1.ps1 Testfunction -Node1 Hello -Node2 Aquib
I do not see any file1 under C:\File1
when when I open the script file and then run the function, it does work and generate the file.
You don't need to use Invoke-Expression in your scenario.
If you want to make Testfunction visible in the current scope, you will need to "dot-source" your script:
PS C:\> . C:\Scripts\Script1.ps1
This executes Script.ps1 in the current scope, which will define Testfunction in the current scope, and then you can run the function:
PS C:\> Testfunction -Node1 "Test1" -Node2 "Test2"
Another alternative is to skip defining Testfunction as a function in a script, and just use it as a script itself:
# Script file
param(
$Node1,
$Node2
)
$SQLNodes = #($Node1, $Node2)
foreach ($node in $SQLNodes) {
#Some code below is dummy code
"$node" | Out-File C:\File1.txt -Append
}
If you name the script Testfunction.ps1, you can run it by typing the script's name:
PS C:\> C:\Scripts\Testfunction.ps1 -Node1 "Test1" -Node2 "Test2"

Strange behavior of PSConsoleReadLine

Trying to seemingly generate text in Powershell console (result predetermined), did not like cls + Write-Host because of constant blinking, tried to use PSConsoleReadLine. Code below works in some situations, while it does not in others.
Code works when:
directly copy pasted into Powershell window
when stored in a script file and the file is called from Powershell window
Code does not work when:
launched in ISE (known issue)
right click on the script file / run with powershell
Tried to get around the error with Add-Type, but it ends with IOException and null reference instead. Is present in code below, but commented.
Tried to write a script in a way that relaunches itself in a new Powershell process to handle it, did not help.
Code itself (probably could reproduce the issue with a single line of code, but the guide says one line of a code is not enough):
function tryOne($oldExpression, $targetExpression, $currentPosition, $src)
{
While($targetExpression[$currentPosition] -cne $triedCharacter)
{
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()#here problem
$triedCharacter = Get-Random -InputObject $src
$expression = $oldExpression + $triedCharacter
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($expression)#here problem
Start-sleep -Milliseconds 50
}
Return $expression
}
cd $PSScriptRoot
#Add-Type -path "C:\Program Files\WindowsPowerShell\Modules\PSReadline\1.2\Microsoft.PowerShell.PSReadLine.dll"
#above helps with not found error, with it uncommented the errors at RevertLine and Insert are IOException and null reference
$targetExpression = "Not ideal"
$oldExpression = ""
$currentPosition = 0
#region AllowedCharacters
$src = New-Object System.Collections.ArrayList
for($i=65;$i-le 90;$i++)
{
$src.Add([char]$i) | Out-Null
}
for($i=97;$i-le 122;$i++)
{
$src.Add([char]$i) | Out-Null
}
for($i=0;$i-le 9;$i++)
{
$src.Add($i) | Out-Null
}
$src.Add(" ") | Out-Null #allowed characters in the target sentence - A-Z, a-z, 0-9, space
#endregion
While($currentPosition -lt ($targetExpression.length))
{
$oldExpression = tryOne $oldExpression $targetExpression $currentPosition $src
$currentPosition++;
}
I'd like to be able to launch the script via right click / run with Powershell.

How do I capture StdOut from External programs from a PowerShell script?

I write VBScript script and often times I need to run a command line program and capture the the information that was written to std out so that output can be scraped. All of this is hidden from the person that executes the VBScript.
Here is an quick and stupid example:
cmd = "ping google.com"
Set objWSH = CreateObject( "WScript.Shell" )
Set Ret = objWSH.exec(cmd)
StdOut = Ret.StdOut.ReadAll()
myarray = Split(StdOut,vbcrlf)
For each line in myarray
If Instr(line,"Average") then avg = Right(line,Len(line) - InStrRev(line," "))
Next
wscript.echo "Google.com = " & avg
My question is not "how do I ping" as I'm showing in my example code.
I need to know how to run command-line programs from within a PowerShell script so that they are not seen but in a way that I can grab the output written to std-out.
Store the result in a variable.
$result = Invoke-Expression 'ping www.google.com'
or
$result = iex 'ping www.google.com'
To be close to your vbscript but with a RegEx:
foreach ($line in (ping.exe google.com)){
if ($line -match 'Average = (\d+)ms'){
"Google.com = $($matches[1])"
}
}
Sample output:
Google.com = 12
A more PowerShell way:
$Avg = (test-connection google.com).responsetime|measure -average|select -expandproperty Average
"Google.com = $Avg"
sample output:
Google.com = 25.25

PowerShell - Sorry, we couldn't find Microsoft.PowerShell.Core\FileSystem::

I'm trying to modify the script created by Boe Prox that combines multiple CSV files to one Excel workbook to run on a network share.
When I run it locally, the script executes great and combines multiple .csv files into one Excel workbook.
Clear-Host
$OutputFile = "ePortalMonthlyReport.xlsx"
$ChildDir = "C:\MonthlyReport\*.csv"
cd "C:\MonthlyReport\"
echo "Combining .csv files into Excel workbook"
. C:\PowerShell\ConvertCSVtoExcel.ps1
Get-ChildItem $ChildDir | ConvertCSVtoExcel -output $OutputFile
echo " "
But when I modify it to run from a network share with the following changes:
Clear-Host
# Variables
$OutputFile = "ePortalMonthlyReport.xlsx"
$NetworkDir = "\\sqltest2\dev_ePortal\Monthly_Report"
$ChildDir = "\\sqltest2\dev_ePortal\Monthly_Report\*.csv"
cd "\\sqltest2\dev_ePortal\Monthly_Report"
echo "Combining .csv files into Excel workbook"
. $NetworkDir\ConvertCSVtoExcel.ps1
Get-ChildItem $ChildDir | ConvertCSVtoExcel -output $OutputFile
echo " "
I am getting an error where it looks like it using the network path twice and I am not sure why:
Combining .csv files into Excel workbook
Converting \sqltest2\dev_ePortal\Monthly_Report\001_StatsByCounty.csv
naming worksheet 001_StatsByCounty
--done
opening csv Microsoft.PowerShell.Core\FileSystem::\sqltest2\dev_ePortal\Monthly_Report\\sqltest2\dev_ePortal\Monthly_Report\001_StatsByCounty.csv) in excel in temp workbook
Sorry, we couldn't find Microsoft.PowerShell.Core\FileSystem::\sqltest2\dev_ePortal\Monthly_Report\\sqltest2\dev_ePortal\Monthly_Report\001_StatsByCounty.csv. Is it possible it was moved, renamed or deleted?
Anyone have any thoughts on resolving this issue?
Thanks,
Because in the script it uses the following regex:
[regex]$regex = "^\w\:\\"
which matches a path beginning with a driveletter, e.g. c:\data\file.csv will match and data\file.csv will not. It uses this because (apparently) Excel needs a complete path, so if the file path does not match, it will add the current directory to the front of it:
#Open the CSV file in Excel, must be converted into complete path if no already done
If ($regex.ismatch($input)) {
$tempcsv = $excel.Workbooks.Open($input)
}
ElseIf ($regex.ismatch("$($input.fullname)")) {
$tempcsv = $excel.Workbooks.Open("$($input.fullname)")
}
Else {
$tempcsv = $excel.Workbooks.Open("$($pwd)\$input")
}
Your file paths will be \\server\share\data\file.csv and it doesn't see a drive letter, so it hits the last option and jams $pwd - an automatic variable of the current working directory - onto the beginning of the file path.
You might get away if you edit his script and change the regex to:
[regex]$regex = "^\w\:\\|^\\\\"
which will match a path beginning with \\ as OK to use without changing it, as well.
Or maybe edit the last option (~ line 111) to say ...Open("$($input.fullname)") as well, like the second option does.
Much of the issues are caused in almost every instance where the script calls $pwd rather than $PSScriptRoot. Replace all instances with a quick find and replace.
$pwd looks like:
PS Microsoft.PowerShell.Core\FileSystem::\\foo\bar
$PSScriptRoot looks like:
\\foo\bar
The second part i fixed for myself is what #TessellatingHeckler pointed out. I took a longer approach.
It's not the most efficient way...but to me it is clear.
[regex]$regex = "^\w\:\\"
[regex]$regex2 = "^\\\\"
$test = 0
If ($regex.ismatch($input) -and $test -eq 0 ) {
$tempcsv = $excel.Workbooks.Open($input)
$test = 1 }
If ($regex.ismatch("$($input.fullname)") -and $test -eq 0) {
$tempcsv = $excel.Workbooks.Open("$($input.fullname)")
$test = 1}
If ($regex2.ismatch($input) -and $test -eq 0) {
$tempcsv = $excel.Workbooks.Open($input)
$test = 1 }
If ($regex2.ismatch("$($input.fullname)") -and $test -eq 0) {
$tempcsv = $excel.Workbooks.Open("$($input.fullname)")
$test = 1}
If ($test -eq 0) {
$tempcsv = $excel.Workbooks.Open("$($PSScriptRoot)\$input")
$test = 0 }

Call powersehell with parameters

I have this in a powershell
if (Test-Path env:\names)
{
[string[]] $names= (dir env:\names).Value.Split(",") | % { $_.Trim() }
} else {
[string[]] $names= "peter","mikael","Anders","William"
}
Write-Host -n "names: " ; [string]$names
If I would like to call it from command prompt is that possible?
I have tried this:
powershell -ExecutionPolicy RemoteSigned -File MainScript.ps1 -PARAM "Peter,Mikael"
I do understand that wont work since I am looking for a env:names but how can I make it work? What I am after is that I would like to send in a parameter with names and that should be caught in something like the code above.
You have a complete mess here. First env:names means value of environment variable names, there shouldn't be \.
Then, if you want you script to accept parameters - just add param(string[] $names) as first line of your script
If you want to run your script with parameters - just start powershell and type: full_path_to_script Peter,Mikael
Like that?
param($name)
if (Test-Path env:\names)
{
$names = $env:names.Split(",") | % { $_.Trim() }
}
else
{
$names = $name.Split(",") | % { $_.Trim() }
}
Write-Host -n "names: $names"