Script Working on Powershell console but not on Powershell ISE - powershell

This is error message i get when running code with Powershell ISE:
Exception calling "Substring" with "1" argument(s): "StartIndex cannot
be less than zero.
Parameter name: startIndex"
At C:\Users\3N16M4\Desktop\Untitled3.ps1:8 char:1
$Last=$Role.Substring($Role.IndexOf('FE'))
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentOutOfRangeException
$text ="`n"
$String= Read-Host -Prompt 'Please Enter Value '
$Role=Get-ChildItem -Path 'C:\Users\3N16M4\Desktop\New folder\*.txt' -Recurse |Select-string -Pattern $String -SimpleMatch -Context 9,0 | Out-String -Stream |Select-Object -Index 1
$Last=$Role.Substring($Role.IndexOf('FE'))
$text
Write-host ('The Answer is: {0}' -f $Last)
$text
Read-Host -Prompt 'Press Enter to exit'
However running this same code with VScode and powershell console gives no errors and runs just fine , so i was wondering what could be causing that.

$role = "you are the winner of a all expense paid trip to the beautiful beaches of Cancun. There are few exceptions that a such as this script must be completed before you read all of the details. The developer that is assisting in the writing of this script will require a new question if you more help. It was a joy and pleasure to see this issue resolved." ;
Write-host "This String is $(($Role).length) characters long.";
$MaxDisplayWidth = 120;
$role -split '(\w{$MaxDisplayWidth})' | Where-Object {$_};

First, do a proper check for your variables because:
$Role.IndexOf('FE')
Will return -1 when it cannot find the text 'FE' in $Role.
When it returns -1 the next statement:
$Role.Substring(-1)
Will fail with the above error.
This means that the issue lies in how $Role is filled. Output $Role to see if it is returning what you are expecting. Maybe $String is being set differently?

Post the output.
$text ="`n"
$String= Read-Host -Prompt 'Please Enter Value '
$Foundfiles = Get-ChildItem -Path 'C:\temp\*.txt' -Recurse
If ($Foundfiles) {
Write-host "Files have been found. The problem is not here" -ForegroundColor green}
Else { Write-host "Error No files Found" -ForegroundColor Red }
$FilesThatContaintheString = $Foundfiles | Select-string -Pattern $String -SimpleMatch -Context 9,0
If ($FilesThatContaintheString) {Write-host "Found value in a file" -ForegroundColor Green}
Else { write-host "Did not find the string in any of the files." -ForegroundColor red}
$convertingToStrings = $FilesThatContaintheString | Out-String -Stream
If ($convertingToStrings) {write-host "Out-string works" -ForegroundColor Green}
Else {Write-host "Out-string is not working" -ForegroundColor red }
$selectTheSecoundOutputedString = $convertingToStrings |Select-Object -Index 1
If ($selectTheSecoundOutputedString) {
Write-host "If you see this then the issue is somewhere else" -ForegroundColor Yellow}
Else {Write-host 'Did not find a second string try $index 0' -ForegroundColor Red}
$Role = $selectTheSecoundOutputedString
Write-host "The value of Role is $role"
Write-host "The Index of FE is $($Role.IndexOf('FE'))"
$Last=$Role.Substring($Role.IndexOf('FE'))
$text
Write-host ('The Answer is: {0}' -f $Last)
$text
Read-Host -Prompt 'Press Enter to exit'

Related

get-process - Unable to retrieve some process information and command line

I've 2 questions regarding the code below :
Question 1:
For some unknown reason, the following code does not retrieve information from certain processes.
However, he manages to recover the sha256
Could you please explain why this behavior and how to fix address this behavior ?
Path is Null
WmiPrvSE
- [(PID=5356) () Description=]
-- Path="None (SHA256=AD938C303F12EA8D164433CC7BA46FC7B9AE00F6F899E308D4317DAB46E25642)
-----
Get-FileHash : Impossible de lier l'argument au paramètre « Path », car il a la valeur Null.
Au caractère C:\Users\LEFBE\Desktop\Klic-20-12-2021\Process.ps1:4 : 33
+ $FileHash = (Get-FileHash -Path $_.Path -Algorithm SHA256 -ErrorActio ...
+ ~~~~~~~
+ CategoryInfo : InvalidData : (:) [Get-FileHash], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Get-FileHash
Question 2:
I'm having trouble retrieving the command line launched by the process. Could you please help me to get this information?
The code :
get-process | ForEach-Object {
$Name = $_.Name
$Desc = $_.Description
$FileHash = (Get-FileHash -Path $_.Path -Algorithm SHA256 -ErrorAction SilentlyContinue).hash
$ID = $_.ID
$Path = $_.Path
$CP = $_.Company
$CL = $_.Commandline
if ($Path -eq $null)
{
Write-Host "Path is Null"
$Path = "None"
Write-Host "$Name"
Write-Host "- [(PID=$ID) ($CP) Description=$Desc]"
Write-Host "-- Path=""$Path (SHA256=$FileHash)"
Write-Host $CL
Write-Host "-----"
}
else
{
Write-Host "$Name"
Write-Host "- [(PID=$ID) ($CP) Description=$Desc]"
Write-Host "-- Path=""$Path (SHA256=$FileHash)"
Write-Host $CL
Write-Host "-----"
}
}
Update 23/12/2021
The updated code works better than the first. (manage Null $Path value)
On the other hand, no command line can be obtained yet.
get-process | ForEach-Object {
$Name = $_.Name
$Desc = $_.Description
$ID = $_.ID
$Path = $_.Path
$CP = $_.Company
$CL = $_.Commandline
IF([string]::IsNullOrEmpty($Path)) {
$Path = "None"
$FileHash = "None"
write-Host "$Name"
Write-Host "- [(PID=$ID) ($CP) Description=$Desc]"
Write-Host "-- Path=""$Path (SHA256=$FileHash)"
Write-Host $CL
Write-Host "-----"
} else {
$FileHash = (Get-FileHash -LiteralPath $_.Path -Algorithm SHA256 -ErrorAction SilentlyContinue).hash
Write-Host "$Name"
Write-Host "- [(PID=$ID) ($CP) Description=$Desc]"
Write-Host "-- Path=""$Path (SHA256=$FileHash)"
Write-Host $CL
Write-Host "-----"
}
}
Thanks for your help,
LEFBE
You can use a calculated property with Select-Object to generate your new object. As for "having trouble retrieving the command line", I'm assuming you're unable to capture the output of your script with Out-File or similar, this is because Write-Host sends the output to the Information Stream and it's output can't be captured unless redirected (6>&1).
Get-Process | Select-Object Name, Description, #{
Name = 'Hash'
Expression = { (Get-FileHash $_.Path -Algorithm SHA256).Hash }
}, ID, Path, Company, CommandLine

powershell catch export to csv not working

I'm writing a script that is fed a .csv and tries to make an operation and then catches into a seperate .csv but for some reason I cant seem to feed the catch info into the csv. I get the error, "Export-csv : Cannot process argument because the value of argument "name" is not valid. Change the value of the "name" argument and run the operation again."
I appreciate any input from the brains.
#imports a csv and does somthing with the data. The columns in the csv are specified by the $($_.'columnName')
Import-Csv -Path 'PathToMyCSV.csv' | ForEach-Object{
#Print associated User
Write-Host "$($_.ModifiedEmail)" -ForegroundColor Yellow -NoNewline;
Write-Host " is the user's email prefix, " -NoNewline
#Print PC name to be moved
Write-Host "SD-LT-$($_.PCName)" -ForegroundColor Yellow -NoNewline;
Write-Host " is the PC they use, and " -NoNewline
#Print The OU the computer is moving to
Write-Host "$($_.OU)" -ForegroundColor Yellow -NoNewline;
Write-Host "is the OU the computer needs to go in!"
$pcname = "SD-LT-$($_.PCName)"
Try {
Get-ADComputer SD-LT-$($_.PCName) | Move-ADObject -TargetPath $($_.OU)
}
Catch {
Write-Host $_ -ForegroundColor Magenta
$pcname | Export-csv -Path 'PathToAnotherCSV.csv' -Append -Force
}
}
Try creating a PSCustomObject.
[PSCustomObject]#{'pcname'=$pcname} | Export-csv -Path 'PathToAnotherCSV.csv' -Append -Force

Subexpression printing out same strings? Powershell

I have this code which deletes User Profiles off a remote machine. The removal of profiles work just fine but, the Aesthetic of doing so doesn't. What do i mean?
I'm passing the user display names to an index and making a selection out of it, and that works fine in regards to assigning the proper names to the appropriate Index Number its associated to in C:\users.
The next line of code is it grabbing the selections i made, and running through them displaying the same name i did for the index, and then it goes off to delete the CIM instance.
So my question is, why is it not passing the subexpression $userinfo1 that is already made and not putting it into the next block of code, for example, the following works as in grabbing the proper Display Name and assigning it to the proper Number:
$menu = (get-childitem "\\$cn\c$\users" | sort LastWriteTime -Descending).Name
$userinfo1 = foreach ($user in $menu) {
Start-Sleep -Milliseconds 2
$userinfo = (net user $user /domain | Select-String "Full Name" -ErrorAction SilentlyContinue) -replace "Full Name ", "" 2>&1 | Out-String -Stream
if ($userinfo.Length -lt 4) {
"$user - NO DISPLAY NAME in ADUC" # output
}
else {
if ($LASTEXITCODE -eq 2) {
"$user - account not in ADUC" # output
}
else {
if ($LASTEXITCODE -eq 0){
$userinfo # output
}
}
}
}
Write-Warning "Ensure user profiles are no longer active and/or, have profiles be backed-up!"
Write-Host "RESULTS:" -BackgroundColor Black -ForegroundColor White
for ($i=0; $i -lt $userinfo1.Count; $i++) {
Write-Host "$($i): $($userinfo1[$i])"
} #END LIST OF POSSIBLE NAMES
Write-Host ""
Write-Host "For multiple users, seperate using a SPACE(1 2 3)"
$selection = Read-Host "ENTER THE NUMBER of the user(s) or Q to quit"
$selection = $selection -split " "
but, the next block doesn't associate the display name (that was captured in $userinfo1) with the number i select and it just continues to display the first display name with the rest of the profiles its reiterating through:
foreach($Profile in $menu[$selection]){
Write-Host "Deleting user: $(,$userinfo1[$selection]) `
ID:$Profile "}
Hopefully this makes sense, and if anyone can point me in the right direction id greatly appreciate it!
Heres the rest of the script, please feel free to use it as it does work for deleting the actual profile off the system and not just the files.
#Deletes a profile properly off remote machine. WARNING: DOES NOT BACK UP DATA! Use at your own peril. Delprofile
$cn = Read-Host -Prompt "Enter Computer Name"
$ping = Test-Connection -ComputerName $cn -Count 1 -Quiet
If($ping -eq $false){ Write-Host "Computer seems to be offline, please check name spelling." -ForegroundColor DarkYellow; Write-Host ""; &PFL-Delete } else {
$menu = (get-childitem "\\$cn\c$\users" | sort LastWriteTime -Descending).Name
$userinfo1 = foreach ($user in $menu) {
Start-Sleep -Milliseconds 2
$userinfo = (net user $user /domain | Select-String "Full Name" -ErrorAction SilentlyContinue) -replace "Full Name ", "" 2>&1 | Out-String -Stream
if ($userinfo.Length -lt 4) {
"$user - NO DISPLAY NAME in ADUC" # output
}
else {
if ($LASTEXITCODE -eq 2) {
"$user - account not in ADUC" # output
}
else {
if ($LASTEXITCODE -eq 0){
$userinfo # output
}
}
}
}
Write-Warning "Ensure user profiles are no longer active and/or, have profiles be backed-up!"
Write-Host "RESULTS:" -BackgroundColor Black -ForegroundColor White
for ($i=0; $i -lt $userinfo1.Count; $i++) {
Write-Host "$($i): $($userinfo1[$i])"
} #END LIST OF POSSIBLE NAMES
Write-Host ""
Write-Host "For multiple users, seperate using a SPACE(1 2 3)"
$selection = Read-Host "ENTER THE NUMBER of the user(s) or Q to quit"
$selection = $selection -split " "
foreach($Profile in $menu[$selection]){
Write-Host "Deleting user: $(,$userinfo1[$selection]) `
ID:$Profile "
$del = Get-CimInstance -ComputerName $cn -Class Win32_UserProfile | Where-Object { $_.LocalPath.split('\')[-1] -eq $Profile }
If($del -eq $null){Write-Warning "No CIM instance found on system, profile has been deleted but files persist. Delete manually!"} else{
Get-CimInstance -ComputerName $cn -Class Win32_UserProfile | Where-Object { $_.LocalPath.split('\')[-1] -eq $Profile } | Remove-CimInstance -WhatIf
Write-Host "user profile has been deleted" -ForegroundColor Red
Write-Host ""}
}
}
#CountPs $cn
12/31/2020 - EDIT:
Here is the finished result:
Function Delete-PFL{
#Deletes a profile properly off remote machine. WARNING: DOES NOT BACK UP DATA! Use at your own peril. Delprofile
$cn = Read-Host -Prompt "Enter Computer Name"
$ping = Test-Connection -ComputerName $cn -Count 1 -Quiet
If($ping -eq $false){ Write-Host "Computer seems to be offline, please check name spelling." -ForegroundColor DarkYellow; Write-Host ""; &Delete-PFL } else {
$menu = (get-childitem "\\$cn\c$\users" | sort LastWriteTime -Descending).Name
$userinfo1 = foreach ($user in $menu) {
Start-Sleep -Milliseconds 2
$userinfo = (net user $user /domain | Select-String "Full Name" -ErrorAction SilentlyContinue) -replace "Full Name ", "" 2>&1 | Out-String -Stream
if ($userinfo.Length -lt 4) {
"$user - NO DISPLAY NAME in ADUC" # output
}
else {
if ($LASTEXITCODE -eq 2) {
"$user - ACCOUNT NOT in ADUC" # output
}
else {
if ($LASTEXITCODE -eq 0){
$userinfo # output
}
}
}
}
Write-Warning "Ensure user profiles are no longer active and/or, have profiles be backed-up!"
Write-Host "RESULTS:" -BackgroundColor Black -ForegroundColor White
for ($i=0; $i -lt $userinfo1.Count; $i++) {
Write-Host "$($i): $($userinfo1[$i])"
} #END LIST OF POSSIBLE NAMES
Write-Host ""
Write-Host "For multiple users, seperate using a SPACE(1 2 3)"
$selection = Read-Host "ENTER THE NUMBER of the user(s) or Q to quit"
$selection = $selection -split " "
foreach($index in $selection) {
$Profile = $menu[$index]
Write-Host "Deleting user: $($userinfo1[$index]) `
ID:$Profile "
$del = Get-CimInstance -ComputerName $cn -Class Win32_UserProfile | Where-Object { $_.LocalPath.split('\')[-1] -eq $Profile }
If($del -eq $null){Write-Warning "No CIM instance found on system, profile has been deleted but files persist."
Write-Host "Attempting to delete files, please wait. . ."
Remove-Item -Path "\\$cn\c$\users\$Profile" -Force -WhatIf
Write-Host ""
Start-Sleep -Seconds 2
Write-Host "Checking if Files are still there. . ."
$TestPath = Test-Path -Path "\\$cn\c$\users\$Profile"
If($TestPath -eq $false){ Write-Host "Profile Files have been deleted. `
Continuing. . . ." -ForegroundColor Green
}
} else{
Get-CimInstance -ComputerName $cn -Class Win32_UserProfile | Where-Object { $_.LocalPath.split('\')[-1] -eq $Profile } | Remove-CimInstance -WhatIf
Write-Host "user profile has been deleted" -ForegroundColor Red
Write-Host ""
}
}
}
#CountPs $cn
}
Remember to remove the -whatif parameter. Enjoy!
$selection is an array of indices, so in your foreach loop you must refer to the single index at hand, not to $selection as a whole, to get the desired display output.
The conceptually clearest approach is probably to iterate over the indices contained in $selection:
foreach($index in $selection) {
$Profile = $menu[$index]
Write-Host "Deleting user: $($userinfo1[$index]) `
EDIPI:$Profile "
# ...
}

Powershell Read-host input from CSV

Im trying to get this script to work by instead of me manually inputing sysnames that I can put the servers into csv and script it and give an output of results
It just sits at the prompt waiting for manual input
$csvpath = E:\Tsm.csv
$SvcName = '*tsm*scheduler*'
$dataset = import-csv -path $csvpath
$row = ($dataset | where{$_.hostname -eq $SysName})
$SysName = Read-Host -prompt "Enter the target computer name: "
$Tsm = Get-Service -ComputerName $SysName | Where {$_.name -Like $SvcName}
Write-Host "Service :" $Tsm.DisplayName
Write-Host "Status :" $Tsm.Status
Write-host "Start Type :" $Tsm.StartType
If ($Tsm.StartType -ne 'Automatic')
{
Write-Host "Setting service startup type to Automatic."
Set-Service -InputObject $Tsm -StartupType Automatic
}
If ($Tsm.Status -ne 'Running')
{
Write-Host "Starting the service."
Start-Service -InputObject $Tsm
}
$Tsm2 = Get-Service -ComputerName $SysName | Where {$_.name -Like $SvcName}
Write-Host "Service :" $Tsm2.DisplayName
Write-Host "Status :" $Tsm2.Status
Write-host "Start Type :" $Tsm2.StartType
Export-Csv C:\TestOutput.csv$csvpath = E:\Tsm.csv
There are many ways to get what you want. Basically you shouldn't be using Read-Host, or only use it when you want the prompt and manual waiting.
A couple of points:
# this line uses the $SysName variable, which is asked for in the next line.
# so it will not work correctly.
$row = ($dataset | where{$_.hostname -eq $SysName})
# if you do not want the waiting and pause on screen, remove this line.
# That's the standard way Read-Host works.
$SysName = Read-Host -prompt "Enter the target computer name: "
One possible solution:
param(
[switch]$manual
)
if($manual){
$SysName = Read-Host -prompt "Enter the target computer name: "
}else{
$SysName = "value or variable"
}
With this solution you can call your script using .\script.ps1 for auto-solution or .\script.ps1 -manual for the Read-Host.

Powershell: Fix My Loop Logic

I am trying to get the logic straightened out for a loop that I need to continue to prompt a user to enter a valid UNC path. I have it set to test the path and output to the console that the path is invalid. But, after that, it moves back to my prompt for choice. I want it to instead, ask the user to enter another valid path before moving on to the next step. Here is my loop:
do{
Write-Host ""
$pathPrompt = Write-Host "Please enter path to file/folder:" -ForegroundColor Cyan;
$path = Read-Host;
$test = Test-Path $path
if($test -eq $false){
Write-Host "ERROR! Invalid Path!" -ForegroundColor Red
}
}until($test -eq $true){
Write-Host ""
Write-Host "Getting ACL on"$path -ForegroundColor Green
Get-NTFSAccess -Path $path
}
What am I missing or not doing right here?
Sounds like you want to reuse your validation test. You could put it in a function for reuse:
Function Get-ValidPath {
do {
Write-Host "`r`nPlease enter path to file/folder:" -ForegroundColor Cyan
$path = Read-Host
$test = Test-Path $path
if ($test -eq $false) {
Write-Host "ERROR! Invalid Path!" -ForegroundColor Red
}
} until ($test -eq $true)
$path
}
$validatedpath1 = Get-ValidPath
Write-Host "`r`nGetting ACL on $validatedpath1" -ForegroundColor Green
Get-NTFSAccess -Path $validatedpath1
$validatedpath2 = Get-ValidPath