简体   繁体   English

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

[英]C# get the full path of a not yet running Process Object

I'm currently trying to accomplish the following: 我目前正在尝试完成以下任务:

For an SDK, which we provide to our customers, we want the SDK-developers to be able to provide external application calls, so that they can insert additional buttons. 对于我们提供给客户的SDK,我们希望SDK开发人员能够提供外部应用程序调用,以便他们可以插入其他按钮。 These buttons than will start an external application or open a file with the default application for it (Word for *.docx for example). 然后,这些按钮将启动外部应用程序或使用默认应用程序打开文件(例如,Word表示* .docx)。

There should be some visual distinction between the different buttons, so our approach is to show the icon of the application to be called. 不同按钮之间应该在视觉上有所区别,因此我们的方法是显示要调用的应用程序的图标。

Now, there are three different kind of calls: (The strings below would always be the value of ProcessStartInfo.FileName) 现在,有三种不同类型的调用:(下面的字符串始终是ProcessStartInfo.FileName的值)

  1. Calling an application providing the full application path, possibly with environement vars (eg "C:\\Program Files\\Internet Explorer\\iexplore.exe" / "%ProgramFiles%\\Internet Explorer\\iexplore.exe" ) 调用提供完整应用程序路径(可能带有环境变量)的应用程序(例如"C:\\Program Files\\Internet Explorer\\iexplore.exe" / "%ProgramFiles%\\Internet Explorer\\iexplore.exe"
  2. Calling an application providing only the executable name, given the application can be found in the PATH Variable (eg "iexplore" ) 如果可以在PATH变量中找到给定应用程序的名称,则调用仅提供可执行文件名称的应用程序(例如"iexplore"
  3. Opening a document, without providing an application to open it (eg "D:\\test.html" ) 打开文档,但不提供打开它的应用程序(例如"D:\\test.html"

We are looking for a way, to find the appropriate Icon for any given call. 我们正在寻找一种方法,为任何给定的呼叫找到合适的图标。 For this we have to find the full application path of the application, which will be executed in any of the three ways above, but before we actually have started the Process 为此,我们必须找到应用程序完整应用程序路径 ,该路径将以上述三种方式中的任何一种执行,但是我们实际启动流程之前


Is there a way to find the full path or the icon of a System.Diagnostics.Process or System.Diagnostics.ProcessStartInfo object, before the process has been started? 在启动进程之前 ,是否可以找到System.Diagnostics.Process或System.Diagnostics.ProcessStartInfo对象的完整路径或图标?

Important: We must not start the process before (could have side effects) 重要提示:我们切勿在此之前开始该过程(可能会有副作用)

Example Code: 示例代码:

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) 

Solution Thanks to you guys I found my solution. 解决方案谢谢你们,我找到了我的解决方案。 The project linked here at CodeProject provides a solution for my exact problem, which works equally with programs and files and can provide the icon before starting the process. CodeProject此处链接的项目为我的确切问题提供了解决方案,该解决方案可与程序和文件同等使用,并且可以在开始过程之前提供图标。 Thanks for the link @wgraham 感谢您的链接@wgraham

The Process class can do exactly what you want. Process类可以完全满足您的要求。 Environment Variables like %ProgramFiles% need to be expanded first with Environment.ExpandEnvironmentVariables(string). 必须先使用Environment.ExpandEnvironmentVariables(string)扩展%ProgramFiles%之类的环境变量。


1. 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. 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. 3。

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

You want to put your code into try-catch blocks as well since Process.Start will throw an Exception if the file doesn't exist. 您还希望将代码放入try-catch块中,因为如果文件不存在,则Process.Start将引发Exception。

Edit: Updated the code, thanks to Dan Field for pointing out that I missed the meaning of the question. 编辑:更新了代码,感谢Dan Field指出我错过了问题的含义。 :/ :/

Your first two examples shouldn't be too hard to figure out using Environment.ExpandEnvironmentVariables . 前两个示例应该不难使用Environment.ExpandEnvironmentVariables Your last one is the tougher one - the best bet seems to be using PInvoke to call AssocCreate . 最后一个是更艰难的-最好的选择似乎是使用PInvoke调用AssocCreate Adapted from the pinvoke page ( http://www.pinvoke.net/default.aspx/shlwapi/AssocCreate.html ): 改编自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");

}

You could call this using string filePathToProgram = GetDefaultProgramHelper.GetDefaultProgram(".docx"); 您可以使用string filePathToProgram = GetDefaultProgramHelper.GetDefaultProgram(".docx");来调用它string filePathToProgram = GetDefaultProgramHelper.GetDefaultProgram(".docx");

If you want your UI to be visually-consistent with the rest of the user's machine, you may want to extract the icon from the file using Icon.ExtractAssociatedIcon(string path) . 如果希望您的UI与用户的其余计算机在视觉上保持一致,则可能需要使用Icon.ExtractAssociatedIcon(string path) 从文件中提取图标 This works under the WinForms/GDI world. 这适用于WinForms / GDI世界。 Alternatively, this question addresses how to complete it with P/Invoke. 或者, 此问题解决如何使用P / Invoke完成它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM