2009-07-14 23 views
5

Abbiamo un'applicazione LOB Winforms, che in circostanze normali dovrebbe essere avviata da un programma di avvio che dovrebbe eseguire controlli di versione di base e scaricare i componenti aggiornati, prima di generare il processo principale.Come scoprire come è stato avviato il processo

Un problema che stiamo riscontrando è che alcuni membri dello staff hanno riscontrato un caricamento più rapido non eseguendo l'applicazione di aggiornamento, tuttavia ciò può portare a persone che non dispongono delle funzionalità più recenti e che supportano tutti i tipi di mal di testa.

Quello che mi piacerebbe essere in grado di fare è di lanciare un avviso se non sono entrati attraverso l'applicazione di inizializzazione. Idealmente, mi piacerebbe poterlo fare senza dover cambiare l'applicazione di aggiornamento (questo significa andare e installare un nuovo MSI su ciascun client) e l'approccio che emerge è trovare un modo per trovare informazioni sul processo che ha iniziato "me" e check contro una lista bianca/nera, per sempre non riesco a trovare un modo per farlo?


parte: Certo, se mi ha fatto ricorso a cambiare l'applicazione di aggiornamento, probabilmente sarei cambiarlo a uno passare un segreto già condivisa come un argomento da riga di comando, o, meglio ancora, cambiare la applicazione tale che potrei semplicemente caricarla come una libreria di classi e istanziare la classe rilevante tramite la riflessione. ClickOnce è stato escluso come does not support being installed for multiple users

risposta

4

vedere qui: How to get parent process in .NET in managed way

Dal link:

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

[Edit: anche vedere il System.Diagnostics FAQ per qualche informazione in più su questo. Grazie a Justin per il collegamento.]

+1

Link a System.Diagnostics Domande frequenti http://msdn.microsoft.com/en-us/netframework/aa569609.aspx#Question3 – Justin

+0

Buon collegamento. Verrà modificato per includere. –

+0

Funziona perfettamente, anche se si tratta di chiudere il cancello dopo che il cavallo si è imbullonato ... –

0

È possibile utilizzare PInvoke con un metodo Kernel32 per trovare il processo padre e verificare se corrisponde al proprio programma di aggiornamento. Source. codice, nel caso in cui se ne va:

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); 
    } 
} 
3

Trovo se il processo - che suppone che si abbia il controllo su - controlla il suo numero di versione vs il numero dell'ultima versione rilasciata (posto db posto centrale/ftp ovunque u look per l'aggiornamento), quindi hai tutta quella logica in un unico posto. Penso che sarebbe una soluzione più semplice.

+0

Per la cronaca, abbiamo una schermata di diagnostica che lo staff di supporto può evidenziare i punti salienti con un brutto rossore se qualcosa è considerato obsoleto.Volevo catturare i colpevoli in anticipo :) –

0

Innanzitutto, se il tuo staff ha persone abbastanza intelligenti da capire che il programma di avvio è lento e su come aggirarlo, scommetto che scopriranno un interruttore di linea di comando "segreto", pure. Considero quell'approccio una perdita di tempo.

In secondo luogo, penso che il answer form Chris Marasti-Georg entri nella giusta direzione: devi capire il nome del processo genitore, cioè il processo che ha avviato la tua app. Non ho un'idea specifica su come farlo, ma WMI sembra un buon punto di partenza. Modifica:Simon P Stevens ha risposto a quella parte.

In terzo luogo, suppongo che tu ne sia a conoscenza, ma lo dirò comunque: il tuo problema è il programma di avvio. Se è così lento che i normali utenti trovano un modo per aggirarlo, è troppo lento. La soluzione migliore non è risolvere l'app principale, ma correggere il programma di avvio. Modifica: Vedere Anders Karlsson's answer per un meccanismo migliore.

+0

Il bit "troppo lento" è principalmente il risultato del pull degli aggiornamenti su una WAN. Questi aggiornamenti sono già distribuiti in posizioni geografiche convenienti e sono anche compressi con gzip. Per la cronaca, non mi piace l'approccio segreto preshared –

+0

Il modo in cui ho capito la tua domanda, ho pensato che il loader fosse * sempre * lento, non solo quando stava effettivamente eseguendo un aggiornamento. Sono corretto ;-) – Treb

Problemi correlati