我想知道是否有人可以提供关于Windows Shell如何传递的链接或解释,例如,默认应用程序,Internet Explorer,Google Chrome或自定义构建应用程序的参数的URL。
我查看过例如:Run shell commands using c# and get the info into string
上述链接和其他类似链接的问题是它们无法正常工作或实际上没有回答实际问题。例如......
本准则的工作符合预期:
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
像这样处理args:
/// <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中然后像这样处理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...
}
}
}
}
我正在使用Click Once。我在上面的链接中设置了带有VB Single Instance代码的应用程序。此代码有效,只运行应用程序的单个实例。
我的问题:
如果我将参数传递给我的应用程序,测试显示进程ID与正在运行的实例的进程ID不同。这样就表明已经运行的Application实例不是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();
因此,即使代码已到位以将Application设置为单个实例应用程序,此代码也会启动一个新实例。运行的现有Application Instance不会处理传递的Args。
新实例将显示编码消息框(&#34;我已经运行...&#34;),但之后会退出。
修改 @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();
我可以验证完全相同的路径对于正在运行的实例以及对EXE路径的Shell调用是否有效。
编辑 - 11.08.14
我想稍微扩展一下这个问题。
当传递参数时,我一直到新进程ID中的参数处理,然后将实例切换回单实例应用程序的代码回到现有实例。现阶段,Args是没有传递给现有的实例。
如果我使用:
MessageBox.Show("Program ID: " + (Process.GetCurrentProcess().Id) + " Arg Passed: " + this.Args[0]);
它在新实例上运行,但不在现有实例上运行。
答案 0 :(得分:1)
为此,可执行路径必须匹配。如果要实例化ClickOnce,那么您的可执行文件路径无效,就像您在示例中所示:
private string EXEPath = @"C:\Program Files (x86)\My App\My App.exe"; // Or actual path to EXE.
ClickOnce应用会下载到用户的个人资料应用数据位置。这就是执行exe的地方。根据Windows版本,可能是(see this post):
Win7的
"c:\users\username\AppData\Local\Apps\2.0\obfuscatedfoldername\obfuscatedfoldername"
或XP:
"C:\Documents and Settings\username\LocalSettings\Apps\2.0\obfuscatedfoldername\obfuscatedfoldername"
文件夹名称(如“obfuscatedfoldername”中)通常基于应用程序清单签名密钥。如果在EXEPath中检索正确的文件夹名称,它应该传递arg并正常工作。
答案 1 :(得分:1)
最后一个解决方案。解决方案来自反复试验。我用来配置单个实例应用程序的代码是问题,或者我应该说我理解这个代码是如何编写和工作的。这是代码,因为它是在上面的链接上写的。
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;
因此,为了解决问题,我在此事件处理程序中添加了一些代码来处理Passed Arguments:
MainForm.AppArgs = new string[] { "Arg 1", "Arg 2" };
此测试有效,我已调整此代码以接受以下参数:
static void Main(string[] args)
args字符串数组。
所以所有人都应该按照我的预期工作,在我的项目中添加第三方代码在方程式中抛出一个曲线球,并且需要进行一些测试以找出所需的实际过程,以便将正确的数据传递到正确的部分。在适当的时候申请。
所以过程是:EXE是用参数执行的 - &gt;参数通过带有新进程ID的新进程中的string [] args传递到“Main”方法 - &gt; args在新流程中的类变量中设置,具有新的流程ID - &gt;启动具有新进程ID的新进程并检查已存在的应用程序实例 - &gt;如果有一个现有的实例,它就会被“提前”(这是我丢失的地方,并且我将我的args传递给现有的实例),并且退出了具有新进程ID的新进程。
但是,我仍然不明白在没有任何特定于流程的代码的情况下,参数如何从一个实例传递到另一个实例?作为代码:MainForm.AppArgs
实际上是在具有不同进程ID的另一个进程中。不知怎的,仍然可以访问它?或者也许过程在某种程度上被实例化了?