Powershell kill all Powershell windows that are open besides the current one - powershell

Get-Process powershell | Format-table -Property Id -HideTableHeaders -Force | out-string -OutVariable "a"
foreach ($a in $tre) {stop-process $tre}

It is much simpler, your script fragment foreach ($a in $tre) has the wrong order,
should be foreach ($tre in $a) but that wouldn't exclude the current powershell.
Try this:
Get-Process powershell | Where-Object ID -ne $PID | Stop-Process

$rtrtrt = (get-random)
Get-Process powershell | Format-table -Property name, Id -HideTableHeaders -OutVariable "zaz"
$zaz = $zaz | out-string
$zaz = $zaz -replace " ", " "
$zaz = $zaz -replace " ", " "
$zaz = $zaz -replace "powershell $pid", ""
$zaz=$zaz -replace "powershell", "stop-process -force"
echo $zaz >$env:temp\$rtrtrt.ps1
&"$env:temp\$rtrtrt.ps1"
IF(!(Test-Path "$env:temp\$rtrtrt.ps1")) {echo "#"} else {Remove-Item "$env:temp\$rtrtrt.ps1" -recurse}
I made that up but yours looks much better
thank you
enter code here
I'm gonna use yours obviously
Get-Process powershell | Where-Object ID -ne $PID | Stop-Process

Related

why am I having this error while using replace methode

I am trying to list first and second level folders of a path. the script works fine, but I am having this error "You cannot call a method on a null-valued expression." any idea why ?
$folderPath = '\\FILSERVER\DATA$'
$PathScript = "C:\Users\adm\Desktop\Script_V.2"
$sites = "Madrid"
foreach ($site in $Sites){
#Get_Level_1_Folders
$PathShare = "\\FILSERVER\DATA$\Data_$site"
Get-ChildItem -Path $PathShare -Directory -Force -ErrorAction SilentlyContinue | Select-Object FullName | out-file "${PathScript}\level_1_${site}.txt"
(get-content "${PathScript}\level_1_${site}.txt") -notmatch "--------" | out-file "${PathScript}\level_1_${site}.txt"
(get-content "${PathScript}\level_1_${site}.txt").replace("\\FILSERVER\DATA$\Data_$site\","" ) | out-file "${PathScript}\level_1_${site}.txt"
(get-content "${PathScript}\level_1_${site}.txt") -notmatch "FullName" | out-file "${PathScript}\level_1_${site}.txt"
(get-content "${PathScript}\level_1_${site}.txt") | Foreach {$_.TrimEnd()} | Set-Content "${PathScript}\level_1_${site}.txt"
(get-content "${PathScript}\level_1_${site}.txt") | ? {$_.trim() -ne "" } | set-content "${PathScript}\level_1_${site}.txt"
#Get_Level_2_Folders
$Level_Folders = get-content "${PathScript}\level_1_${site}.txt"
foreach($lv1 in $Leve1_Folders){
Get-ChildItem -Path $PathShare\$lv1 -Directory -Force -ErrorAction SilentlyContinue | Select-Object FullName | out-file "${PathScript}\level_2_${site}_${lv1}.txt"
(get-content "${PathScript}\level_2_${site}_${lv1}.txt") -notmatch "--------" | out-file "${PathScript}\level_2_${site}_${lv1}.txt"
(get-content "${PathScript}\level_2_${site}_${lv1}.txt").replace("\\FILSERVER\DATA$\Data_$site\","") | out-file "${PathScript}\level_2_${site}_${lv1}.txt"
(get-content "${PathScript}\level_2_${site}_${lv1}.txt") -notmatch "FullName" | out-file "${PathScript}\level_2_${site}_${lv1}.txt"
(get-content "${PathScript}\level_2_${site}_${lv1}.txt") | Foreach {$_.TrimEnd()} | Set-Content "${PathScript}\level_2_${site}_${lv1}.txt"
(get-content "${PathScript}\level_2_${site}_${lv1}.txt") | ? {$_.trim() -ne "" } | set-content "${PathScript}\level_2_${site}_${lv1}.txt"
}
As mentioned in comments, the cause is likely that this expandable string:
"${PathScript}\level_2_${site}_${lv1}.txt"
... resolved to the path of a file that's empty.
Get-Content will open the file - which is why you don't get any "file not found" errors - and then immediately return without outputting anything, since there's no meaningful "lines" to consume in an empty file.
The result of the (Get-Content ...) expression is therefore $null, and you received the error in question.
You can either use the -replace operator which will take any number of strings (including none) as input - just make sure you escape the arguments:
(Get-Content "${PathScript}\level_2_${site}_${lv1}.txt") -replace [regex]::Escape("\\FILSERVER\DATA$\Data_$site\") |Out-File ...
Or let the pipeline take care of enumerating the output instead of relying on implicit property enumeration:
Get-Content "${PathScript}\level_2_${site}_${lv1}.txt" |ForEach-Object {$_.Replace("\\FILSERVER\DATA$\Data_$site\","")} |Out-File ...

Trying to simplify Powershell Code to Single Line

The following snippet of code gets a list of paths, converts each character of each path to its ASCII value and stores this in a variable named $output
$itemlist = (Get-ChildItem -Recurse -Path "$data_path").FullName
Foreach($item in $itemlist)
{
$output+= [int[]]#("$item").ToCharArray() -join ',' | Out-String
}
Write-Host $output
I'm trying to get all this in a single line (due to a complicated reason that prevents me from running a Powershell script) so I can run a single Powershell command to get the same effect but so far I'm having a hard time.
Given below is what I've managed to achieve.
(Get-ChildItem -Recurse -Path "$data_path").FullName | Format-Table -Property #{n='';e={[int[]]#($_).ToCharArray() -join ','}} | Out-Host
The output however doesn't have the ASCII values, the paths in the output are represented in characters. Can someone please help me out with this ?
How you should be doing it if you're running this from cmd.exe:
$Command = #'
$itemlist = (Get-ChildItem -Recurse -Path "$data_path").FullName
Foreach($item in $itemlist)
{
$output+= [int[]]#("$item").ToCharArray() -join ',' | Out-String
}
Write-Host $output
'#
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Command))
End result:
powershell.exe -NoProfile -NoLogo -EncodedCommand JABpAHQAZQBtAGwAaQBzAHQAIAA9ACAAKABHAGUAdAAtAEMAaABpAGwAZABJAHQAZQBtACAALQBSAGUAYwB1AHIAcwBlACAALQBQAGEAdABoACAAIgAkAGQAYQB0AGEAXwBwAGEAdABoACIAKQAuAEYAdQBsAGwATgBhAG0AZQAgAAoAIABGAG8AcgBlAGEAYwBoACgAJABpAHQAZQBtACAAaQBuACAAJABpAHQAZQBtAGwAaQBzAHQAKQAKACAAIAAgACAAewAgAAoAIAAgACAAIAAgACQAbwB1AHQAcAB1AHQAKwA9ACAAWwBpAG4AdABbAF0AXQBAACgAIgAkAGkAdABlAG0AIgApAC4AVABvAEMAaABhAHIAQQByAHIAYQB5ACgAKQAgAC0AagBvAGkAbgAgACcALAAnACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcACgAgACAAIAAgAH0ACgAgAFcAcgBpAHQAZQAtAEgAbwBzAHQAIAAkAG8AdQB0AHAAdQB0AA==
If this is turning into a short contest..
ls $data_path -r|%{($_|% f*|% t*y|% toi*2 $null)-join','}|out-string
I guess you can use this:
(Get-ChildItem -Recurse -Path "$data_path").FullName | ForEach-Object { [int[]]#("$_").ToCharArray() -join ',' } | Out-String
$itemlist = (Get-ChildItem -Recurse -Path "$data_path").FullName; Foreach($item in $itemlist){$output+= [int[]]#("$item").ToCharArray() -join ',' | Out-String};Write-Host $output
Get-ChildItem -Path "$data_path" | ForEach-Object { [int[]][char[]]$_.FullName -join ',' }
Get-ChildItem -Path "$data_path" | ForEach-Object { [int[]]#($_.FullName).ToCharArray() -join ',' }
Using aliases is all I can think of to shorten it further than anyone has so far:
ls "$data_path" -r | %{[int[]]#($_.FullName).ToCharArray() -join ","} | Out-String
$itemlist = (Get-ChildItem -Recurse -Path "$data_path").FullName
Foreach($item in $itemlist)
{
$output+= [int[]]#("$item").ToCharArray() -join ',' | Out-String
}
Write-Host $output

Avoid blank line on Out-File

How can I avoid getting a blank line at the end of an Out-File?
$DirSearcher = New-Object System.DirectoryServices.DirectorySearcher([adsi]'')
$DirSearcher.Filter = '(&(objectClass=Computer)(!(cn=*esx*)) (!(cn=*slng*)) (!(cn=*dcen*)) )'
$DirSearcher.FindAll().GetEnumerator() | sort-object { $_.Properties.name } `
| ForEach-Object { $_.Properties.name }`
| Out-File -FilePath C:\Computers.txt
I have tried several options and none of them seem to do anything, they all still have a blank line at the end.
(get-content C:\Computers.txt) | where {$_ -ne ""} | out-file C:\Computers.txt
$file = C:\Computers.txt
Get-Content $file | where {$_.Length -ne 0} | Out-File "$file`.tmp"
Move-Item "$file`.tmp" $file -Force
Use [IO.File]::WriteAllText:
[IO.File]::WriteAllText("$file`.tmp",
((Get-Content $file) -ne '' -join "`r`n"),
[Text.Encoding]::UTF8)
Often when you're looking to see if strings have no character data, you will want to use String.IsNullOrWhiteSpace():
Get-Content $file | Where-Object { ![String]::IsNullOrWhiteSpace($_) } | Out-File "$file`.tmp"
this the best solution for the avoiding the empty line at the end of txt file using powershell command
Add-Content C:\Users\e5584332\Desktop\CSS.txt "Footer | Processed unique data || $count " -NoNewline

PowerShell - drive variable

Hello Stackoverflow users,
I am a noob at powershell and this is part of my 1st script I am creating :). I am lost on how I would run a script that is dependent on a drive. I have script that runs task on the d: drive but some hosts does not have a D: drive but has an F: drive instead. What is the best way of adding this variable into the script?
Sample of the script is below
mkdir -Force -Path D:\Apps\NetprobeNT\Auto-monitor
Copy-Item D:\Apps\NetprobeNT\selfannounce.xml -Destination D:\Apps\NetprobeNT\Auto-monitor -Force
$removecomment = Get-Content D:\Apps\NetprobeNT\Auto-monitor\selfannounce.xml
$removecomment = $removecomment -replace "<!--<type>automonitor-windows</type>-->","" -replace "<!-- Autogenerated types -->","" -replace "<!--End of autogenerated types -->",""
$removecomment | ?{$_.Trim() -ne ""}
$removecomment | Out-File D:\Apps\NetprobeNT\Auto-monitor\selfannounce.xml -Encoding default
[xml]$selfannounceXml = Get-Content -Path D:\Apps\NetprobeNT\Auto-monitor\selfannounce.xml
$newCommentstart = $selfannounceXml.CreateComment('Autogenerated types')
$startupNode = $selfannounceXml.netprobe.selfAnnounce.managedEntity.types
$startupNode.InsertAfter($newCommentstart, $startupNode.LastChild)
$selfannounceXml.Save("D:\Apps\NetprobeNT\Auto-monitor\selfannounce.xml")
#Get IIS application path
Import-Module webadministration
$a = Get-Website | Select-Object Name
$a | ForEach-Object {
$_.name = $_.name.replace(" ","")
}
#Export file as .txt
$a | Format-Table -HideTableHeaders | Out-File D:\Apps\NetprobeNT\Auto-monitor\Website.txt
$b = Get-Content -Path D:\Apps\NetprobeNT\Auto-monitor\Website.txt
$b | ForEach {$_.TrimEnd()} | ? {$_.trim() -ne '' } > D:\Apps\NetprobeNT\Auto-monitor\Website.txt
$b = Get-Content -Path D:\Apps\NetprobeNT\Auto-monitor\Website.txt
#(ForEach ($a in $b) {$a.Replace(' ', '')}) > D:\Apps\NetprobeNT\Auto-monitor\Website.txt
#Get XML and add IIS path to 'types'
#Stop-Service -DisplayName NetprobeNT_DES
[xml]$xmlSA = Get-Content D:\Apps\NetprobeNT\Auto-monitor\selfannounce.xml
$b | ForEach-Object {
$tempchild = $xmlSA.CreateElement("type")
$tempchild.set_InnerText($_)
$newType = $xmlSA.netprobe.selfAnnounce.managedEntity.types.AppendChild($tempchild)
}
#$Newcommentstart =
$xmlSA.Save("D:\Apps\NetprobeNT\Auto-monitor\selfannounce.xml")
[xml]$selfannounceXml = Get-Content -Path D:\Apps\NetprobeNT\Auto-monitor\selfannounce.xml
$newCommentstart = $selfannounceXml.CreateComment('End of Autogenerated types')
$startupNode = $selfannounceXml.netprobe.selfAnnounce.managedEntity.types
$startupNode.InsertAfter($newCommentstart, $startupNode.LastChild)
$selfannounceXml.Save("D:\Apps\NetprobeNT\Auto-monitor\selfannounce.xml")
As you can see everything is dependent on D:\Apps.... but in some cases it might be F:\Apps..... How would I put some logic in or variable to know which drive is present? thank you for any help in advance.
Update:
From some help below, I can use the following method for now
$Path = "F:\Apps\NetprobeNT\"
$PathExists = Test-Path $Path
If ($PathExists -eq $True)
{
$DeviceID = "F:"}
Else
{
$DeviceID = "D:"}
How could I do something similar to the script above that would scan all drives and test-path to determine the $DeviceID? Note - must work for PowerShell 2.0 (windows 2003 host).
Thanks Again.
Update 2 -
I think the best method is the following as it will cater for any drive but I can not get it working. I know I am making a simple mistake -
Get-WmiObject win32_logicaldisk -Filter "DriveType=3 AND DeviceID!='C:'" | Select DeviceID | Format-Table -HideTableHeaders > c:\DeviceID.txt -Force
$DeviceID = Get-Content C:\DeviceID.txt
$DeviceID | ForEach {$_.TrimEnd()} | ? {$_.trim() -ne '' } > c:\DeviceID.txt
$DeviceID = Get-Content C:\DeviceID.txt
$Path = "$_\Apps\NetprobeNT\"
$PathExists = Test-Path $Path
foreach ($DeviceID in $DeviceID)
{
If ($PathExists -eq $True)
{
$DeviceDrive = $DeviceID}
Else
{
$DeviceDrive = "C:"}
}
I think the following line is the problem
$Path = "$_\Apps\NetprobeNT\"
Any ideas on to get this working?
Thank you
You can use WMI Filter, Filter only disk volumes which are not C Drive
$DeviceID = Get-WmiObject win32_logicaldisk -Filter "DriveType=3 AND DeviceID!='C:'" |
Select DeviceID
Then change the target:
mkdir -Force -Path "$DeviceID\Apps\NetprobeNT\Auto-monitor"
*Also, it's best practice to use one variable and call it each time, more readable, and easier, like this:
$TargetPath = "$DeviceID\Apps\NetprobeNT\Auto-monitor"
mkdir -Force -Path $TargetPath
I was able to achieve this from another post I posted. The below will make the $DeviceDrive C: drive by default. It will then search all volumes for the path and if true it will assign the drive to $DeviceDrive. Note - if two drives has the same path it will assign the last drive it finds to the variable.
$DeviceDrive = "C:"
Get-WmiObject win32_logicaldisk -Filter "DriveType=3 AND DeviceID!='C:'" |
Where-Object { Test-Path "$($_.DeviceID)\Apps\NetprobeNT\" } |
Foreach-Object {
$DeviceDrive = $_.DeviceID

Powershell script - Start-Job & MSIEXEC

I wonder if you can help please? I have the need to write a Powershell script to execute an MSI script.
I also need to set a time out on the process (as the MSIs we're given sometimes hang).
I've seen that you can acheive this by using the Start-Job/ Wait-Job process
Obviously the code below in in a severe state of butchery currently
Thanks in advance
$timeoutSeconds = 20
$uninstall32 = gci "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match "My File" } | select UninstallString$uninstall64 = gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match "Vix.Cbe.SalesTransaction" } | select UninstallString
Echo "uninstall32 :" $uninstall32
if ($uninstall32) {
$uninstall32 = $uninstall32.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
$uninstall32 = $uninstall32.Trim()
$32p = #("/X", "$uninstall32", "/b")
}
Echo "uninstall32 :" $uninstall32
Echo "u32 :" $32p
$32j = Start-Job msiexec -ArgumentList $32p
if (Wait-Job $32j -Timeout $timeoutSeconds) { Receive-Process $32j }
Remove-Process -force $32j
You don't have to mess with jobs to do that. Here is the easy way:
start Notepad -PassThru | select -ExpandProperty id | set id
sleep 60
kill $id -ea 0
This might not work if app spawns another app and exits as the Id will be wrong. In that case you will probably have to hunt it in the process list or via cmd line params.
Thanks to majkinetor I managed to alter the code sufficiently to acheive my goal.
The only thing is that obviously whether the process is still actively uninstalling or not, its killed after the TOSecs value.
This should be good enough for what I need.
So to explain for anyone else looking for a similar solution:
This process checks both 32 bit and 64 bit Registry entries for an MSI similar to the ServiceName (Urbancode Deploy parameter is the '${p:ServiceName}' passed to the script at runtime)
If it finds an entry it'll execute the uninstall code for the specific 32/64 MSI
/x = Uninstall
$uninstall64/32 = GUID of the Uninstall part to the MSI
/nq = quiet uninstall with no GUI (infact in isolation testing you get a Yes/No dialogue)
The uninstall will run for the amount of seconds that you set in $TOSecs
Hope this helps someone else
$TOSecs = 30
$uninstall32 = gci "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match "'${p:ServiceName}'" } | select UninstallString
$uninstall64 = gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match "'${p:ServiceName}'" } | select UninstallString
if ($uninstall64) {
$uninstall64 = $uninstall64.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
$uninstall64 = $uninstall64.Trim()
Write "Uninstalling 64bit " '${p:ServiceName}'
start-process "msiexec.exe" -arg "/X $uninstall64 /nq" -PassThru |
select -ExpandProperty id | set id
#Echo "proc id = "$id
sleep $TOSecs
kill $id -ea 0
}
if ($uninstall32) {
$uninstall32 = $uninstall32.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
$uninstall32 = $uninstall32.Trim()
Write "Uninstalling 32bit " '${p:ServiceName}'
start-process "msiexec.exe" -arg "/X $uninstall32 /nq" -PassThru |
select -ExpandProperty id | set id
#Echo "proc id = "$id
sleep $TOSecs
kill $id -ea 0
}