Check whether a RunspacePool is already open on a machine - powershell

I have a process that runs Powersell script on a VM. This script defines a RunspacePool on the VM and sets threshold (no. of Runspaces) based on the resource capability of that VM. This process is recurring so I do not want it to keep defining and opening RunspacePools when there is already one defined and opened on that VM
At the beginning of the Powershell script, I have tried to check whether a Runspacepool is already defined\ opened by calling RunspacePoolStateInfo or RunspacePoolAvailability properties. But these are not identified as the Runspacepool object itself is not available in the new window that the process opens up to run the script
I am basically looking for a way to identify that a RunspacePool is open on a VM by using Powershell scripting

Answer for PowerShell V5 and newer
You can get the Runspacess in the current processes by running
Get-Runspace
or if you know the name
Get-Runspace -Name <name>
Remote Runspaces in PowerShell V5
If the Runspace you want to check is in another process, you must first do this.
Enter-PSHostProcess -Id <int>
or
Enter-PSHostProcess -Process <ProcessObject>

Related

invoke a private environment variable of a process from another PS Session

I have a process (testxx) running on my Database. Every time a user connects with the database the process will start separate session for. All processes include a private environment variable(Client-Nr) with different values. I want to invoke a particular process with the particular private environment variable. I used the following command:
Let's say there are 5x "testxx"-processes. I want to invoke the one process which has the value "Client-Two" in the private environment variable "Client-Nr".
Therefore, I use the following code:
get-process -name "testxx" | where-object {$env:Client-Nr -eq "client-Two"}
It didn't invoke the process I needed. I checked with the following command, if PowerShell recognize the private environment variable:
(get-process -Name "testxx").StartInfo.EnvironmentVariables
PowerShell didn't recognized this private environment variable. However, if I open "Process Hacker", choose the specific "testxx" process, I see the private environment variable "client-Nr" with that particular "Client-nr" value. How can I invoke this kind of private environment variable via PowerShell?
I think this will be to long for a comment but actually it is meant as one. ;-)
I'm still not really sure if I got what you want. But if it is what I think it is you may go the wrong way. I think PowerShell (Windows) does not have the concept of private environment variables only belonging to one single running process. I think the environment variables you can get with .StartInfo.EnvironmentVariables from the object of the type System.Diagnostics.Process are the environment variables inherited by the process when it started. So they will not change over time the process runs.
You would need an attribute what's - manipulated from the inside of the process - visible to the outside of the process. For manually started consoles this could be the MainWindowTitle.
You may test this. I created a file GUID-Title_90Sec.ps1 with the content:
$Host.UI.RawUI.WindowTitle = $(New-Guid)
Start-Sleep -Seconds 90
Now I ran this a few times:
Start-Process Powershell -ArgumentList '-NoProfile', '-File .\GUID-Title_90Sec.ps1'
And with ...
Get-Process -Name PowerShell |
Select-Object -Property Name,MainWindowTitle
... you could list all of those processes what's looking something like this:
Name MainWindowTitle
---- ---------------
powershell ParentProcess
powershell ff37b8b6-f791-4d2b-8dfd-8c0dc0a8bc96
powershell fe06d061-784f-441b-8cd4-0a2d3ec040c5
powershell 9f954fb5-cda8-4f2a-98fe-391c59c51ab2
powershell 095a8019-08d5-4461-ab3c-d6f0f2f485cb
powershell
I just doubt that this would work with processes started by a database engine because they probably will not have a MainWindowTitle. Sorry. ;-)
Edit:
Instead of trying to identify the processes afterwards you could keep track of the processes you start.
When you save the process info the moment you start it in a variable you can use it later on. With ...
$PowerShellInstance = Start-Process Powershell -PassThru
you start a new PowerShell session. With ...
$PowerShellInstance
... you have all information about this process. For example ...
$PowerShellInstance.Id
... shows the process id. Could this be helpful? ;-)

Powershell script triggers process only when invoked manually. Timing out when triggered via Scheduled Task

On a Windows 2012 R2 server there is a Powershell script that I can manually invoke to start a process on some EXE, this works just fine.
But when trying to trigger it via a scheduled task (invoking the same script) the start-process within the script just doesn't trigger or finish. Causing the task scheduler to terminate the task due to exceeding the timeout threshold.
Here's the core section of the script:
$exe = "c:\some\app.exe"
$arguments = "-user me -pwd secret"
$process = Start-Process $exe -ArgumentList $arguments -PassThru -Wait
return $process
Is there some way I can get some insights into what start-process is doing or why the same script works when invoked manually but not programmatically?
I want to emphasize that the way the script is invoked from the scheduled task is not a problem! The script triggers because the corresponding log file populates.
Any insights or help on this is greatly appreciated!
quick update on this since I found the problem. It turns out, it had nothing to do with either the powershell script or the scheduled task itself...
On the machine the script is running on, there is a network share that is mapped as the z:\ drive. I use it to save logs to. Now apparently that mapping/mounting is handled differently depending on whether the script is invoked interactively or programatically, because in the latter case it appears that the resoultion of the network path \\network\share\folder1 does not succeed, however there is nothing complaining about it, the process just silently does not start. If however, I point the logs to a physical local path or the explicit full network path itself, there is no problem running the script.
Lesson learned, never trust OS' drive mapping of network paths :D
Cheers

How to show the current pshostprocess and runspace information?

When debugging a powershell DSC resource, we have a help from the DSC resource which shows the commands needed to attach the debugger to the right Powershell Runspace. As described in https://overpoweredshell.com/Troubleshooting-DSC/:
I want to be able to output the same kind of help from my powershell script, nothing to do with DSC.
So, how do I figure out my current PSHostProcess, AppDomain and Runspace Id from my powershell script?
I do not want to debug in ISE or any other GUI (for the reasons irrelevant to the question).
The process ID of the host process is available via the $PID automatic variable.
The name of the containing AppDomain can be found via:
[AppDomain]::CurrentDomain.FriendlyName
but is usually not necessary when targeting most host applications (such as powershell.exe or powershell_ise.exe)
For the runspaces, use Get-Runspace from the host application:
Get-Runspace

How To Populate Shutdown Executable field in IIS App Pool through Powershell

In Internet Information Services Manager, for each app pool, there is an option to set path to a Shutdown Executable, and any parameters under Rapid-Fail Protection in advanced settings.
I have several app pools (a couple hundred) and would like to use a PowerShell script to automate setting
the shutdown field of each one to a program I created.
Does such a PowerShell command exist? I have pored through the appropriate documentation but with no results.
Short answer? I cant figure it out in Powershell specifically, However.. using "appcmd.exe" I was able to make this happen. I wrote a script that tried to restart the app pool and emails me the result. This script gets kicked off by the rapid fail protection. I can share this script too if you like...
However, I really didnt want to manually set every app pool as you mention, so I came up with the following.. Its not as pretty or elegant as some, but, it works:
$poolList = (Get-ItemProperty -Path "IIS:\AppPools\*").name
ForEach($pool in $poolList) {
C:\Windows\System32\inetsrv\appcmd.exe set apppool "$pool" /Failure.autoshutdownParams:"D:\_Scripts\CheckPools.ps1 -PoolName $pool"
C:\Windows\System32\inetsrv\appcmd.exe set apppool "$pool" /Failure.autoshutdownexe:"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
Get-ItemProperty -Path "IIS:\AppPools\$pool" -name Failure.autoshutdownexe|select *
}
I can confirm for me, with Windows 2016, this script sets the Shutdown Executable, and the Shutdown Executable Parameter. The Executable is set to launch powershell, and the parameters calls a powershell script and passes it the app pool name.

Triggering a remote powershell script to run independently

I've created a script which calls 'dfsutil', and is available for all the members in my team. Some members don't have RSAT (dfsutil) installed locally, so I'd like to 'trigger' a .ps1 script independently of the source PC (PC1) to be run on a server (Server1) which has 'dfsutil' installed.
It's easy enough to trigger a remote PowerShell script from the source 'PC1' by dot-sourcing it from 'myscript.ps1':
. \\Server1\scripts\dfsscript.ps1
As we already know, the above will fail as PowerShell is looking for 'dfsutil' locally on PC1, rather than on the server 'Server1'.
'dfsscript.ps1' has been written so it can be run independently, without need to return the values to PC1.
I can't seem to find any documentation which shows how to initialise a remote script which only uses the values and conditions of the OS it was triggered on.
Any thoughts?
Dot-sourcing is about the scope of a PowerShell session, but doesn't include the computing environment, so what you are doing won't get the script on Server1 to run from Server2, but still act like it is on Server1 with access to all of Server1's installed apps, etc.
What you need to do is use PowerShell remoting to actually run the script on the remote server (i.e. trigger from Server2, but execute on Server1). For example:
Invoke-Command -ComputerName Server1 -FilePath <path>\script.ps1