ps1 not giving result in dos shell - powershell

My script....
function DirSize {
BEGIN {}
PROCESS
{
$timer = Get-Date -UFormat "%Y%m%d%H%M%S"
$bFile="C:\00mpd\DR\mrv_incr_"+$timer+".txt"
$data = Get-Content "C:\00mpd\DR\vaults.txt"
write-host $data.count total lines read from file
foreach ($line in $data)
{
write-host $line
$a=0
foreach ($file in (Get-ChildItem $line -recurse -Force| where-object {!($_.psiscontainer)} | where { $_.LastWriteTime -ge ((get-date).AddHours(-1))} ))
{
$a+=$file.length/1GB
}
Write-Output "$line :: $a GB"
"$line :: $a GB"| Out-File $bFile -append
}
}
END {}
} # end function Get-DirSize
vaults.txt contents name of the various folders....
d:\Milind_laptop_backup\DDrive\Milind_pst\
d:\Milind_laptop_backup\DDrive\Office\
d:\Milind_laptop_backup\DDrive\personal\
d:\Milind_laptop_backup\DDrive\ToMilind\
Above ps1 give proper result when running in powershell window. But when I'm running same in dos shell, it's not giving any result.
Powershell commands
PS C:\> . "c:\00mpd\dr\dirsize.ps1"
PS C:\> DirSize
But when I tried in Dos shell, no result is coming out.
C:\00mpd\DR>powershell -File "c:\00mpd\dr\DirSize.ps1"

You are running the script as function
This is OK when you are executing it from Inside PowerShell, The Function DirSize Load it and DirSize to Execute it. but when run it from .ps1 file it just loads the function but not executing it.
To Solve this:
Method 1:
Remove the function DirSize { and the last line } # end function Get-DirSize
Method 2:
Dot Source the .ps1 as a command to load the function then run it after
powershell -Command ". c:\00mpd\dr\DirSize.ps1; DirSize"
As Mathias R. Jessen Suggested

As others have said if you remove
function DirSize{ }
and dot source your script, it will solve one issue.
I would personally then change Write-Output to Write-Host. It should give the result that you are looking for.

Related

How can I write a script that will read other scripts and record their processes?

I have a folder of scripts that are being used for my company, and I need to know what each script does. I am trying to write a script in power shell that will record what each script does into a csv file.
I am a beginner in Powershell and am still learning so I apologize if I am being unclear.
I know that each of these scripts basic function is to map drives to a users computer, but there are too many to go through manually, any advice would be appreciated!
EDIT: Most of them are bat with a couple of vbs too. I want to record what drives are being mapped.
EDIT 2: I have now written my own script that looks like this :
Set-location z:\
get-Childitem "z:\Test"|
Foreach-object{
$filename = $_.Fullname
Get-content $filename|
foreach-object {
if ($_ -match "echo off") {
Write-output "$($filename): $_" | select-object $_ $filename
| export-csv "test.csv" -notypeinformation
}
}
}
I am having trouble exporting the data into a csv file as the error "A positional parameter cannot be found that accepts argument 'z:\Test\Test1.bat'"
The easiest way will be string parsing: look for the commands that map the drives. That's net use for bat files, or MapNetworkDrive in VBS. So look for those lines.
This will look through all the files in a folder and output the filename and the content of the line wherever it finds those lines:
Get-ChildItem "C:\Scripts" |
Foreach-Object {
$filename = $_.FullName
Get-Content $filename |
Foreach-Object {
if ($_ -match "net use" -or $_ -match "MapNetworkDrive") {
Write-Output "$($filename): $_"
}
}
}
That will not likely be exactly what you need, but it should get you started.

Inline command execution in PowerShell ForEach Loop

I am familiar with how BASH syntax handles this request but I am unable to find a way to do this in PowerShell.
BASH Example:
for x in `ls .`; do something with ${x}; done
What I am trying to perform the same thing with PowerShell (which has the incorrect syntax for demonstration purposes)...
ForEach ($group in `$wsus.GetComputerTargetGroups()`)
...I obviously get a syntax error.
BASH to PowerShell translation is the ask here. :D
For the example you have, it would just work (without the backticks):
ForEach ($group in $wsus.GetComputerTargetGroups()) {
# do stuff
}
If it's a command, you can wrap it in a subexpression:
foreach ($process in $(Get-Process)) {
# do stuff
}
You might also look at the ForEach-Object cmdlet which can be more idiomatic in PowerShell's pipelines:
Get-Process | ForEach-Object { Write-Verbose "This process is $_" -Verbose }
This might help you get going...
$things = Get-ChildItem C:\Windows\
foreach ($thing in $things) {
# Do a thing with each one in turn
Write-Host $thing.Name -ForegroundColor Magenta
}

Execute All Functions In A Script

If I have a script with some functions such as:
function FunctionOne{}
function FunctionTwo{}
How can I call them all in one line, in the same script, without having to specify the name of each function?
I'd like to do something like:
Call-AllFunctionsInCurrentScriptConsecutively #calls FunctionOne then FunctionTwo
This blog post suggests using ParseFile() for parsing the script:
$filename = 'C:\path\to\your.ps1'
[ref]$tokens = $null
[ref]$parseErrors = $null
$ast = [Management.Automation.Language.Parser]::ParseFile($filename, $tokens, $parseErrors)
Then you can invoke the functions (after you dot-sourced the script) via the call operator:
$ast.EndBlock.Statements | Where-Object { $_.Name } | ForEach-Object { & $_.Name }
For using this from within a script replace the filename with $MyInvocation.MyCommand.Path.
Parsing the file and grabbing the function names from the AST is probably the most reliable option.
A more low-tech approach would be to simply diff the function list before and after sourcing the script:
$InitialFunctions = Get-ChildItem function: -Name
. C:\path\to\script.ps1
Get-ChildItem function: -Name |Where-Object {$InitialFunctions -notcontains $_} |ForEach-Object {
& $_
}

Get-Content - Get all Content, starting from a specific linenumber

My first question here, and just want to say thanks for all the input I've gotten over the years from this site.
I'm also new to powershell so the answar might be very simple.
I'm working on a Script that ment check a log file every 5 mins. (schedulded from ActiveBatch).
At the moment the script is searching for ERROR in a logfile. And it works fine.
But my problem is that the script searches the entire file throgh every time. So when an ERROR do occur, the check "fails" every 5 minutes the rest of the day. Untill a new logfile is generated.
My script:
Write-Host Opretter variabler...
$file = "${file}"
$errorString = "${errorString}"
Write-Host file variable is: $file
Write-Host errorString variable is: $errorString
Write-Host
Write-Host Select String Results:
$ssResult = Get-Content $file | Select-String $errorString -SimpleMatch
Write-Host
Write-Host There was $ssResult.Count `"$errorString`" statements found...
Write-Host
IF ($ssResult.Count -gt 0) {Exit $ssResult.Count}
So what i would like, is to Find the ERROR, and then Remeber the Linenumber (Perhaps in a file). Then in the next run (5minutes later) i want to start the search from that line.
for example. And error is found on line 142, the Script exits with error code 142. five minutes later the script is run again, and it should start from line 143, and go through the rest of the file.
You can remember number of error strings found in file:
$ssResult.Count > C:\path\to\file.txt
Then number of new erros is:
$errorCount = $ssResult.Count - (Get-Content C:\path\to\file.txt)
Remember to set the value in file to zero on first run of script and every time a new logfile is generated.
You basically gave a pretty good description of how it will work:
Read the last line number
$if (Test-Path $Env:TEMP\last-line-number.txt) {
[int]$LastLineNumber = #(Get-Content $Env:TEMP\last-line-number.txt)[0]
} else {
$LastLineNumber = 0
}
Read the file
$contents = Get-Content $file
Find the first error starting at $LastLineNumber (one of the rare cases where for is appropriate in PowerShell, lest we want to create nicer objects)
for ($i = $LastLineNumber; $i -lt $contents.Count; $i++) {
if ($contents[$i] -like "*$errorString*") {
$i + 1 > $Env:TEMP\last-line-number.txt
exit ($i + 1)
}
}
Select-String returns matchinfo objects, which have the line number, so you can should be able to do something like this:
$lasterror = Get-Content $lasterrorfile
$newerrors = select-string -Path $file -Pattern $errorstring -SimpleMatch |
where $_.LineNumber -gt $lasterror
Write-Host "$($newerrors.count) found."
if ($newerrors.count)
{$newerrors[-1].LineNumber | Set-Content $lasterrorfile}
So this is my final Script, Thanks Dano. I'm sure the Day-Reset thing can be done smarter, but this seems to work :)
#logic for Day-Reset
Write-Host checking if its a new day...
$today = Get-Date -format dddd
$yesterday = Get-Content $ENV:TEMP\${adapterName}_yesterday.txt
Write-Host today variable is: $today
Write-Host yesterday variable is: $yesterday
Write-Host
IF ($today.CompareTo($yesterday))
{
Get-Date -format dddd > $ENV:TEMP\${adapterName}_yesterday.txt
0 > $ENV:TEMP\${adapterName}_numberofErrors.txt
}
Write-Host Setting variables...
$file = "${file}"
$errorString = "${errorString}"
Write-Host file variable is: $file
Write-Host errorString variable is: $errorString
Write-Host
Write-Host Select String Results:
$ssResult = Get-Content $file | Select-String $errorString -SimpleMatch
Write-Host There was $ssResult.Count `"$errorString`" statements found...
$errorCount = $ssResult.Count - (Get-Content $ENV:TEMP\${adapterName}_numberofErrors.txt)
Write-Host There was $errorCount new `"$errorString`" statements found...
Write-Host
$ssResult.Count > $Env:TEMP\FXAll_numberofErrors.txt
Exit $errorCount

Foreach loop in Powershell on the console

Very simple question here, I want to see how can we process a bunch of commands using foreach on the command line (not through a PS1 script).
For instance, I display the directory listing on the console, now I want to execute 2 commands per object.
Get-ChildItem | ForEach-Object { Write-Host $_ $_}
This is ok, it shows the filename twice, but lets say I wanted to run 2 Write-Host commands for the same object, would that be possible on the console?
PS: I'm trying to achieve writing an output to 2 files using the out-file cmdlet, so I can read something and have 2 separate out-file calls per object
Thanks
you can script in the console windows just as you would in a powershell file. Use the "`" (backtick) key to separate lines. e.g.:
PS > Write-Host `
>>> hello, world!
So you could do
PS > Get-ChildItem | ForEach-Object { `
>>> Write-Host $_ `
>>> doFoo() `
>>> doBar() `
>>> ` }
Basically you want to execute 2 commands in ForEach-Object statement, right?
Just use ; to separate commands in this way ForEach-Object { command1; command2 }
In your code it should be something like this
Get-ChildItem | ForEach-Object { Write-Host $_; Write-Host $_ }