Process.Start() 在自己的进程上返回 null

发布于 2024-09-27 13:08:05 字数 1286 浏览 3 评论 0原文

我正在使用 Process.Start() 来初始化当前正在运行的应用程序的提升副本。不幸的是 Process.Start() 返回 null,因为它认为它正在使用我的应用程序的现有进程,并且虽然存在现有进程,但它没有指定处理此类入口点的任何方法。

.NET 中是否有任何方法(通过配置或其他方式)可以告诉系统不要重用我的流程的现有副本?此问题似乎仅发生在 Windows XP 上,而不是 Vista 或 7。

代码副本如下:

internal static bool EnsureAssociation()
{
    // Check to make sure RoketPack is associated.
    if (!Protocol.IsAssociated())
    {
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = UNC.UniversalApplicationPath;
        info.UseShellExecute = true;
        if (!UAC.IsAdmin())
            info.Verb = "runas"; // Provides Run as Administrator
        info.Arguments = "--associate";
        Process proc = null;
        try
        {
            proc = Process.Start(info);
        }
        catch (Win32Exception)
        {
            Errors.Raise(Errors.ErrorType.ERROR_CAN_NOT_ASSOCIATE_PROTOCOL);
            return false;
        }

        if (null != proc)
        {
            // Wait until the association is complete.
            proc.WaitForExit();
            return Protocol.IsAssociated();
        }
        else
        {
            Errors.Raise(Errors.ErrorType.ERROR_CAN_NOT_ASSOCIATE_PROTOCOL);
            return false;
        }
    }
    else
        return true;
}

I'm using Process.Start() to initialize an elevated copy of the currently running application. Unfortunately Process.Start() returns null because it thinks it's using an existing process of my application, and while there is an existing process, it doesn't specify any way of handling this kind of entry point.

Is there any way in .NET (via configuration or otherwise) that I can tell the system not to reuse existing copies of my process? This issue only seems to occur on Windows XP, and not Vista or 7.

A copy of the code is below:

internal static bool EnsureAssociation()
{
    // Check to make sure RoketPack is associated.
    if (!Protocol.IsAssociated())
    {
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = UNC.UniversalApplicationPath;
        info.UseShellExecute = true;
        if (!UAC.IsAdmin())
            info.Verb = "runas"; // Provides Run as Administrator
        info.Arguments = "--associate";
        Process proc = null;
        try
        {
            proc = Process.Start(info);
        }
        catch (Win32Exception)
        {
            Errors.Raise(Errors.ErrorType.ERROR_CAN_NOT_ASSOCIATE_PROTOCOL);
            return false;
        }

        if (null != proc)
        {
            // Wait until the association is complete.
            proc.WaitForExit();
            return Protocol.IsAssociated();
        }
        else
        {
            Errors.Raise(Errors.ErrorType.ERROR_CAN_NOT_ASSOCIATE_PROTOCOL);
            return false;
        }
    }
    else
        return true;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谜兔 2024-10-04 13:08:06

我通过检查 UAC.IsAdmin() 是否为真解决了这个问题,如果是,则只需执行提升的进程将执行的操作即可。

这并不能直接解决 Process.Start() 返回 null 的问题,但我认为造成重用的情况是因为本来要启动的进程在各个方面都是相同的(就好像进程启动时提升了通过“runas”动词,它被认为是不同的并且不会返回 null)。

I solved this by checking to see if UAC.IsAdmin() is true, and if it is, simply perform the actions that the elevated process would have performed.

This doesn't directly solve the issue of Process.Start() returning null, but I think that the re-use situation is caused because the process that would have been started is identical in every way (where as if the process is started elevated via the 'runas' verb, it's considered different and will not return null).

电影里的梦 2024-10-04 13:08:06

您想要做的是默认行为,即任何程序都可以运行多个实例。防止应用程序运行多次需要额外的代码。

查看 ReflectorProcess.Start()

public static Process Start(ProcessStartInfo startInfo)
{
    Process process = new Process();
    if (startInfo == null)
    {
        throw new ArgumentNullException("startInfo");
    }
    process.StartInfo = startInfo;
    if (process.Start())
    {
        return process;
    }
    return null;
}

您可以跟踪返回 null 的位置。如果进程无法在 process.Start() 内启动,它将返回 null

public bool Start()
{
    this.Close();
    ProcessStartInfo startInfo = this.StartInfo;
    if (startInfo.FileName.Length == 0)
    {
        throw new InvalidOperationException(SR.GetString("FileNameMissing"));
    }
    if (startInfo.UseShellExecute)
    {
        return this.StartWithShellExecuteEx(startInfo);
    }
    return this.StartWithCreateProcess(startInfo);
}

...

你明白了。继续追踪为什么您会得到 null 值。如果您还没有 Reflector 的副本,立即获取!

注意:很抱歉,这并没有为您的问题提供准确解决方案,但它表明您可以自己找到它。 :)

哈,

What you want to do is the default behaviour, i.e., any program can run multiple instances. Preventing the application from running more than once would require additional code.

Looking in Reflector at Process.Start()

public static Process Start(ProcessStartInfo startInfo)
{
    Process process = new Process();
    if (startInfo == null)
    {
        throw new ArgumentNullException("startInfo");
    }
    process.StartInfo = startInfo;
    if (process.Start())
    {
        return process;
    }
    return null;
}

You can trace where is returning null. It will return null if the process fails to start inside of process.Start().

public bool Start()
{
    this.Close();
    ProcessStartInfo startInfo = this.StartInfo;
    if (startInfo.FileName.Length == 0)
    {
        throw new InvalidOperationException(SR.GetString("FileNameMissing"));
    }
    if (startInfo.UseShellExecute)
    {
        return this.StartWithShellExecuteEx(startInfo);
    }
    return this.StartWithCreateProcess(startInfo);
}

...

You get the idea. Continue to trace why you are getting a null value. If you haven't got a copy of Reflector, GET IT NOW!

NB: Apologies that this does not give you the exact solution to your problem, however it shows you can go about finding it yourself. :)

HTH,

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文