When the script executes, it must check for the presence of this process.
If it fails to find an instance it throws a new instance.
If it finds just one instance inside the local session it must do nothing.
If it find more than one instance it must kill non local instances (the
server can be accessed at the same time by a couple of people by means of RDP)
My assumption is that local session has always session id=0, while RDP
session #1 and RDP session #2 have session id 1 and 2.
Unfortunately, this assumption is far from being always true.
Sometimes local console has session id=1 so script fails; some others RDP
session #2 has session id=4 and so forth.
Is there a way to discriminate between local session and RDP session without
the chance to make a mistake?
Before attaching the code I wanna tell that it would be great if the script
could also realize if a process is blocked and take care of relaunch it.
The code follows:
Option Explicit
Dim objWMIService, objProcess, colProcess
Dim ActiveAcquisitionsConsole, ActiveAcquisitionsSession1,
ActiveAcquisitionsSession2
Dim objWMIServiceNewInstance, objProcessNewInstance
Dim strShellNewInstance, objProgramNewInstance, strComputerNewInstance,
strExeNewInstance
Dim objWMIService1, objProcess1, colProcess1
Dim objWMIService2, objProcess2, colProcess2
Dim strComputer, strAcquisitionProcess
strComputer = "."
strAcquisitionProcess = "'MySoftware.exe'"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
'Search for MySoftware.exe instances inside the local console
Set colProcess = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = " & strAcquisitionProcess )
ActiveAcquisitionsConsole=0
For Each objProcess in colProcess
ActiveAcquisitionsConsole= ActiveAcquisitionsConsole + 1
Next
Set objWMIService1 = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
'Search for MySoftware.exe instances inside the first RDP session (assuming
this session id=1)
Set colProcess1 = objWMIService1.ExecQuery("Select Name from Win32_Process
Where Name='MySoftware.exe' and SessionID = 1" )
ActiveAcquisitionsSession1= 0
For Each objProcess1 in colProcess1
ActiveAcquisitionsSession1= ActiveAcquisitionsSession1 + 1
Next
'Kill every instance of MySoftware.exe inside the first RDP session
(assuming this session id=1)
For Each objProcess1 in colProcess1
objProcess1.Terminate()
Next
Set objWMIService2 = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
'Search for MySoftware.exe instances inside the second RDP session
(assuming this session id=2)
Set colProcess2 = objWMIService2.ExecQuery("Select Name from Win32_Process
Where Name='MySoftware.exe' and SessionID = 2" )
ActiveAcquisitionsSession2= 0
For Each objProcess2 in colProcess2
ActiveAcquisitionsSession2= ActiveAcquisitionsSession2 + 1
Next
'Kill every instance of MySoftware.exe inside the second RDP session
(assuming this session id=2)
For Each objProcess2 in colProcess2
objProcess2.Terminate()
Next
'No instances of MySoftware.exe on local console -> let's launch an instance
if ActiveAcquisitionsConsole = 0 Then
strComputerNewInstance = "."
strExeNewInstance = "MyPathFolder\MySoftware.exe"
' Connect to WMI
set objWMIServiceNewInstance = getobject("winmgmts://"_
& strComputerNewInstance & "/root/cimv2")
Set objProcessNewInstance = objWMIServiceNewInstance.Get("Win32_Process")
Set objProgramNewInstance = objProcessNewInstance.Methods_( _
"Create").InParameters.SpawnInstance_
objProgramNewInstance.CommandLine = strExeNewInstance
Set strShellNewInstance = objWMIServiceNewInstance.ExecMethod( _
"Win32_Process", "Create", objProgramNewInstance)
End if
WScript.Quit
Thanks for your help!
Logon to the system directly and type SET at the command prompt, saving the
results in a text file. Then logon to the system via RDP and do the same
thing. You will likely find that some of the environment variables defined
have values depending on whether the session is an RDP session. I have
nothing to RDP against, however, I think you might find CLIENTNAME and
SESSIONNAME useful; when logged on directly, they are set to "Console".
/Al
Eventually this (simple?) script would save me a lot of headache, so I'm
asking for futher assistance.
Can someone point me to the right direction with more straightforward
suggestions?
Thanks.
WMI is a wonderful thing. However, when someone has already done most of the
work and delivered a suitable tool then it would make sense to use that
tool. Tasklist.exe / Taskkill.exe are such tools. Tasklist tells you
unambiguously whether a process is run from the console or from an RDP
session and it also gives you a process-ID that you can feed into
taskkill.exe. Try the following batch file:
[1] @ECHO off
[2] set active=no
[3] set task=MySoftware.exe
[4] for /F "tokens=1-3" %%a in ('tasklist /v /fo table ^| find /i "%task%"')
do (
[5] if /i [%%c]==[Console] (set active=yes) else (echo taskkill /f /pid
%%b)
[6] )
[7] if %active%==no echo "c:\Program Files\Passeron\%task%"
To activate the batch file, remove the word "echo" from lines [5] and [7].
Post again if you want to know what each line of code does. Make sure to
unwrap wrapped lines properly!
The code follows:
@ECHO off
set active=no
set task="MySoftware.exe"
for /F "tokens=1-3" %%a in ('tasklist /v /fo table ^| find /i "%task%"')
do (
if /i [%%c]==[Console] (set active=yes) else (taskkill /f /pid %%b )
)
if %active%==no "C:\MyFolder\%task%"
"Big Passeron" <BigPa...@discussions.microsoft.com> wrote in message
news:5DDF9E04-D175-4050...@microsoft.com...
[1]@ECHO on
[2]set active=no
[3](set task='My Software 1.00.exe')
[4]for /F "tokens=1-3" %%a in ('tasklist /v /fo table ^| find /i "%task%"')
do (
[5]if /i [%%c]==[Console] (set active=yes) else ( taskkill /f /im %%b ))
[6]if %active%==no "C:\My Folder\%task%"
A problem is with task's name that's composed by more than one word and from
uncertainty with single and double quotes.
As a consequence, this is the output given by the command:
C:\My Folder\>set active=no
C:\My Folder\>(set task='My Software 1.00.exe' )
C:\My Folder\>for /F "tokens=1-3" %a in ('tasklist /v /fo table | find /i
"'My Software 1.00.exe'"') do (if /I [%c] == [Console] (set active=yes )
else (taskkill /f /im %b ) )
C:\My Folder\>if no == no "C:\My Folder\'My Software 1.00.exe'"
I guess the problem is with the single quote before my tasks's name. I also
tried with double quotes but the script fails to execute.
Here is a modified version that can cope with executables that have embedded
spaces in the name.
[01] @echo off
[02] SetLocal EnableDelayedExpansion
[03] set active=no
[04] set task=My Software 1.00.exe
[05] for /F "tokens=1-3 delims=," %%a in ('tasklist /v /fo csv ^| find /i
"%task%"') do (
[06] for /F %%i in (%%b) do set pid=%%~i
[07] if /i [%%c]==[Console] (set active=yes) else (echo taskkill /f /pid
!pid!)
[08] )
[09] if %active%==no echo "C:\My Folder\%task%"
"Big Passeron" <BigPa...@discussions.microsoft.com> wrote in message
news:AC285389-B482-471F...@microsoft.com...
I don't know if this behavior is caused by scheduled task be executed as
user Administrator, while user logged inside Console session is a Standard
User (for security purposes).
To make a long story short, I've made some little modifications to your
script (among the other things, I want the process to be launched with
StandardUser credentials, should an instance not be running), but it still
doesn't work as expected. The code follows:
"[1]@echo on
[2]SetLocal EnableDelayedExpansion
[3]set active=no
[4]set task=MyTask.exe
[5]for /F "tokens=1-3 delims=," %%a in ('tasklist /v /fo csv /fi "imagename
eq %task%"') do (
[6]for /F %%i in (%%b) do set pid=%%~i
[7]if /i [%%c]==[""] (set active=yes) else (taskkill /f /pid !pid!)
[8)
[9]if %active%==no Runas /user:MyServer\StandardUser /savecred
"C:\MyFolder\%task%"
"
Thanks for your help
set task=MyTask.exe
tasklist /v /fo csv /fi "imagename eq %task%
If you get no output then there you must run this command so that you can
tell the correct image name:
tasklist /v /fo List | more
"Big Passeron" <BigPa...@discussions.microsoft.com> wrote in message
news:72A29975-B448-4938...@microsoft.com...
i don't know how to correct this behavior...
I am unable to duplicate the behaviour you observe. When I run a scheduled
task then it is flagged as a Console session, not as an RDP session. I
tested this both on a WinXP PC and on an SBS installation, using the Task
Scheduler GUI and at.exe. Same result everywhere.
Could it be that the OP is logged on using the account that runs the task in
the scheduler?
/Al