C#获取尚未运行的Process Object的完整路径

时间:2015-04-10 15:05:23

标签: c# .net

我目前正在努力完成以下任务:

对于我们提供给客户的SDK,我们希望SDK开发人员能够提供外部应用程序调用,以便他们可以插入其他按钮。这些按钮将启动外部应用程序或使用默认应用程序打开文件(例如Word for * .docx)。

不同按钮之间应该存在一些视觉区别,因此我们的方法是显示要调用的应用程序的图标。

现在,有三种不同的呼叫: (下面的字符串将始终是ProcessStartInfo.FileName的值)

  1. 调用提供完整申请路径的应用程序,可能包含environement vars(例如"C:\Program Files\Internet Explorer\iexplore.exe" / "%ProgramFiles%\Internet Explorer\iexplore.exe"
  2. 调用只提供可执行文件名的应用程序,因为应用程序可以在PATH变量中找到(例如"iexplore"
  3. 打开文档,但未提供打开它的应用程序(例如"D:\test.html"
  4. 我们正在寻找一种方法,为任何给定的电话找到合适的图标。为此,我们必须找到应用程序的完整应用程序路径,它将以上述三种方式中的任何一种方式执行,但之前我们实际上已经启动了流程


    有没有办法找到System.Diagnostics.Process或System.Diagnostics.ProcessStartInfo对象的完整路径或图标,流程开始之前?

    重要提示:我们必须才能启动此过程(可能有副作用)

    示例代码:

    var process = new Process
    {
        StartInfo =
        {
            //applicationPath could be any of the stated above calls
            FileName = Environment.ExpandEnvironmentVariables(applicationPath)
        }
    };
    //we have to find the full path here, but MainModule is null as long as the process object has not yet started
    var icon = Icon.ExtractAssociatedIcon(process.MainModule.FullPath) 
    

    解决方案 多亏你们,我找到了解决方案。链接here at CodeProject的项目为我的确切问题提供了解决方案,该解决方案与程序和文件同样有效,并且可以在开始流程之前提供图标。感谢@wgraham的链接

3 个答案:

答案 0 :(得分:0)

Process类可以完全按照您的意愿执行。 环境变量如%ProgramFiles%需要首先使用Environment.ExpandEnvironmentVariables(string)进行扩展。


1

using System.IO;
using System.Diagnostics;

string iexplore = @"C:\Program Files\Internet Explorer\iexplore.exe");

string iexploreWithEnvVars = Environment.ExpandEnvironmentVariables(@"%ProgramFiles%\Internet Explorer\iexplore.exe");

2

public static string FindFileInPath(string name)
{
    foreach (string path in Environment.ExpandEnvironmentVariables("%path%").Split(';'))
    {
        string filename;
        if (File.Exists(filename = Path.Combine(path, name)))
        {
            return filename; // returns the absolute path if the file exists
        }
    }
    return null; // will return null if it didn't find anything
}

3

Process.Start("D:\\test.html");

您希望将代码放入try-catch块中,因为如果文件不存在,Process.Start将抛出异常。

编辑:更新了代码,感谢Dan Field指出我错过了问题的含义。 :/

答案 1 :(得分:0)

前两个例子不应该太难以理解使用Environment.ExpandEnvironmentVariables。你的最后一个是更难的 - 最好的选择似乎是使用PInvoke来调用AssocCreate。改编自pinvoke页面(http://www.pinvoke.net/default.aspx/shlwapi/AssocCreate.html):

public static class GetDefaultProgramHelper
{
    public unsafe static string GetDefaultProgram(string ext)
    {
        try
        {
           object obj;
           AssocCreate(
             ref CLSID_QueryAssociations,
             ref IID_IQueryAssociations,
             out obj);
           IQueryAssociations qa = (IQueryAssociations)obj;
           qa.Init(
             ASSOCF.INIT_DEFAULTTOSTAR,
             ext, //".doc",
             UIntPtr.Zero, IntPtr.Zero);

           int size = 0;
           qa.GetString(ASSOCF.NOTRUNCATE, ASSOCSTR.COMMAND,
             "open", null, ref size);

           StringBuilder sb = new StringBuilder(size);
           qa.GetString(ASSOCF.NOTRUNCATE, ASSOCSTR.COMMAND,
             "open", sb, ref size);

           //Console.WriteLine(".doc is opened by : {0}", sb.ToString());
           return sb.ToString();
        }
        catch(Exception e)
        {
           if((uint)Marshal.GetHRForException(e) == 0x80070483)
             //Console.WriteLine("No command line is associated to .doc open verb.");
             return null;
           else
             throw;
        }
    }

    [DllImport("shlwapi.dll")]
    extern static int AssocCreate(
       ref Guid clsid,
       ref Guid riid,
       [MarshalAs(UnmanagedType.Interface)] out object ppv);

    [Flags]
    enum ASSOCF
    {
       INIT_NOREMAPCLSID = 0x00000001,
       INIT_BYEXENAME = 0x00000002,
       OPEN_BYEXENAME = 0x00000002,
       INIT_DEFAULTTOSTAR = 0x00000004,
       INIT_DEFAULTTOFOLDER = 0x00000008,
       NOUSERSETTINGS = 0x00000010,
       NOTRUNCATE = 0x00000020,
       VERIFY = 0x00000040,
       REMAPRUNDLL = 0x00000080,
       NOFIXUPS = 0x00000100,
       IGNOREBASECLASS = 0x00000200,
       INIT_IGNOREUNKNOWN = 0x00000400
    }

    enum ASSOCSTR
    {
       COMMAND = 1,
       EXECUTABLE,
       FRIENDLYDOCNAME,
       FRIENDLYAPPNAME,
       NOOPEN,
       SHELLNEWVALUE,
       DDECOMMAND,
       DDEIFEXEC,
       DDEAPPLICATION,
       DDETOPIC,
       INFOTIP,
       QUICKTIP,
       TILEINFO,
       CONTENTTYPE,
       DEFAULTICON,
       SHELLEXTENSION
    }

    enum ASSOCKEY
    {
       SHELLEXECCLASS = 1,
       APP,
       CLASS,
       BASECLASS
    }

    enum ASSOCDATA
    {
       MSIDESCRIPTOR = 1,
       NOACTIVATEHANDLER,
       QUERYCLASSSTORE,
       HASPERUSERASSOC,
       EDITFLAGS,
       VALUE
    }

    [Guid("c46ca590-3c3f-11d2-bee6-0000f805ca57"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IQueryAssociations
    {
       void Init(
         [In] ASSOCF flags,
         [In, MarshalAs(UnmanagedType.LPWStr)] string pszAssoc,
         [In] UIntPtr hkProgid,
         [In] IntPtr hwnd);

       void GetString(
         [In] ASSOCF flags,
         [In] ASSOCSTR str,
         [In, MarshalAs(UnmanagedType.LPWStr)] string pwszExtra,
         [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszOut,
         [In, Out] ref int pcchOut);

       void GetKey(
         [In] ASSOCF flags,
         [In] ASSOCKEY str,
         [In, MarshalAs(UnmanagedType.LPWStr)] string pwszExtra,
         [Out] out UIntPtr phkeyOut);

       void GetData(
         [In] ASSOCF flags,
         [In] ASSOCDATA data,
         [In, MarshalAs(UnmanagedType.LPWStr)] string pwszExtra,
         [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] out byte[] pvOut,
         [In, Out] ref int pcbOut);

       void GetEnum(); // not used actually
    }

    static Guid CLSID_QueryAssociations = new Guid("a07034fd-6caa-4954-ac3f-97a27216f98a");
    static Guid IID_IQueryAssociations = new Guid("c46ca590-3c3f-11d2-bee6-0000f805ca57");

}

您可以使用string filePathToProgram = GetDefaultProgramHelper.GetDefaultProgram(".docx");

来调用此方法

答案 2 :(得分:0)

如果您希望自己的用户界面与用户计算机的其他部分在视觉上保持一致,则可能需要extract the icon from the file使用Icon.ExtractAssociatedIcon(string path)。这适用于WinForms / GDI世界。或者,this question解决了如何使用P / Invoke完成它。