We've got a winforms LOB application, which under normal circumstances should be started from a launcher that should do basic version checks and download any updated components, before spawning the main process.
我们有一个winforms LOB应用程序,在正常情况下应该从一个启动程序开始,该启动程序应该在生成主进程之前进行基本的版本检查并下载任何更新的组件。
One problem we're seeing is that some members of staff have found it loads faster by not running the update application, however this can lead to people not having the latest features and causes all manner of headache to support.
我们看到的一个问题是,一些工作人员发现,如果不运行更新应用程序,它的加载速度会更快,但这可能导致人们没有最新的特性,并导致各种令人头痛的问题。
What I'd like to be able to do is to throw up a warning if they haven't gone in through the initialise application. Ideally, I'd like to be able to do this without having to change the update application (as that means going and installing a new MSI on each client), and the approach that springs out is to find some way of finding information about the process that started "me" and check against a white/black list, forever I can't seem to find a way to do this?
我希望能够做的是,如果他们没有通过initialise应用程序,那么就抛出一个警告。理想情况下,我想能够这样做,而不必更改更新应用程序(也就是说,在每个客户端上安装一个新的MSI),和弹簧的方法是找到某种方式找到的信息的过程,“我”开始,检查一个白色/黑名单,永远我似乎无法找到一个方法来做呢?
Aside: Of course, if I did resort to changing the update application, I'd probably change it to either pass a pre-shared secret as a command line argument, or better still, change the application such that I could just load it as a class library and instantiate the relevant class via reflection. ClickOnce has been ruled out as it does not support being installed for multiple users
旁白:当然,如果我采取改变更新应用程序中,我可能会改变它,要么通过pre-shared秘密作为命令行参数,或者更好的是,改变应用程序的,这样我可以负载作为类库和实例化类通过反射有关。ClickOnce已经被排除,因为它不支持为多个用户安装。
4 个解决方案
#1
4
See here: How to get parent process in .NET in managed way
参见这里:如何以托管方式在.NET中获取父进程
From the link:
从链接:
using System.Diagnostics;
PerformanceCounter pc = new PerformanceCounter("Process",
"Creating Process ID", Process.GetCurrentProcess().ProcessName);
return Process.GetProcessById((int)pc.NextValue());
[Edit: Also see the System.Diagnostics FAQ for some more information about this. Thanks to Justin for the link.]
[编辑:也可以查看系统。诊断常见问题解答更多有关这方面的信息。感谢贾斯汀的链接。
#2
3
I find if your process - which I assume you have control over - checks its version number vs the latest released version number (placed somewhere central db/ftp wherever u look for the update) , then you have all that logic in one place. I think that would be a simpler solution.
我发现,如果您的进程(我假设您拥有控制权)检查它的版本号与最新发布的版本号(放置在*db/ftp的某个位置,无论您在哪里查找更新),那么您将在一个地方拥有所有这些逻辑。我认为这是一个更简单的解决方案。
#3
0
First, if your staff has people smart enough to figure out that the launcher is slow and how to get around it, I bet they will find out some 'secret' command line switch, too. I would consider that approach a waste of time.
首先,如果你的团队有足够聪明的人来发现启动器太慢以及如何绕过它,我敢打赌他们也会发现一些“秘密”的命令行切换。我认为这种做法是浪费时间。
Second, I think the answer form Chris Marasti-Georg goes into the rigth direction: You have to figure out the name of the parent process, i.e. the process that launched your app. I have no specific idea on how to do this, but WMI seems like a good place to start. Edit: Simon P Stevens answered that part.
第二,我认为Chris marastig - georg的答案会进入严格的方向:你必须找出父进程的名称,也就是启动应用程序的过程。编辑:西蒙·P·史蒂文斯回答了这个问题。
Third, I suppose you are aware of this, but I will say it anyway: Your problem is the launcher. If it is so slow that normal users find a way to get around it, it is just too slow. Your best solution is not ti fix the main app, but to fix the launcher. Edit: See Anders Karlsson's answer for a better mechanism.
第三,我想你知道这一点,但我还是要说:你的问题是发射器。如果它是如此缓慢,以至于普通用户找到了绕过它的方法,那它就是太慢了。你最好的解决方案不是修复主应用程序,而是修复启动程序。编辑:请参阅安德斯·卡尔松的答案,以获得更好的机制。
#4
0
You can use PInvoke with a Kernel32 method to find the parent process and check to see if it matches your updater. Source. Code, in case it goes away:
您可以使用带有Kernel32方法的PInvoke查找父进程,并检查它是否与您的更新程序匹配。源。代码,以防它消失:
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);
}
}
#1
4
See here: How to get parent process in .NET in managed way
参见这里:如何以托管方式在.NET中获取父进程
From the link:
从链接:
using System.Diagnostics;
PerformanceCounter pc = new PerformanceCounter("Process",
"Creating Process ID", Process.GetCurrentProcess().ProcessName);
return Process.GetProcessById((int)pc.NextValue());
[Edit: Also see the System.Diagnostics FAQ for some more information about this. Thanks to Justin for the link.]
[编辑:也可以查看系统。诊断常见问题解答更多有关这方面的信息。感谢贾斯汀的链接。
#2
3
I find if your process - which I assume you have control over - checks its version number vs the latest released version number (placed somewhere central db/ftp wherever u look for the update) , then you have all that logic in one place. I think that would be a simpler solution.
我发现,如果您的进程(我假设您拥有控制权)检查它的版本号与最新发布的版本号(放置在*db/ftp的某个位置,无论您在哪里查找更新),那么您将在一个地方拥有所有这些逻辑。我认为这是一个更简单的解决方案。
#3
0
First, if your staff has people smart enough to figure out that the launcher is slow and how to get around it, I bet they will find out some 'secret' command line switch, too. I would consider that approach a waste of time.
首先,如果你的团队有足够聪明的人来发现启动器太慢以及如何绕过它,我敢打赌他们也会发现一些“秘密”的命令行切换。我认为这种做法是浪费时间。
Second, I think the answer form Chris Marasti-Georg goes into the rigth direction: You have to figure out the name of the parent process, i.e. the process that launched your app. I have no specific idea on how to do this, but WMI seems like a good place to start. Edit: Simon P Stevens answered that part.
第二,我认为Chris marastig - georg的答案会进入严格的方向:你必须找出父进程的名称,也就是启动应用程序的过程。编辑:西蒙·P·史蒂文斯回答了这个问题。
Third, I suppose you are aware of this, but I will say it anyway: Your problem is the launcher. If it is so slow that normal users find a way to get around it, it is just too slow. Your best solution is not ti fix the main app, but to fix the launcher. Edit: See Anders Karlsson's answer for a better mechanism.
第三,我想你知道这一点,但我还是要说:你的问题是发射器。如果它是如此缓慢,以至于普通用户找到了绕过它的方法,那它就是太慢了。你最好的解决方案不是修复主应用程序,而是修复启动程序。编辑:请参阅安德斯·卡尔松的答案,以获得更好的机制。
#4
0
You can use PInvoke with a Kernel32 method to find the parent process and check to see if it matches your updater. Source. Code, in case it goes away:
您可以使用带有Kernel32方法的PInvoke查找父进程,并检查它是否与您的更新程序匹配。源。代码,以防它消失:
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);
}
}