传递命令行到单实例应用程序的第一个实例 [英] Pass Command Line to first instance of a Single Instance App

查看:489
本文介绍了传递命令行到单实例应用程序的第一个实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经执行上下文菜单,当用户使用注册表右键点击一个文件在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; and StartupNextInstance 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆