Windows Shell,将参数传递给应用程序的运行实例

本文关键字:应用程序 运行 实例 参数传递 Shell Windows | 更新日期: 2023-09-27 18:16:52

我想知道是否有人可以提供一个链接或解释Windows Shell如何传递,例如,一个url到默认应用程序,Internet Explorer, Google Chrome,或一个参数通过自定义构建的应用程序。

我看过这样的例子:使用c#运行shell命令并将信息转换为字符串

上面的链接和其他类似的链接的问题是,它们不像预期的那样工作,或者实际上没有回答实际的问题。例如…

此代码工作正常:

private string EXEPath = @"C:'Program Files (x86)'Internet Explorer'iexplore.exe";
Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = EXEPath,
Arguments = "http://www.google.com.au",
UseShellExecute = true,
RedirectStandardOutput = false,
CreateNoWindow = true
}
};
process.Start();

这个链接给出了一个如何将应用程序设置为单实例应用程序的好例子:http://social.msdn.microsoft.com/Forums/vstudio/en-US/a5bcfc8a-bf69-4bbc-923d-f30f9ecf5f64/single-instance-application

像这样处理参数:

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(args));
}

,然后在Form1中像这样处理参数:

private string[] Args;
public MINION(string[] args)
{
InitializeComponent();
// Assign the incoming Arguments...
this.AppArgs = args;
}
public string[] AppArgs
{
set
{
this.Args = value;
if (this.Args.Length > 0)
{
foreach (string arg in this.Args)
{
// Do the processing here of each arg...
}
}
}
}

我使用点击一次。我有应用程序设置与VB单实例代码在上面的链接。这段代码可以工作,并且只运行应用程序的一个实例。

我的问题:

如果向应用程序传递参数,测试显示进程ID与运行实例的进程ID不相同。因此,显示已经运行的应用程序实例不是Args通过代码传递给的实例:

private string EXEPath = @"C:'Program Files (x86)'My App'My App.exe"; // Or actual path to EXE.
Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = EXEPath,
Arguments = "http://www.google.com.au",
UseShellExecute = true,
RedirectStandardOutput = false,
CreateNoWindow = true
}
};
process.Start();

所以这段代码启动了一个新的实例,即使代码已经到位,将应用程序设置为单个实例应用程序。现有的应用程序实例运行不处理传递的Args。

新实例将显示一个Coded Messagebox("I have run…"),但在此之后退出。

编辑@loopedcode -第一个答案。这是我使用的代码,以确保我在任何时候都与相同的EXE交谈。这也是一种治疗。很遗憾,我已经把你的建议写完了。

Process[] runningProcess = Process.GetProcessesByName("MyEXEName.exe");
Process proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = runningProcess[0].MainModule.FileName,
Arguments = "http://www.google.com.au",
UseShellExecute = true,
RedirectStandardOutput = false,
CreateNoWindow = true
}
};
proc.Start();

我可以验证完全相同的路径是有效的运行实例和Shell调用的EXE的路径。

EDIT - 11.08.14

我想稍微扩展一下这个问题。

当传递参数时,我在新的进程ID中一直到参数的处理,然后将实例切换到单实例应用程序的代码开始启动到现有实例。在此阶段,Args不会传递给现有实例。

如果我使用:

MessageBox.Show("Program ID: " + (Process.GetCurrentProcess().Id) + " Arg Passed: " + this.Args[0]);

它在新实例上运行,而不是在现有实例上运行。

Windows Shell,将参数传递给应用程序的运行实例

要做到这一点,可执行路径必须匹配。如果您正在实例化ClickOnce,那么您的可执行路径就不像您的示例中那样有效:

private string EXEPath = @"C:'Program Files (x86)'My App'My App.exe"; // Or actual path to EXE.

ClickOnce应用程序被下载到用户的个人资料应用程序数据位置。这就是exe将被执行的地方。这取决于Windows版本,可能是(见这篇文章):

这个主题

"c:'users'username'AppData'Local'Apps'2.0'obfuscatedfoldername'obfuscatedfoldername"

或XP:

"C:'Documents and Settings'username'LocalSettings'Apps'2.0'obfuscatedfoldername'obfuscatedfoldername"

文件夹名称(如"obfuscatedfoldername")通常基于应用程序清单签名密钥。如果在EXEPath中检索到正确的文件夹名称,它应该传递参数并正常工作。

终于有办法了。解决方案来自于反复试验。我用来配置单实例应用程序的代码是问题所在,或者我应该说我对这些代码的编写和工作方式的理解是问题所在。这是上面链接上的代码。

using System;   
using System.Collections.Generic;   
using System.Linq;   
using System.Windows.Forms;   
using Microsoft.VisualBasic.ApplicationServices;   
namespace WindowsFormsApplication10   
{   
static class Program   
{   
static Form1 MainForm;   
/// <summary>   
/// The main entry point for the application.   
/// </summary>   
[STAThread]   
static void Main()   
{   
Application.EnableVisualStyles();   
Application.SetCompatibleTextRenderingDefault(false);   
MainForm = new Form1();   
SingleInstanceApplication.Run(MainForm, NewInstanceHandler);   
}   
public static void NewInstanceHandler(object sender, StartupNextInstanceEventArgs e)   
{   
//You can add a method on your Form1 class to notify it has been started again   
//and perhaps pass parameters to it. That is if you need to know for instance    
//the startup parameters.   
//MainForm.NewInstance(e);   
e.BringToForeground = true;   
}   
public class SingleInstanceApplication : WindowsFormsApplicationBase   
{   
private SingleInstanceApplication()   
{   
base.IsSingleInstance = true;   
}   
public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)   
{   
SingleInstanceApplication app = new SingleInstanceApplication();   
app.MainForm = f;   
app.StartupNextInstance += startupHandler;   
app.Run(Environment.GetCommandLineArgs());   
}   
}   
}   
}  

在此代码中传递命令行参数并不像代码中显示的那样直接。当然,这不是我所期望的那样。逻辑流不像预期的那样。不合逻辑。

app.Run(Environment.GetCommandLineArgs());
上面的代码启动了应用程序的一个新实例,这是显而易见的。这是预期的入口点,但它不是。
public static void NewInstanceHandler(object sender, StartupNextInstanceEventArgs e)   
{   
//You can add a method on your Form1 class to notify it has been started again   
//and perhaps pass parameters to it. That is if you need to know for instance    
//the startup parameters.   
//MainForm.NewInstance(e);   
e.BringToForeground = true;   
}

上面的代码是作为一个事件处理程序处理的(不是新实例的,而是应用程序的现有实例的)。

e.BringToForeground = true;   

所以为了解决这个问题,我在这个事件处理程序中添加了一些代码来处理传递的参数:

MainForm.AppArgs = new string[] { "Arg 1", "Arg 2" };

这个测试工作了,我已经调整了这个代码来接受来自

的参数:
static void Main(string[] args)

参数字符串数组。

所以一切都应该像我预期的那样工作,在我的项目中添加第三方代码在等式中抛出了一个曲线球,并且需要一些测试来找出在正确的时间将正确的数据传递到应用程序的正确部分所涉及的实际过程。

所以过程是:EXE执行与参数->参数传递到"主要"的方法通过string[]参数在一个新的过程和一个新的进程ID ->参数设置在一个类变量的新工艺与新进程ID ->新工艺新进程ID启动并检查现有应用程序的实例——>如果有现有的实例是"提出"(这就是我迷路了,我有我的参数传递给现有的实例)和新的过程进程ID退出。

我仍然,然而,不明白参数是如何从一个实例传递到另一个没有任何进程特定的代码?如代码:

MainForm.AppArgs 

实际上在另一个具有不同进程ID的进程中。还是可以访问的?或者Process在此时以某种方式实例化了?