Как мне узнать, как начался мой процесс? - PullRequest
5 голосов
/ 14 июля 2009

У нас есть LOB-приложение winforms, которое при нормальных обстоятельствах должно запускаться из модуля запуска, который должен выполнять базовые проверки версий и загружать все обновленные компоненты, прежде чем запустить основной процесс.

Одна из проблем, с которой мы сталкиваемся, заключается в том, что некоторые сотрудники обнаружили, что она загружается быстрее, если не запускать приложение обновления, однако это может привести к тому, что люди не будут обладать новейшими функциями и станут причиной поддержки всех видов головной боли.

Что я хотел бы сделать, это выдать предупреждение, если они не прошли через инициализированное приложение. В идеале я хотел бы иметь возможность сделать это без необходимости изменять приложение обновления (поскольку это означает, что нужно установить и установить новый MSI на каждом клиенте), и в результате возникает подход к поиску информации о процесс, который запустил «я» и проверил белый / черный список, навсегда я не могу найти способ сделать это?


В сторону: Конечно, если бы я прибегнул к изменению приложения обновления, я, вероятно, изменил бы его, чтобы либо передать предварительно общий секретный ключ в качестве аргумента командной строки, либо, что еще лучше, изменить приложение, чтобы я мог просто загрузить его как библиотеку классов и создать экземпляр соответствующего класса с помощью отражения. ClickOnce был исключен, поскольку не поддерживает установку для нескольких пользователей

Ответы [ 4 ]

4 голосов
/ 14 июля 2009

См. Здесь: Как получить родительский процесс в .NET управляемым способом

Из ссылки:

using System.Diagnostics;
PerformanceCounter pc = new PerformanceCounter("Process",
"Creating Process ID", Process.GetCurrentProcess().ProcessName);
return Process.GetProcessById((int)pc.NextValue());

[Редактировать: также см. FAQ по системной диагностике для получения дополнительной информации об этом. Спасибо Джастину за ссылку.]

3 голосов
/ 14 июля 2009

Я нахожу, что если ваш процесс - который, как я полагаю, вы контролируете, - проверяет номер своей версии по сравнению с номером последней выпущенной версии (помещается где-то в центре db / ftp, где бы вы ни искали обновление), тогда у вас есть вся логика в одном место. Я думаю, что это было бы более простым решением.

0 голосов
/ 14 июля 2009

Во-первых, если в вашем штате есть люди, достаточно умные, чтобы понять, что лаунчер работает медленно и как его обойти, держу пари, они тоже найдут какой-нибудь «секретный» переключатель командной строки. Я бы посчитал такой подход пустой тратой времени.

Во-вторых, я думаю, что форма ответа Криса Марасти-Георга идет в правильном направлении: вам нужно определить имя родительского процесса, то есть процесса, который запустил ваше приложение. Я понятия не имею, как это сделать, но WMI кажется хорошим местом для начала. Редактировать: Саймон П Стивенс ответил на эту часть.

В-третьих, я полагаю, вы знаете об этом, но я все равно скажу: ваша проблема - это программа запуска. Если он настолько медленный, что обычные пользователи находят способ обойти его, он слишком медленный. Лучшее решение - не исправить основное приложение, а исправить лончер. Редактировать: См. Ответ Андерса Карлссона для улучшения механизма.

0 голосов
/ 14 июля 2009

Вы можете использовать PInvoke с методом Kernel32, чтобы найти родительский процесс и проверить, соответствует ли он вашему модулю обновления. Источник. Код, на случай, если он исчезнет:

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
static class myProcessEx
{  
    //inner enum used only internally
    [Flags]
    private enum SnapshotFlags : uint
    {
    HeapList = 0x00000001,
    Process = 0x00000002,
    Thread = 0x00000004,
    Module = 0x00000008,
    Module32 = 0x00000010,
    Inherit = 0x80000000,
    All = 0x0000001F
    }
    //inner struct used only internally
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct PROCESSENTRY32
    {
    const int MAX_PATH = 260;
    internal UInt32 dwSize;
    internal UInt32 cntUsage;
    internal UInt32 th32ProcessID;
    internal IntPtr th32DefaultHeapID;
    internal UInt32 th32ModuleID;
    internal UInt32 cntThreads;
    internal UInt32 th32ParentProcessID;
    internal Int32 pcPriClassBase;
    internal UInt32 dwFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
    internal string szExeFile;
    }

    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern IntPtr CreateToolhelp32Snapshot([In]UInt32 dwFlags, [In]UInt32 th32ProcessID);

    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern bool Process32First([In]IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern bool Process32Next([In]IntPtr hSnapshot, ref PROCESSENTRY32 lppe);

    // get the parent process given a pid
    public static Process GetParentProcess(int pid)
    {

    Process parentProc = null;
    try
    {
        PROCESSENTRY32 procEntry = new PROCESSENTRY32();
        procEntry.dwSize = (UInt32)Marshal.SizeOf(typeof(PROCESSENTRY32));
        IntPtr handleToSnapshot = CreateToolhelp32Snapshot((uint)SnapshotFlags.Process, 0);
        if (Process32First(handleToSnapshot, ref procEntry))
        {
        do
        {
            if (pid == procEntry.th32ProcessID)
            {
            parentProc = Process.GetProcessById((int)procEntry.th32ParentProcessID);
            break;

            }
        } while (Process32Next(handleToSnapshot, ref procEntry));
        }
        else
        {
        throw new ApplicationException(string.Format("Failed with win32 error code {0}", Marshal.GetLastWin32Error()));
        }
    }
    catch (Exception ex)
    {
        throw new ApplicationException("Can't get the process.", ex);
    }
    return parentProc;
    }

    // get the specific parent process
    public static Process CurrentParentProcess
    {
    get
    {
        return GetParentProcess(Process.GetCurrentProcess().Id);
    }
    }

    static void Main()
    {
    Process pr = CurrentParentProcess;

    Console.WriteLine("Parent Proc. ID: {0}, Parent Proc. name: {1}", pr.Id, pr.ProcessName);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...