Extract string without spacing in powershell cmdlet - string

I have some powershell script . Instead totalcmd* you can type another process you want.
$tc = get-process -Name totalcmd* | format-wide -property Name
echo $tc
if ($tc -eq "Totalcmd64")
{
Stop-Process -Name totalcmd*
}
Start-Sleep 10
It doesn't work, I think, because, my $tc not equal to string "totalcmd". How can I remove unwanted spaces of cmdlet get-process -Name totalcmd* | format-wide -property Name output and compare strings correctly?

You do not end up with a string because you pipe to format-wide. These cmdlets are best for representing data on the screen. Instead select the property and use -ExpandProperty to return it as a string:
$tc = get-process -Name totalcmd* | Select-Object -ExpandProperty Name
echo $tc
...

You are generally correct that $tc is not equal to "totalcmd" and that is because when you set $tc, you are creating an array (most likely of one element). You can test that by running $tc | get-member to see what kind of object you are working with.
To work with string objects, you could use the Out-String cmdlet as well.

If you want to explicitly stop TotalCmd64 processes why not simply use:
Get-Process -Name TotalCmd64 | Stop-Process
If you want to switch between 64/32bit versions of the program, use a switch statement (untested):
$tc = (Get-Process -Name TotalCmd*).Name
switch ($tc){
'TotalCmd' {Get-Process -Name TotalCmd |Stop-Process;"Start TotalCmd64";Break}
'TotalCmd64' {Get-Process -Name TotalCmd64|Stop-Process;"Start TotalCmd32";Break}
default {"No TotalCmd* processes found"}
}

Related

PowerShell export "Get-volume" to excel/csv

I used the below one it gives somewhat different in excel ,please help me on this
#Disk Space
Get-Volume
$results = Get-Volume | Export-Csv -Path C:\temp\software1.csv
Note: I need health check , Drive Name, Free space , size, disk type in excel
Thanks in advance friends :)
Generally speaking, when you run a powershell command it only shows what sections are deemed as important. If you take the same command and pipe it to format-list (or "ft" for short) you will get everything.
Get-Volume | ft
When exporting it exports everything.
Also, you need to add the paramater -NoTypeInformation to get rid of the first row.
To only get certain values, you will just pipe it using select.. something like this:
Get-Volume | select HealthStatus, DriveLetter, SizeRemaining,DriveType | Export-Csv -NoTypeInformation -Path C:\temp\software1.csv
Also, there is no need to do $results = get-volume... This pushes the output into the variable $results. This would be applicable if you wanted to recall the variable later. So, you could also do something like this..
$results = Get-Volume
$results | select HealthStatus, DriveLetter, SizeRemaining, DriveType | Export-Csv -NoTypeInformation -Path C:\temp\software1.csv
Keep in mind you need to have the Import-Excel Module loaded but you should be able to use this to output to Excel.
#check-DiskSpace_FSs.ps1
import-module activedirectory
$dc = "domainController09"
$currentDate = get-date -Format yyyyMMdd_HHmm
$path = "\\UNC\export\FileServer_DiskSpace\FileServer_DiskSpace_$currentDate.xlsx"
$smtpServer = "10.10.10.10"
$from = "me#somewhere.com"
$to = "me#somewhere.com"
$subject = "Server FS diskspace - $date"
$ServerFSs = get-adcomputer -Server $dc -SearchBase "OU=fs,OU=Server,DC=somewhere,DC=com" -filter * | select name | sort Name
$DriveSize = foreach ($FS in $somewhereFSs)
{
get-WmiObject win32_logicaldisk -ComputerName $FS.name -Filter "Drivetype=3" | select SystemName,DeviceID,#{n="TotalSize(GB)";e={$_.Size / 1gb -as [int] }}`
,#{n="FreeSize(GB)";e={$_.freespace / 1gb -as [int] }}`
,#{n="FreeSize(%)";e={[int]($_.Freespace*100/$_.Size)}},VolumeName | Export-Excel -Path $path -append -FreezeTopRow -BoldTopRow -AutoSize -AutoFilter
}
Send-Mailmessage -smtpServer $smtpServer -from $from -to $to -subject $subject -Attachments $path -priority High

powershell script, text placement in cells in csv file

So, to continue my lovely journey through powershell from here:
Loop for two variables
I have a ps1 that runs a loop for a bunch of transactions and a bunch of nodes and sends them over to a csv file.
$url = "https://someserver/trans="
$transactions = '1','2','3','4' #There are 4 transactions
$nodes = 'node1','node2','node3','node4','node5','node6' #There are 10 nodes
Remove-Item ATM.csv -Force
# So far so good
# Below is what I'd use as a function in bash. No sure what/how to do in PS:
#OUTPUT:
foreach($transaction in $transactions)
{
foreach($node in $nodes)
{
"$transaction;$node" |out-file -Append ATM.csv
curl -k -u user#pass $url$transaction$node | findstr "<value>" | out-file -Append ATM.csv
}
}
Opening the file in excel, I end up with this output under column A:
transaction1;node1 (in the first row, left-most cell)
value1 (from the curl. It's actually a number and it sits in the row right under the first entry)
and so on and so forth for 2,3, and the rest. only the left most column (column A) gets populated.
What I'd like to get is a way to place the values in three columns, such that the csv will look like:
Column A | Column B | Column C
transaction1| node1 | valueX
transaction2| node2 | valueY
and so on. The script or another will have to do this, the end user for this job who'll run the script will not open excel every day and start running macros, he needs the final csv ready from the script.
Whatever shall I do?
Something like this will fix your issues, the only bit that's not included is selecting the value itself from Invoke-WebRequest (curl) as that will change depending on what's returned.
foreach($transaction in $transactions)
{
foreach($node in $nodes)
{
$value = Invoke-WebRequest -Uri $url$transaction$node -UseBasicParsing | Select-Object -Expand Content
Add-Content -Path ATM.csv -Value "$transaction,$node,$value"
}
}
You are currently writing your output in two different lines. One solution could be to use the NoNewLine parameter in the Out-File:
"$transaction;$node" |out-file -Append ATM.csv -nonewline
curl -k -u user#pass $url$transaction$node | findstr "<value>" | out-file -Append ATM.csv
Personally I would create a Powershell Object and create the csv at the end:
$array = #()
foreach($node in $nodes) {
$obj = New-Object psobject
$obj | Add-Member -MemberType NoteProperty -Name 'Transaction' -Value $transaction
$obj | Add-Member -MemberType NoteProperty -Name 'Node' -Value $node
$obj | Add-Member -MemberType NoteProperty -Name 'Value' -Value (curl -k -u user#pass $url$transaction$node | findstr "<value>")
$array += $obj
}

using threads to delete files with specific extensions ignoring files over a certain date

In my profession I make forensic images from "foreign" PCs which I extract later on my local storage.
To clean up the data I'd hope to delete all files that aren't relevant for me. (not limited to: audio, movies, systemfiles,...)
Since we're speaking of multiple TB of data, I'd have hoped to use threads, especially since my storage is all flash and the limitation on the disk is somewhat less of a problem.
To speed the process up after an initial manual run, I would want the script to exclude files older then 1 day (since I have done that one already with a manual run).
what I have so far:
$IncludeFiles = "*.log", "*.sys", "*.avi", "*.mpg", "*.mkv", ".mp3", "*.mp4",
"*.mpeg", "*.mov", "*.dll", "*.mof", "*.mui", "*.zvv", "*.wma",
"*.wav", "*.MPA", "*.MID", "*.M4A", "*.AIF", "*.IFF", "*.M3U",
"*.3G2", "*.3GP", "*.ASF", "*.FLV", "*.M4V", "*.RM", "*.SWF",
"*.VOB"
$ScriptBlock = {
Param($mypath = "D:\")
Get-ChildItem -Path $mypath -Recurse -File -Include $file | Where-Object {
$_.CreationTime -gt (Get-Date).AddDays(-1)
}
foreach ($file in $IncludeFiles) {
Start-Job -ScriptBlock $ScriptBlock -ArgumentList $file
}
Get-Job | Wait-Job
$out = Get-Job | Receive-Job
Write-Host $out
the only thing that doesn't work is the limitation that it only looks at files "younger" than 1 day. If I run the script without it, it seems to work perfectly. (as it gives me a list of files with the extensions I want to remove)
Parameter passing doesn't work the way you seem to expect. Param($mypath = "D:\") defines a parameter mypath with a default value of D:\. That default value is superseded by the value you pass into the scriptblock via -ArgumentList. Also the variable $file inside the scriptblock and the variable $file outside the scriptblock are not the same. Because of that an invocation
Start-Job -ScriptBlock $ScriptBlock -ArgumentList '*.log'
will run the command
Get-ChildItem -Path '*.log' -Recurse -File -Include $null | ...
Change your code to something like this to make it work:
$ScriptBlock = {
Param($extension)
$mypath = "D:\"
Get-ChildItem -Path $mypath -Recurse -File -Filter $extension | Where-Object {
$_.CreationTime -gt (Get-Date).AddDays(-1)
}
}
foreach ($file in $IncludeFiles) {
Start-Job -ScriptBlock $ScriptBlock -ArgumentList $file
}
Get-Job | Wait-Job | Receive-Job
Using -Filter should provide better performance than -Include, but accepts only a single string (not a list of strings like -Include), so you can only filter one extension at a time.

Powershell Script to loop through folders checking security permissions

I have part of the code: at the moment its coming empty in the CSV file. But i need a command to specify the path/folders to look at, how do i modify this for that purpose.
Param(
[String]$path,
[String]$outfile = ".\outfile.csv"
)
$output = #()
ForEach ($item in (Get-ChildItem -Path $path -Recurse -Directory)) {
ForEach ($acl in ($item.GetAccessControl().Access)){
$output += $acl |
Add-Member `
-MemberType NoteProperty `
-Name 'Folder' `
-Value $item.FullName `
-PassThru
}
}
$output | Export-Csv -Path $outfile -NoTypeInformation
Ok, let's do this. I've made it into a function, and removed the OutFile part of it. If you want to output it to a file, pipe it to Export-CSV. If you want it saved as a variable, assign it to a variable. Just simpler this way.
Function Get-RecursiveACLs{
Param(
[String]$Path=$(Throw "You must specify a path")
)
$Output = GCI $Path -Recurse -Directory|%{
$PathName=$_.FullName
$_.GetAccessControl().Access|%{
Add-Member -InputObject $_ -NotePropertyName "Path" -NotePropertyValue $PathName -PassThru
}
}
}
Then it's a simple matter of storing it in a variable like:
$ACLList = Get-RecursiveACLs "C:\Example\Path"
Or piping it to output to a CSV if you would prefer:
Get-RecursiveACLs "C:\Example\Path" | Export-CSV "C:\Results.csv" -NoType
Put the function at the top of your script and call it as needed.

PowerShell FINDSTR eqivalent?

What's the DOS FINDSTR equivalent for PowerShell? I need to search a bunch of log files for "ERROR".
Here's the quick answer
Get-ChildItem -Recurse -Include *.log | select-string ERROR
I found it here which has a great indepth answer!
For example, find all instances of "#include" in the c files in this directory and all sub-directories.
gci -r -i *.c | select-string "#include"
gci is an alias for get-childitem
Just to expand on Monroecheeseman's answer. gci is an alias for Get-ChildItem (which is the equivalent to dir or ls), the -r switch does a recursive search and -i means include.
Piping the result of that query to select-string has it read each file and look for lines matching a regular expression (the provided one in this case is ERROR, but it can be any .NET regular expression).
The result will be a collection of match objects, showing the line matching, the file, and and other related information.
if ($entry.EntryType -eq "Error")
Being Object Oriented, you want to test the property in question with one of the standard comparison operators you can find here.
I have a PS script watching logs remotely for me right now - some simple modification should make it work for you.
edit: I suppose I should also add that is a cmdlet built for this already if you don't want to unroll the way I did. Check out:
man Get-EventLog
Get-EventLog -newest 5 -logname System -EntryType Error
On a related note, here's a search that will list all the files containing a particular regex search or string. It could use some improvement so feel free to work on it. Also if someone wanted to encapsulate it in a function that would be welcome.
I'm new here so if this should go in it's own topic just let me know. I figured I'd put it her since this looks mostly related.
# Search in Files Script
# ---- Set these before you begin ----
$FolderToSearch="C:\" # UNC paths are ok, but remember you're mass reading file contents over the network
$Search="Looking For This" # accepts regex format
$IncludeSubfolders=$True #BUG: if this is set $False then $FileIncludeFilter must be "*" or you will always get 0 results
$AllMatches=$False
$FileIncludeFilter="*".split(",") # Restricting to specific file types is faster than excluding everything else
$FileExcludeFilter="*.exe,*.dll,*.wav,*.mp3,*.gif,*.jpg,*.png,*.ghs,*.rar,*.iso,*.zip,*.vmdk,*.dat,*.pst,*.gho".split(",")
# ---- Initialize ----
if ($AllMatches -eq $True) {$SelectParam=#{AllMatches=$True}}
else {$SelectParam=#{List=$True}}
if ($IncludeSubfolders -eq $True) {$RecurseParam=#{Recurse=$True}}
else {$RecurseParam=#{Recurse=$False}}
# ---- Build File List ----
#$Files=Get-Content -Path="$env:userprofile\Desktop\FileList.txt" # For searching a manual list of files
Write-Host "Building file list..." -NoNewline
$Files=Get-ChildItem -Include $FileIncludeFilter -Exclude $FileExcludeFilter -Path $FolderToSearch -ErrorAction silentlycontinue #RecurseParam|Where-Object{-not $_.psIsContainer} # #RecurseParam is basically -Recurse=[$True|$False]
#$Files=$Files|Out-GridView -PassThru -Title 'Select the Files to Search' # Manually choose files to search, requires powershell 3.0
Write-Host "Done"
# ---- Begin Search ----
Write-Host "Searching Files..."
$Files|
Select-String $Search #SelectParam| #The # instead of $ lets me pass the hastable as a list of parameters. #SelectParam is either -List or -AllMatches
Tee-Object -Variable Results|
Select-Object Path
Write-Host "Search Complete"
#$Results|Group-Object path|ForEach-Object{$path=$_.name; $matches=$_.group|%{[string]::join("`t", $_.Matches)}; "$path`t$matches"} # Show results including the matches separated by tabs (useful if using regex search)
<# Other Stuff
#-- Saving and restoring results
$Results|Export-Csv "$env:appdata\SearchResults.txt" # $env:appdata can be replaced with any UNC path, this just seemed like a logical place to default to
$Results=Import-Csv "$env:appdata\SearchResults.txt"
#-- alternate search patterns
$Search="(\d[-|]{0,}){15,19}" #Rough CC Match
#>
This is not the best way to do this:
gci <the_directory_path> -filter *.csv | where { $_.OpenText().ReadToEnd().Contains("|") -eq $true }
This helped me find all csv files which had the | character in them.
PowerShell has basically precluded the need for findstr.exe as the previous answers demonstrate. Any of these answers should work fine.
However, if you actually need to use findstr.exe (as was my case) here is a PowerShell wrapper for it:
Use the -Verbose option to output the findstr command line.
function Find-String
{
[CmdletBinding(DefaultParameterSetName='Path')]
param
(
[Parameter(Mandatory=$true, Position=0)]
[string]
$Pattern,
[Parameter(ParameterSetName='Path', Mandatory=$false, Position=1, ValueFromPipeline=$true)]
[string[]]
$Path,
[Parameter(ParameterSetName='LiteralPath', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
[Alias('PSPath')]
[string[]]
$LiteralPath,
[Parameter(Mandatory=$false)]
[switch]
$IgnoreCase,
[Parameter(Mandatory=$false)]
[switch]
$UseLiteral,
[Parameter(Mandatory=$false)]
[switch]
$Recurse,
[Parameter(Mandatory=$false)]
[switch]
$Force,
[Parameter(Mandatory=$false)]
[switch]
$AsCustomObject
)
begin
{
$value = $Pattern.Replace('\', '\\\\').Replace('"', '\"')
$findStrArgs = #(
'/N'
'/O'
#('/R', '/L')[[bool]$UseLiteral]
"/c:$value"
)
if ($IgnoreCase)
{
$findStrArgs += '/I'
}
function GetCmdLine([array]$argList)
{
($argList | foreach { #($_, "`"$_`"")[($_.Trim() -match '\s')] }) -join ' '
}
}
process
{
$PSBoundParameters[$PSCmdlet.ParameterSetName] | foreach {
try
{
$_ | Get-ChildItem -Recurse:$Recurse -Force:$Force -ErrorAction Stop | foreach {
try
{
$file = $_
$argList = $findStrArgs + $file.FullName
Write-Verbose "findstr.exe $(GetCmdLine $argList)"
findstr.exe $argList | foreach {
if (-not $AsCustomObject)
{
return "${file}:$_"
}
$split = $_.Split(':', 3)
[pscustomobject] #{
File = $file
Line = $split[0]
Column = $split[1]
Value = $split[2]
}
}
}
catch
{
Write-Error -ErrorRecord $_
}
}
}
catch
{
Write-Error -ErrorRecord $_
}
}
}
}
FYI:
If you update to Powershell version 7 you can use grep...
I know egrep is in powershell on Azure CLI...
But SS is there!
An old article here: [https://devblogs.microsoft.com/powershell/select-string-and-grep/]

Resources