传递命令行到单实例应用程序的第一个实例 [英] Pass Command Line to first instance of a Single Instance App
问题描述
我已经执行上下文菜单,当用户使用注册表右键点击一个文件在Windows资源管理器出现。该文件地址将被传递给应用程序的命令行。分析它是没有问题的。
我如何可以实现类似于添加到Windows Media Player播放列表?它不打开应用程序的另一个实例,但工作在同一个打开的窗口,并将其添加到一个列表?
有2种方式,视乎你的应用程序开始执行此操作。
方法1:使用VB应用程序框架和的MainForm
这是最简单的,因为你主要是只需要添加一些$ C $下一个应用程序事件。首先,添加一个方法到您的主要形式的接受新的观点,从你的应用程序的后续实例:
格式的公共类MyMainForm注类名
...
公用Sub NewArgumentsReceived(参数为String())
' 例如。将它们添加到列表框中
如果args.Length> 0然后
lbArgs.Items.AddRange(参数)
结束如果
结束小组
下一篇:
- 开启项目属性
- 检查使单一实例选项
- 在底部,点击查看应用程序事件
- 这将打开像任何其他新的code窗口;选择
在左边的下拉MyApplication的活动
;和StartupNextInstance
在正确的。
在这里,我们发现的主要形式,并发送命令行参数,我们创建的方法:
私人小组MyApplication_StartupNextInstance(发件人为对象,
E上ApplicationServices.StartupNextInstanceEventArgs)_
手柄Me.StartupNextInstance
昏暗F = Application.MainForm
用你的实际的窗体类名:
如果f.GetType是的GetType(MyMainForm)然后
CTYPE(F,MyMainForm).NewArgumentsReceived(e.CommandLine.ToArray)
结束如果
结束小组
请注意:不要试图以鱼的主要形式出 Application.OpenForms
的。有几次我已经受够了无法找到一个开放的形式集合中,所以我已经退出依赖它。 Application.MainForm
也更简单。
这就是它 - 一个新的实例运行时,它的命令行参数应该传递的形式和显示在列表框(或处理,但你的方法认为合适)。
方法2:从开始子主
这是比较复杂的,因为在开始从子主意味着VB应用程序框架不使用,它提供了 StartupNextInstance
事件您的应用程序。解决的办法是继承 WindowsFormsApplicationBase
来提供所需的功能。
首先,给你的主要形式,一个有意义的名称,并添加类似 NewArgumentsReceived(参数为String())
如上。
对于那些不知道,这里是如何从开始您的应用程序子的Main()
:
- 添加一个名为程序模块,您的应用程序
- 添加
公用Sub主要()
给它。 - 转到项目 - >属性 - >应用程序
- 取消选中
启用应用程序框架
- 选择您的新的子主为启动对象
该模块其实是可以命名,计划
的约定VS使用的C#应用程序。在$ C $下子主
稍后会后,我们创建类。大部分下列源于一个古老的MSDN文章或博客什么的。
进口Microsoft.VisualBasic.ApplicationServices
进口System.Collections.ObjectModel
公共类SingleInstanceApp
这是My.Application
继承WindowsFormsApplicationBase
公共子新(模式AuthenticationMode)
MyBase.New(模式)
InitializeApp()
结束小组
公共子新()
InitializeApp()
结束小组
我们要实现标准的启动程序
受保护的可重写小组InitializeApp()
Me.IsSingleInstance = TRUE
Me.EnableVisualStyles = TRUE
结束小组
即Application.Run(FRM):
公共重载Sub运行(FRM作为表)
'设置的MainForm用作消息泵
Me.MainForm = FRM
通过命令行
Me.Run(Me.CommandLineArgs)
结束小组
私人重载Sub运行(参数作为ReadOnlyCollection还(串))
转换RO集合简单数组
这些将被分主要处理一审
'和在StartupNextInstance处理程序他人
Me.Run(myArgs.ToArray)
结束小组
可选:保存退出设置
受保护的覆盖子OnShutdown()
如果My.Settings.Properties.Count> 0然后
My.Settings.Save()
结束如果
MyBase.OnShutdown()
结束小组
末级
请注意,这三个主要的东西在App框架能为我们做什么(启用XP样式,做单实例和退出时保存设置)都占了。现在,一些修改子主
:
进口Microsoft.VisualBasic.ApplicationServices
进口System.Collections.ObjectModel
模块程序
这个应用程序的主要形式
朋友myForm会随着MyMainForm
公用Sub主要(参数为String())
创建硬连接到SingleInstance应用程序对象
昏暗的应用程序作为新SingleInstanceApp()
对于添加处理程序时,第二个实例试图启动
(奇迹发生在那里)
AddHandler的app.StartupNextInstance,AddressOf StartupNextInstance
myForm会=新MyMainForm
进程的命令行参数在这里的第一个实例
'喊你添加到窗体的方法:
myForm.NewArgumentsReceived(参数)
启动应用程序
app.Run(myForm的)
结束小组
这是调用时以后的情况下,尝试启动。
抓住并处理其命令行
私人小组StartupNextInstance(发件人为对象,
E上StartupNextInstanceEventArgs)
TODO:过程e.CommandLine提供的命令行。
myForm.NewArgumentsReceived(e.CommandLine.ToArray)
结束小组
前端模块
在 SingleInstanceApp
类可以与任何子主
风格的应用程序可以重复使用,和code在方法主要是复制粘贴样板外遇除了 NewArgumentsReceived
的方法也许是形式的参考和真实姓名。
测试
编译应用程序,然后使用命令行窗口,把一些命令行参数的应用程序。我使用的:
C:\ TEMP> singleinstance第一出师表苹果蝙蝠猫
这将启动应用程序的正常,显示的参数。然后:
C:\ TEMP> singleinstance下一步出师表齐格Zoey的zacky
C:\ TEMP> singleinstance最后出师表111 222 3333
不管从你使用的方法 - 他们都工作相同。结果:
请注意,根据安全设置,防火墙可以请求准许使用上述两种方法连接到其他计算机的应用程序。这是如何实例发送或监听来自其他参数的结果。至少在我的,我也不能否认允许连接,一切仍然正常工作。
I have already implemented context menu to appear when a user right-clicks a file in windows explorer using Registry. The file address will be passed to the application as command lines. Parsing it is no problem.
How can I implement that is similar to "Add To Windows Media Player Playlist"? It does not open another instance of the app but works on the same open window and adds it to a list?
There are 2 ways to do this depending on how your app starts.
Method 1: Using VB App Framework and a MainForm
This is the easiest because you mainly just need to add some code for an Application event. First, add a method to your main form to receive new arguments from subsequent instances of your app:
Public Class MyMainForm ' note the class name of the form
...
Public Sub NewArgumentsReceived(args As String())
' e.g. add them to a list box
If args.Length > 0 Then
lbArgs.Items.AddRange(args)
End If
End Sub
Next:
- Open Project Properties
- Check the "Make Single Instance" option
- At the bottom, click View Application Events
- This will open a new code window like any other; Select
MyApplication Events
in the left drop down; andStartupNextInstance
in the right one.
Here, we find the main form and send the command line arguments to the method we created:
Private Sub MyApplication_StartupNextInstance(sender As Object,
e As ApplicationServices.StartupNextInstanceEventArgs) _
Handles Me.StartupNextInstance
Dim f = Application.MainForm
' use YOUR actual form class name:
If f.GetType Is GetType(MyMainForm) Then
CType(f, MyMainForm).NewArgumentsReceived(e.CommandLine.ToArray)
End If
End Sub
Note: Do not try to fish the main form out of Application.OpenForms
. A few times I've had it fail to find an open form in the collection, so I have quit relying on it. Application.MainForm
is also simpler.
That's it - when a new instance runs, its command line args should be passed to the form and displayed in the listbox (or processed however your method sees fit).
Method 2: Starting From Sub Main
This is more complicated because starting your app from a Sub Main means that the VB Application Framework is not used, which provides the StartupNextInstance
event. The solution is to subclass WindowsFormsApplicationBase
to provide the functionality needed.
First, give your main form a meaningful name and add something like the NewArgumentsReceived(args As String())
as above.
For those not aware, here is how to start your app from Sub Main()
:
- Add a module named 'Program' to your app
- Add a
Public Sub Main()
to it. - Go to Project -> Properties -> Application
- Uncheck
Enable Application Framework
- Select your new "Sub Main" as the Startup Object
The module can actually be named anything, Program
is the convention VS uses for C# apps. The code for Sub Main
will be later after we create the class. Much of the following originated from an old MSDN article or blog or something.
Imports Microsoft.VisualBasic.ApplicationServices
Imports System.Collections.ObjectModel
Public Class SingleInstanceApp
' this is My.Application
Inherits WindowsFormsApplicationBase
Public Sub New(mode As AuthenticationMode)
MyBase.New(mode)
InitializeApp()
End Sub
Public Sub New()
InitializeApp()
End Sub
' standard startup procedures we want to implement
Protected Overridable Sub InitializeApp()
Me.IsSingleInstance = True
Me.EnableVisualStyles = True
End Sub
' ie Application.Run(frm):
Public Overloads Sub Run(frm As Form)
' set mainform to be used as message pump
Me.MainForm = frm
' pass the commandline
Me.Run(Me.CommandLineArgs)
End Sub
Private Overloads Sub Run(args As ReadOnlyCollection(Of String))
' convert RO collection to simple array
' these will be handled by Sub Main for the First instance
' and in the StartupNextInstance handler for the others
Me.Run(myArgs.ToArray)
End Sub
' optional: save settings on exit
Protected Overrides Sub OnShutdown()
If My.Settings.Properties.Count > 0 Then
My.Settings.Save()
End If
MyBase.OnShutdown()
End Sub
End Class
Note that the three main things the App Framework can do for us ("Enable XP Styles", "Make Single Instance" and "Save Settings on Exit") are all accounted for. Now, some modifications to Sub Main
:
Imports Microsoft.VisualBasic.ApplicationServices
Imports System.Collections.ObjectModel
Module Program
' this app's main form
Friend myForm As MyMainForm
Public Sub Main(args As String())
' create app object hardwired to SingleInstance
Dim app As New SingleInstanceApp()
' add a handler for when a second instance tries to start
' (magic happens there)
AddHandler app.StartupNextInstance, AddressOf StartupNextInstance
myForm = New MyMainForm
' process command line args here for the first instance
' calling the method you added to the form:
myForm.NewArgumentsReceived(args)
' start app
app.Run(myForm)
End Sub
' This is invoked when subsequent instances try to start.
' grab and process their command line
Private Sub StartupNextInstance(sender As Object,
e As StartupNextInstanceEventArgs)
' ToDo: Process the command line provided in e.CommandLine.
myForm.NewArgumentsReceived(e.CommandLine.ToArray)
End Sub
End Module
The SingleInstanceApp
class can be reused with any Sub Main
style app, and the code in that method is mainly a copy-paste boilerplate affair except for perhaps the form reference and actual name of the NewArgumentsReceived
method.
Testing
Compile the app, then using a command window, send some commandline arguments to the app. I used:
C:\Temp>singleinstance "First Inst" apple bats cats
This starts the app as normal, with the arguments shown. Then:
C:\Temp>singleinstance "Next Inst" ziggy zoey zacky
C:\Temp>singleinstance "Last Inst" 111 222 3333
It doesnt matter which approach you use - they both work the same. The Result:
Note that depending on security settings, your firewall may request permission for apps using either method to connect to other computers. This is a result of how an instance sends or listens for the arguments from others. At least with mine, I can deny permission to connect and everything still works fine.
这篇关于传递命令行到单实例应用程序的第一个实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!