تنفيذ برنامج آخر من C#، هل أحتاج إلى تحليل "سطر الأوامر" من التسجيل بنفسي؟

StackOverflow https://stackoverflow.com/questions/1560356

  •  21-09-2019
  •  | 
  •  

سؤال

من السجل ، لنوع ملف معين ، أحصل على سلسلة تحتوي على شيء مثل هذا:

"C:\Program Files\AppName\Executable.exe" /arg1 /arg2 /arg3

أو في بعض الأحيان:

"C:\Program Files\AppName\Executable.exe" /arg1 /arg2 /arg3 "%1"

لكي أقوم بتنفيذ هذا البرنامج ، وتمرير اسم ملف كمعلمة (التي أعرفها) ، هل يجب علي تحليل هذه السلسلة بنفسي ، أم أن هناك فئة وقت تشغيل سيفعل ذلك من أجلي؟ لاحظ أنني لا أسأل عن التعامل مع الفرق بين الاثنين فيما يتعلق بما إذا كان لديه "٪ 1" أم لا ، ولكن بدلاً من ذلك ، أحتاج إلى تقسيم اسم وسيطات سطر الأوامر إليها بشكل منفصل.

لقد حاولت فقط إلحاق/ضخ المسار الكامل للملف واسمه للتمرير إلى السلسلة أعلاه وتمرير الشبانج بأكمله للمعالجة. الشغل.

في الأساس ، يجب القيام بما سبق مثل هذا يدويًا:

Process proc = new Process();
proc.StartInfo.FileName = @"C:\Program Files\AppName\Executable.exe";
proc.StartInfo.Arguments = "/arg1 /arg2 /arg3 \"" + fileName + "\"";
proc.Start();

حاولت استخدام Useshellexecute, ، لكن هذا لم يساعد. أي مؤشرات أخرى؟

أن أكون واضحا ، أريد هذا:

String commandPath = ReadFromRegistry();
String fullCommand = commandPath + " " + fileName; // assuming not %1
Process.Start(fullCommand); // <-- magic happens here
هل كانت مفيدة؟

المحلول

المشكلة التي تواجهها هي أن الاسم القابل للتنفيذ وبعض الوسائط موجودة بالفعل في متغيرك commandPath (وهو ليس فقط المسار ، ولكن أيضًا بعض المعاملات). إذا كان الجزء الأول يتكون من شخصيات فقط (لا توجد مسافات) ، فلن يكون من الصعب للغاية فصل القابل للتنفيذ عن المعلمات ، ولكن هذه هي النوافذ ، لذلك قد يكون لديك مسافات ، لذلك أنت عالق. هكذا يبدو.

الحل في ليس استخدام Process.Start, ، و ليس استخدام ShellExecute. Process.Start, ، سواء طلبت استخدامها ShellExecute أو CreateProcess, ، في كلتا الحالتين ، يتطلب FileName المعلمة/العضو المراد تعيينه ، والذي يتم تمريره كما هو إلى المعالجة المخلقة و shellexecute.

فما ثم؟ بدلاً من ذلك ، استخدم: استخدم CreateProcess نفسك. تتمثل الميزة الأقل شهرة في وظيفة API هذه في أنه يمكنك تمرير سطر أوامر كامل إليها ، تمامًا كما يمكنك تحت Winkey+R (Windows Run). ال "سحر" يمكن تحقيق ذلك عن طريق تحديد أول معلمة لها null والمعلمة الثانية إلى المسار الكامل ، بما في ذلك جميع المعلمات. مثل ما يلي ، والذي سيبدأ معرض صور Windows بالنسبة لك ، أثناء استخدام نفس السلسلة مع params مع Process.Start أي طريقة من شأنها أن تسفر "لم يتم العثور على الملف" خطأ:

STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
CreateProcess(
    /* app name     */ null,
    /* cmd line     */ @"C:\Program Files\Windows Photo Gallery\WindowsPhotoGallery.exe testBogusParam", 
    /* proc atts    */ IntPtr.Zero, 
    /* thread atts  */ IntPtr.Zero, 
    /* inh handles  */ false,
    /* create flags */ 0, 
    /* env ptr      */ IntPtr.Zero, 
    /* current dir  */ null, 
    /* startupinfo  */ ref si, 
    /* processinfo  */ out pi);

لاحظ أنني لم أتضمن عن عمد عروض أسعار حول المسار القابل للتنفيذ. ولكن إذا كان المسار القابل للتنفيذ لديه اقتباسات حوله ، كما هو الحال مع الكود أعلاه ، فسيظل يعمل ، كل سحر هل هناك. ادمج ذلك مع مقتطف الرمز الخاص بك ، سيبدأ ما يلي العملية بالطريقة التي تريدها:

/* with your code */
String commandPath = ReadFromRegistry();
String fullCommand = commandPath + " " + fileName; // assuming not %1
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
CreateProcess(
    null,
    fullCommand, 
    IntPtr.Zero, 
    IntPtr.Zero, 
    false,
    0, 
    IntPtr.Zero, 
    null, 
    ref si, 
    out pi);

الإعلانات شيء يمكنك الحصول عليه http://www.pinvoke.net, ، ولكن للراحة ، إليك الجزء الذي يجب لصقه داخل قسم الفصل للحصول على ما سبق للعمل. مرجع هذه الوظائف ، كيفية التحقق من النتيجة (النجاح / الفشل) و STARTUPINFO و PROCESS_INFORMATION يمكن العثور على الهياكل في MSDN من Microsoft هنا. للراحة ، أوصي بطلب المكالمة CreateProcess في وظيفة الأداة المساعدة.

/* place the following at the class level */
[DllImport("kernel32.dll")]
static extern bool CreateProcess(
    string lpApplicationName, 
    string lpCommandLine, 
    IntPtr lpProcessAttributes, 
    IntPtr lpThreadAttributes,
    bool bInheritHandles, 
    uint dwCreationFlags, 
    IntPtr lpEnvironment,
    string lpCurrentDirectory, 
    ref STARTUPINFO lpStartupInfo,
    out PROCESS_INFORMATION lpProcessInformation);

public struct PROCESS_INFORMATION
{
    public IntPtr hProcess;
    public IntPtr hThread;
    public uint dwProcessId;
    public uint dwThreadId;
}



public struct STARTUPINFO
{
    public uint cb;
    public string lpReserved;
    public string lpDesktop;
    public string lpTitle;
    public uint dwX;
    public uint dwY;
    public uint dwXSize;
    public uint dwYSize;
    public uint dwXCountChars;
    public uint dwYCountChars;
    public uint dwFillAttribute;
    public uint dwFlags;
    public short wShowWindow;
    public short cbReserved2;
    public IntPtr lpReserved2;
    public IntPtr hStdInput;
    public IntPtr hStdOutput;
    public IntPtr hStdError;
}

آمل أن أفهم مشكلتك بشكل صحيح. اسمحوا لي أن أعرف إذا كنت تواجه مشكلة في تنفيذ الكود أعلاه.

نصائح أخرى

أعتقد (لقد مر بعض الوقت منذ أن فعلت هذا) يمكنك استخدامه فقط:

System.Diagnostics.Process.Start(/*File to open*/);

وسوف يفتح الملف مع التطبيق الافتراضي إذا كان هناك واحد. لم تكن بحاجة إلى معرفة التطبيق الذي سيستخدمه.

هل أفهم ما تبحث عنه؟ أو هل فاتني شيء؟

ماذا عن التفريخ cmd.exe /c "سلسلة الخاص بك"

أي - شيء مثل

Process proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = @"/C ""C:\Program Files\AppName\Executable.exe"" /arg1 /arg2 /arg3 """ + fileName + """";
proc.Start();

واجهت مشكلة مماثلة (تحليل إلغاء التثبيت من السجل لتنفيذه باستخدام System.Diagnostics.process). لقد حلتها بواسطة إزالة الرموز من نهاية سلسلة إلغاء التثبيت حتى أتمكن من اكتشاف مسار ملف صالح.

    public static string GetExecutable(string command)
    {
        string executable = string.Empty;
        string[] tokens = command.Split(' ');

        for (int i = tokens.Length; i >= 0; i--)
        {
            executable = string.Join(" ", tokens, 0, i);
            if (File.Exists(executable))
                break;
        }
        return executable;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top