Powershell For-Loop throws MissingVariableNameAfterForeach - powershell

Why do I get the error "MissingVariableNameAfterForeach" for the following:
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "foreach($file in Get-ChildItem C:){((Get-Date)-$file.LastWriteTime).ToString('dd')}"
The command is supposed to print out the day since today of the last file/folder write in C:\

From the help text:
PS C:\> powershell.exe /?
If the value of Command is a script block, the script block must be enclosed
in braces ({}). You can specify a script block only when running PowerShell.exe
in Windows PowerShell.
Try this:
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command {Get-ChildItem C: | ForEach-Object{($_.LastWriteTime).ToString('dd')}}

Your command will work if you enclose the Get-ChildItem in parentheses.
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ^
"foreach($file in (Get-ChildItem C:)){((Get-Date)-$file.LastWriteTime).ToString('dd')}"

I may have understood your question, because the existing answers do not seem to provide the information I thought you were looking for.
Whilst these examples don't specifically answer the question posed in your title, they are intended to output what I think you were looking for.
Here therefore is my batch-file attempt:
#"%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile -Command^
"Get-ChildItem -Path 'C:\'|Sort-Object -Property LastWriteTime|"^
"Select-Object -Last 1|Format-Table -AutoSize -Property Name,"^
"#{Name='DaysOld';Expression={[Int]$((Get-Date)-$_.LastWriteTime).TotalDays}}"
#Pause
And obviously the cmd version, to be on topic:
"%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile -Command "Get-ChildItem -Path 'C:\'|Sort-Object -Property LastWriteTime|Select-Object -Last 1|Format-Table -AutoSize -Property Name,#{Name='DaysOld';Expression={[Int]$((Get-Date)-$_.LastWriteTime).TotalDays}}"
Just in case it is simply my misunderstanding, perhaps this batch-file may work for you:
#"%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile -Command^
"Get-ChildItem -Path 'C:\'|Sort-Object -Property LastWriteTime -Descending|"^
"Format-Table -AutoSize -Property Name,"^
"#{Name='DayInMonth';Expression={($_.LastWriteTime).ToString('dd')}},"^
"#{Name='DaysOld';Expression={[Int]$((Get-Date)-$_.LastWriteTime).TotalDays}}"
#Pause
cmd version:
"%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile -Command "Get-ChildItem -Path 'C:\'|Sort-Object -Property LastWriteTime -Descending|Format-Table -AutoSize -Property Name,#{Name='DayInMonth';Expression={($_.LastWriteTime).ToString('dd')}},#{Name='DaysOld';Expression={[Int]$((Get-Date)-$_.LastWriteTime).TotalDays}}"
In both cases, you'll note because I'm not running a PowerShell script, there is no need to stipulate an execution policy. Commands should work as if being run directly in the PowerShell window.

Related

How to pause the output of Powershell from a bat file

I need to see the powershell output when I'm running it from a bat file. The bat file pauses with no problem but the powershell executes and flashes on the screen and closes before I can read the powershell error. How can I pause the powershell output so I can read it.
Bat file RemovePackagesFitBit.bat
#ECHO Off
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs} | Wait-Process"
#PAUSE
Powershell file RemovePackagesFitBit.PS1
Get-AppxPackage -allusers *fitbit* | Remove-AppxPackage
Running this in Windows 10
Just insert pause in script where required:
$Package = Get-AppxPackage -allusers -Name fitbit
Pause
$Packasge | Remove-AppxPackage
Pause
I wasn't able to see the errors with a pause so I logged all output to a file this way:
I put this at the begining of the script:
$Logfile = "C:\Temp\Fix-Sysprep.log"
If (Test-Path $Logfile)
{
Remove-item -path $Logfile
}
Start-Transcript -Path $Logfile -Append
I put this at the end of the script:
Stop-Transcript

Calling Powershell in a batch file issue

My powershell command is this:
Get-WmiObject -class Win32_printer | ft name, systemName, shareName >> $PSScriptRoot\printers.txt
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, InstallDate | Format-Table –AutoSize >> $PSScriptRoot\programs.txt
Get-WmiObject -Class Win32_MappedLogicalDisk | select Name, ProviderName >> $PSScriptRoot\drives.txt
My batch is this:
#ECHO OFF
SET Directory=%~dp0
SET PowerShellScriptPath=%Directory%reimage_checklist.ps1
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%'";
If I run the PowerShell script in IDE, it puts out three text documents with the requested information. If I run the batch file, it outputs three batch files, but the network drive text file is blank.
Resolved by adding
Set-ExecutionPolicy -Scope CurrentUser Bypass
To the powershell script and removing
-ExecutionPolicy Bypass
From the batch file

Right Click context - Search folder .txt & .log files

Still new to PowerShell and have been creating automation scripts, checks and balances and anything I can think of to make our jobs easier day to day. The contract we are working on are extremely tight when it comes to applications and forbids opensource\freeware applications. So I have been working on using powershell to do the job.
Here is what I have so far:
1. Created HKCR\Directory\Shell\powershell (default) Reg_sz Search Folder Text & Log files
2. Created HKCR\Directory\Shell\powershell\command (default) Reg_sz
C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -file c:\temp\RightClickSearch.ps1 -NoExit -Command Set-Location -LiteralPath '%L'
I was able to get the right click to launch and the script opens up and prompts me for my keyword to search. Problem is, I can't seem to figure out how to pass the location to the script properly.
RightClickSearch.ps1 (I know the $path isn't set, before it was hardcoded and I know I have to pass a variable to it from the menu)
$promt = (Read-Host -Prompt "Enter Search Keyword")
Get-ChildItem -Path $Path -Include *.txt, *.log -Recurse | Select-String -Pattern $promt | Format-table -AutoSize -Property LineNumber,Filename,Path
Pause
There are two problems with your call to powershell.exe:
You can't specify both the -File and -Command parameters. You can only specify one of them.
Whichever one you do specify, it has to be the last parameter in the command. In your example, the -NoExit and -Command parameters would be ignored. (Type powershell.exe -? for an explanation.)
The good news is that PowerShell scripts themselves can accept arguments by using the param keyword. Simply declare the parameter at the top of your script:
param ($Path)
$promt = (Read-Host -Prompt "Enter Search Keyword")
Get-ChildItem -Path $Path -Include *.txt, *.log -Recurse | Select-String -Pattern $promt | Format-table -AutoSize -Property LineNumber,Filename,Path
Pause
You call it from the command line like this:
C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -File c:\temp\RightClickSearch.ps1 -Path '%L'
Since $Path is the one and only parameter, you don't even have to specify its name:
C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -File c:\temp\RightClickSearch.ps1 '%L'
Ironically, you could use the -Command parameter in exactly the same way. The only difference is that your script file will not be dot-sourced, but that won't matter in the example you gave.

How can I find the length of the first line of a file in batch or powershell

I have to read each file in a folder and determine the length of the first line of each, then do something depending on whether or not that length is what is should be in a table. I can loop through each file in batch and have %%f as the file, but how do I get that length and assign it to a variable?
If there is a way to do this in Powershell using a batch file, that would help, but I would need to know how to call the Powershell from the batch file also.
The simple PowerShell code would look something like this:
param($path)
Get-ChildItem $path -File |
Select FullName,#{Label="1stLineLength";Expression={(Get-Content $_.FullName -First 1).Length}}
So the first argument will be taken as the path of the script. Then to call it from batch I borrow the answer to this SO question.
Powershell.exe -executionpolicy remotesigned -File m:\Scripts\firstlinelength.ps1 "C:\temp"
That will get output like this on console.
FullName 1stLineLength
-------- -------------
C:\Users\mcameron\CleansedBigFile.txt 4
This code assumes that you have at least PowerShell v3.0 for the -First and -File parameter and switch. I would like to think that most batch code can be converted easily to a PowerShell equivalent so if your environment allows you consider converting to the powerful PowerShell.
Some of your question is pretty vague (what table?). But in general, you don't need a batch file at all. PowerShell example:
Get-ChildItem -File | ForEach-Object {
$firstLineLength = (Get-Content $_ | Select-Object -First 1).Length
if ( $firstLineLength -gt $whateverFromTable ) {
...
}
}
Note that the -File parameter of Get-ChildItem doesn't exist before PowerShell v3. For PowerShell v2 and below, you would replace Get-ChildItem -File with Get-ChildItem | Where-Object { -not $_.PSIsContainer }.

Using the -command PowerShell feature does not executing in CMD

I am trying to create a PowerShell command that reads a registy variable and then executes a command. It does this from the command line using CMD and it runs under SYSTEM.
I have the following code:
powershell.exe -ExecutionPolicy ByPass -WindowStyle Minimized -Command
"$ErrorActionPreference = 'silentlycontinue' |`
New-Variable -name UserNameForSapFolderRemoval -Value (get-itemproperty 'HKCU:\Volatile Environment' |`
Select-Object -ExpandProperty UserName) |`
Remove-Item $("C:\Users\"+$UserNameForSapFolderRemoval +"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Sapgui 7.30") -Force -Recurse |`
Remove-Variable -Name UserNameForSapFolderRemoval"
But it returns with:
The string is missing the terminator
I added the " character but without succes.
Any idea how I can get this powershell command to run succesful?
Parsing username from registry is way too complicated, as there already is $env:username. Try something like this,
powershell -command { rm -force -recurse "c:\users\$env:username\appdata\whatever" }