我们有一个winforms LOB应用程序,在正常情况下应该从应该执行基本版本检查并下载任何更新组件的启动程序启动,然后才会生成主进程。
我们看到的一个问题是,一些员工发现,如果没有运行更新应用程序,加载速度会更快,但这可能会导致人们没有最新的功能并导致各种令人头疼的问题。
我希望能够做的是,如果他们没有通过初始化应用程序,则会发出警告。理想情况下,我希望能够在不必更改更新应用程序的情况下执行此操作(因为这意味着在每个客户端上安装新的MSI),并且出现的方法是找到一些方法来查找有关开始“我”并检查白/黑名单的过程,我似乎无法找到办法做到这一点?
除了:当然,如果我确实想要更改更新应用程序,我可能会将其更改为将预共享密钥作为命令行参数传递,或者更好的是,更改应用程序使我可以将其作为类库加载并通过反射实例化相关的类。 ClickOnce已被排除为does not support being installed for multiple users
答案 0 :(得分:4)
见这里:How to get parent process in .NET in managed way
从链接:
using System.Diagnostics;
PerformanceCounter pc = new PerformanceCounter("Process",
"Creating Process ID", Process.GetCurrentProcess().ProcessName);
return Process.GetProcessById((int)pc.NextValue());
[编辑:另请参阅System.Diagnostics FAQ以获取有关此内容的更多信息。感谢Justin的链接。]
答案 1 :(得分:3)
我发现你的进程 - 我认为你可以控制 - 检查它的版本号与最新发布的版本号(放在中央db / ftp的某处,无论你在哪里寻找更新),然后你就拥有了所有的逻辑地点。我认为这将是一个更简单的解决方案。
答案 2 :(得分:0)
您可以将PInvoke与Kernel32方法一起使用来查找父进程并检查它是否与您的更新程序匹配。 Source.代码,以防它消失:
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 :(得分:0)
首先,如果你的员工有足够聪明的人发现发射器很慢以及如何绕过它,我敢打赌他们也会发现一些'秘密'命令行开关。我认为这种方法浪费时间。
其次,我认为answer form Chris Marasti-Georg进入了严格的方向:您必须弄清楚父进程的名称,即启动应用程序的进程。我对如何做到这一点没有具体的想法,但WMI似乎是一个好的起点。 修改: Simon P Stevens回答了这一部分。
第三,我想你已经意识到这一点,但无论如何我会说:你的问题是发射器。如果它太慢以至于普通用户找不到绕过它的方法,那就太慢了。您最好的解决方案不是修复主应用程序,而是修复启动器。 修改:有关更好的机制,请参阅Anders Karlsson's answer。