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

C# Windows Shell,将参数传递给正在运行的应用程序实例,c#,shell,arguments,C#,Shell,Arguments,我想知道是否有人可以提供一个关于Windows Shell如何传递的链接或解释,例如,默认应用程序的url、Internet Explorer、Google Chrome或自定义构建应用程序的参数 我看过一些例子,例如: 上面的链接和其他类似链接的问题是,它们没有按照预期工作,或者实际上没有回答实际问题。例如 此代码工作正常: private string EXEPath = @"C:\Program Files (x86)\Internet Explorer\iexplore.exe"; P

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

我看过一些例子,例如:

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

此代码工作正常:

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();
此链接提供了一个很好的示例,说明如何将应用程序设置为单实例应用程序:

按如下方式处理arg:

/// <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));
}
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();
MainForm.AppArgs 
因此,该代码启动一个新实例,即使该代码已准备好将应用程序设置为单个实例应用程序。正在运行的现有应用程序实例不处理传递的参数

新实例将显示一个编码的Messagebox(“我已运行…”),但随后退出

编辑 @循环代码-第一个答案。这是我用来确保始终与同一个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();
我可以验证相同的路径对于正在运行的实例以及对EXE路径的Shell调用是否有效

编辑-11.08.14

我想把问题扩大一点

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

如果我使用:

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

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

要使其工作,可执行路径必须匹配。如果您正在实例化ClickOnce,则您的可执行路径与示例中的路径不同:

private string EXEPath = @"C:\Program Files (x86)\My App\My App.exe"; // Or actual path to EXE.
ClickOnce应用程序下载到用户的配置文件应用程序数据位置。这就是执行exe的位置。根据Windows版本,可能是():

Win7

或XP:

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

文件夹名称(如“模糊文件夹名称”)通常基于应用程序清单签名密钥。如果您在EXEPath中检索到正确的文件夹名称,它将通过arg并正常工作。

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

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());   
}   
}   
}   
}  
上面的代码启动了应用程序的一个新实例,这是显而易见的。预计这将是一个切入点,但事实并非如此

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)
args字符串数组

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

因此,该过程是:使用参数执行EXE-->参数通过字符串[]传递到“Main”方法具有新进程ID-->的新进程中的args在具有新进程ID-->的新进程中的类变量中设置args具有新进程ID-->的新进程启动并检查应用程序的已存在实例-->如果存在已“提前”的现有实例(这就是我丢失的地方,我已经将参数传递给了现有实例)并且具有新进程ID的新进程退出

但是,我仍然不理解在没有任何流程特定代码的情况下,参数是如何从一个实例传递到另一个实例的

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();
MainForm.AppArgs 

实际上位于另一个具有不同进程ID的进程中。以某种方式它仍然可以被访问?或者该进程在此点上以某种方式被实例化?

是的,我有代码自动执行此工作,我已验证这不是问题所在。请参阅上面的编辑。