Registry shell open, unless already running - in which case...
Hi guys,
I'm writing to the registry to create a custom web protocol that passes variables to my program, so that on the web, my application would handle URLs like: appname:var1/var2 -- This has worked out great thus far, however, I have it setup in the registry somewhat like this:
Which is OK if the program has not already been executed, but if the program is already a running process, it will not communicate with the running .exe, but instead open a new (duplicate) one.
Now, I didn't really expect it to 'communicate' with the existing one automatically or anything, as I know from messing with VB6 for a few months now, that nothing really 'communicates' on its own.
So, my question is; How can I say, if xxxxxxx.exe is running, do not open a new instance and instead open communication with the current process, otherwise [else] open a new xxxxxxx.exe
In case you were wondering, the remainder of the function resembles this:
Code:
'command is the command that open the program, if you double clicked the icon, the path would be "" nothing.
'if a file called the opening of this program, the Command would be the path of that file
Path = Command
If Path = "" Then ' if no file requested it to open, aka you click the icon to execute the program
Else ' if it was requested by a webpage, then do the following
ExtractData1
ExtractData2
ExtractData3
End If
Thanks a lot!
David
Last edited by DavidNels; Dec 20th, 2008 at 03:25 AM.
Re: Registry shell open, unless already running - in which case...
This may be a sledgehammer to crack a nut, but you could use WMI (Win32_Process class) to enumerate running processes and then check the ExecutablePath property to see if the .exe in question is running.
Something like this:
Code:
Option Explicit
Private Function IsExeRunning(strProg As String) As Boolean
Dim wmiServices As Object
Dim wmiObjects As Object
Dim wmiObject As Object
Dim strPath As String
Dim strDetails() As String
Set wmiServices = GetObject("winmgmts:\\")
Set wmiObjects = wmiServices.InstancesOf("Win32_Process")
For Each wmiObject In wmiObjects
If wmiObject.executablepath <> vbNullString Then
strPath = wmiObject.executablepath
strDetails = Split(strPath, "\")
If UCase(strDetails(UBound(strDetails))) = UCase(strProg) Then
IsExeRunning = True
Exit For
End If
End If
Next
End Function
Private Sub Command1_Click()
Dim strExe As String
strExe = "VB6.exe" ' The .exe you're looking for
If IsExeRunning(strExe) = True Then
MsgBox "Program is running"
Else
MsgBox "Program is not running"
End If
End Sub
Re: Registry shell open, unless already running - in which case...
Looks good, I'm sure I'll be able to put that to use in whatever I do, thanks a lot!
I guess the only thing in question is, how can I get it to continue with it's original task?
I'm basically a moron when it comes to working within the registry and its functions and VB6, but presently it seems my HKEY_CLASSES_ROOT\app\shell\open\command", "", "" & EXEpath is only going to want to open a new EXE, regardless of whether or not it is currently running.
Re: Registry shell open, unless already running - in which case...
David,
I guess it depends upon how you 'communicate' with the Application. If the .exe is running then IsExeRunning = True, so under that condition you put whatever code you use to communicate with it. If the result is False then you can start-up the new process and communicate with that.
Re: Registry shell open, unless already running - in which case...
Hey,
It could go either way, if I'm understanding you correctly.
Since this is all initiated by someone clicking a link in Firefox or IE, or any browser, (a link like protocol:variable1), then the program may, or may not be running, and I'm not sure how to 'inject' a check for that.
In the registry is what launches the .exe, but since I do not know much about the registry, I'm not sure how to insert the running process check before the application already launches.
If it helps, here's a bit more of the rough code.
The 'communication' comes in after it splits up the variables from the command string and assigns them to the value of the textboxes on the form.
Code:
Option Explicit
Sub Main()
Dim EXEpath As String
Dim Path As String
'just to make sure we get the quotes and %1 in the registry entry below
EXEpath = "" + Chr(34) + "" + App.Path + "\" + App.EXEName + ".exe" + Chr(34) + " %1"
'create the needed registry entries for our custom protocol
CreateKey "HKEY_CLASSES_ROOT\Tester"
CreateKey "HKEY_CLASSES_ROOT\Tester\shell"
CreateKey "HKEY_CLASSES_ROOT\Tester\shell\open"
CreateKey "HKEY_CLASSES_ROOT\Tester\shell\open\command"
SetStringValue "HKEY_CLASSES_ROOT\Tester", "", "URL: TesterProtocol"
SetStringValue "HKEY_CLASSES_ROOT\Tester", "URL Protocol", ""
SetBinaryValue "HKEY_CLASSES_ROOT\Tester", "EditFlags", Chr$(&H2) + Chr$(&H0) + Chr$(&H0) + Chr$(&H0)
SetStringValue "HKEY_CLASSES_ROOT\Tester\shell\open\command", "", "" & EXEpath
'command is the command that open the program, if you double clicked the icon, the path would be "" nothing.
'if a file called the opening of this program, the Command would be the path of that file
Path = Command
If Path = "" Then ' if no file requested it open
Form1.Show
Else ' if it was requested by a file, then do the following
ExtractData1
ExtractData2
ExtractData3
Form1.Show
End If
End Sub
Public Sub ExtractData1()
Dim CMDLine As String
CMDLine = Command
CMDLine = Mid(CMDLine, InStr(1, CMDLine, ":") + 1) 'tells it, we want everything 1 space in front of the :
CMDLine = Mid(CMDLine, 1, InStr(1, CMDLine, "?") - 1) 'tells it, we want everything 1 space behind the ?
Form1.Text1.Text = CMDLine 'text1 get the cleaned up stuff
End Sub
Public Sub ExtractData2()
Dim CMDLine As String
CMDLine = Command
CMDLine = Mid(CMDLine, InStr(1, CMDLine, "?") + 1) 'tells it, we want everything 1 space in front of the ?
CMDLine = Mid(CMDLine, 1, InStr(1, CMDLine, "$") - 1) 'tells it, we want everything 1 space behind the $
Form1.Text2.Text = CMDLine 'text2 get the cleaned up stuff
End Sub
Public Sub ExtractData3()
Dim CMDLine As String
CMDLine = Command
CMDLine = Mid(CMDLine, InStr(1, CMDLine, "$") + 1) 'tells it, we want everything 1 space in front of the $
CMDLine = Mid(CMDLine, 1, InStr(1, CMDLine, "*") - 1) 'tells it, we want everything 1 space behind the *
'the above line isnt really needed, i dont think, but i left it there incase you want to add more
Form1.Text3.Text = CMDLine 'text3 get the cleaned up stuff
End Sub
actualy cause the program to run? If that is the case then you'd put the check before the key is created, ie if the program is already running don't run another copy. I'm still confused about the 'communicate with...' aspect (it may just be me!!)
Re: Registry shell open, unless already running - in which case...
you can use app.previnstance to see if your vb6 program is already running
and dde to pass information to your running instance
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Re: Registry shell open, unless already running - in which case...
Hey, great idea! But I am having an issue here, and it's driving me mad..
First of all, instead of using app.previnstance I ended up having an intermediate new EXE that will handle whether or not the program is open, and if it is, it will send via DDE, otherwise it will prompt the user whether or not they'd like to open the program.
So now the registry opens this intermediate EXE which does all the checking for me.
This is killing me, though, I got it working great using DDE in a couple test projects, but now that I'm actually trying to apply this code to my destination/source project, it won't communicate with the initial executive -- I get runtime error 282, "No foreign application responded to a DDE initiate"
I know that the problem is within the destination/source form, because my initiating/sending exe works fine to communicate with other destination forms if I tweak it to match their linktopics.
What's frustrating is I've been studying this for hours trying to figure out what's wrong with this tiny little thing... Maybe I'm missing something...
I have completed these steps: 'Send' project has LinkMode set to 0, LinkTopic set to DDETest 'Destination' project has LinkMode set to 1 (source), and LinkTopic set to DDETest Form -> LinkExecute has been setup on 'Destination' project.
'Send' project form:
Code:
Option Explicit
Private Sub Command1_Click()
HiddenText.Text = Command$
HiddenText.LinkTopic = "Source|DDETest"
'Set the link topic
HiddenText.LinkMode = vbLinkManual
'Initiate the DDE link
HiddenText.LinkExecute HiddenText.Text
'Send data
HiddenText.LinkMode = vbLinkNone
End Sub
'Destination' Project Form:
Code:
Private Sub Form_LinkExecute(CmdStr As String, Cancel As Integer)
Text1.Text = CmdStr
Cancel = 0
End Sub
I'm confident I've been through every bit of this code (many times) and nothing seems out of place, but I could be wrong.
I'm also wondering if there are any common/known triggers for this error to occur. It would seem as though the problem may reside in the environment which I am now using this code, rather than the code itself.
Re: Registry shell open, unless already running - in which case...
i have a sample project i downloaded someplace (vbhelper) using app.previnstance i have tested it and edited it a bit
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Re: Registry shell open, unless already running - in which case...
Hi there,
Yes I looked at the same article at one point.
I just can't seem to figure out what in my project is conflicting with my it, or not allowing it to communicate, unless there is indeed something wrong with what I'm doing, however you may review all that I'm doing above, and [I think] it looks good