我有一个C#/ .NET应用程序,其行为与svchost类似 - 我们使用它来启动我们的服务,每个服务都驻留在一个单独的DLL中。查看任务管理器时,所有这些都显示相同的名称 - 启动它们的可执行进程的名称。
我们希望将这些中的每一个都命名为唯一的。是否有API调用可以动态设置进程名称 - 即。到从配置文件中读取的字符串?
我已经阅读了其他类似的主题,但他们没有帮助。对问题#14711100的回答建议使用符号链接,响应是不起作用的。那个问题也是关于杀戮和开始,所以答案是针对这个问题的。
其他人提到设置窗口标题栏文本或可执行文件的进程名称。这些不适用于此处,因为没有窗口标题栏,并且使用相同的可执行文件来启动不同的进程。
问题#1402824似乎是最接近的。 Windows下是否有可用的libc实现?
如果无法做到这一点,那么有什么办法以某种方式伪造它吗?我们的主要目标是能够区分任务管理器和类似流程列表中的哪个流程。
如果我们甚至可以使用PID来获取完整的命令行,那可能会有所帮助。
作为最后的手段,如果我在启动之前设置某种将EXE复制到新名称的主管,我应该考虑哪些含义?我是否需要担心内存中重复的内容?内存中共享的东西?有人踩到任何人的数据,文件等?对问题#1402824的回答提到了相同的背景。我们需要了解什么?
感谢。
修改
我了解到我可以使用wmic工具获取流程信息:
wmic service where (pathname like "%%svchostOrWhatever.exe%%" and state="Running") get DisplayName,Name,PathName,ProcessId,StartMode
如果我们无法更改图像名称,这可能最终成为我们必须接受的。关于这一点,我确实找到了比利康纳的这个VB 6.0项目:
http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=66443&lngWId=1
我知道事情自2006年以来发生了很大变化,但我认为这值得一试。 (仅供我在Windows 7上使用。)
看起来它基本上使用SendMessage发送带有所需进程名称的LVM_SETITEMTEXT消息。我使用P / Invoke将调用转换为C#,但它似乎不起作用。
如果我正确理解了API,如果LVM_SETITEMTEXT成功,SendMessage将返回true(非零),如果失败则返回false(零),然后我可以像往常一样使用GetLastError的托管版本找到更多信息。
当我在svchost等效项中运行它时,SendMessage()返回零。我打电话给Marshal.GetLastWin32Error()并返回1400,看起来我得到的是ERROR_INVALID_WINDOW_HANDLE。好吧,也许我不能在Windows服务上运行它,因为它没有窗口。
然后,我在虚拟WPF应用程序中尝试了它。这次,我仍然从SendMessage()返回0,但GetLastWin32Error也返回零。
虚拟应用程序有一个App.xaml和一个MainWindow.xaml。我在后面的代码中的MainWindow构造函数的末尾放置了以下调用:
IntPtr handle = System.Diagnostics.Process.GetCurrentProcess().Handle;
SetItemText(handle, "Gobbledygook.exe", 0);
以下是从Connor的项目中采用和翻译的SetItemText的定义:
public static void SetItemText(IntPtr handle,
string desiredImageName,
long index,
long subIndex = 0)
{
// TODO: Check return values for errors...
desiredImageName = string.Format("{0}\0", desiredImageName); // TODO: Is the nul character required?
byte[] memStorage = System.Text.Encoding.ASCII.GetBytes(desiredImageName);
long size = memStorage.Length;
// allocate some shared memory for our string
IntPtr sharedProcMemString = VirtualAllocEx(handle,
IntPtr.Zero,
(uint)size,
AllocationType.Reserve | AllocationType.Commit,
MemoryProtection.ReadWrite);
// setup some info
LVITEM lvi = new LVITEM()
{
iItem = (int)index,
iSubItem = (int)subIndex,
cchTextMax = (int)size,
pszText = sharedProcMemString // store our string handle
};
// allocate some shared memory for our Struct
IntPtr sharedProcMem = VirtualAllocEx(handle,
IntPtr.Zero,
(uint)System.Runtime.InteropServices.Marshal.SizeOf(lvi),
AllocationType.Reserve | AllocationType.Commit,
MemoryProtection.ReadWrite);
// write to memory
WriteProcessMemory(handle, sharedProcMemString, memStorage);
WriteProcessMemory(handle, sharedProcMem, GetBytes(lvi));
// get the text
IntPtr result = SendMessage(handle, LVM_SETITEMTEXTA, (IntPtr)index, sharedProcMem);
if ((int)result == 0) // false, i.e. error
{
int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
// TODO: do something with errorCode - e.g. log it?
}
// clean up
VirtualFreeEx(handle, sharedProcMem, System.Runtime.InteropServices.Marshal.SizeOf(lvi), AllocationType.Release);
VirtualFreeEx(handle, sharedProcMemString, (int)size, AllocationType.Release);
}
以下是一些支持程序:
private static byte[] GetBytes(LVITEM str)
{
int size = System.Runtime.InteropServices.Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);
System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr, true);
System.Runtime.InteropServices.Marshal.Copy(ptr, arr, 0, size);
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr);
return arr;
}
public static void WriteProcessMemory(IntPtr handle, IntPtr writeAddress, byte[] buffer)
{
int bytesWritten;
WriteProcessMemory(handle, writeAddress, buffer, (uint)buffer.Length, out bytesWritten);
}
以下是必要的P / Invoke声明:
private const int LVM_FIRST = 0x1000;
private const int LVM_GETITEMCOUNT = LVM_FIRST + 4;
private const int LVM_GETITEM = LVM_FIRST + 75;
private const int LVIF_TEXT = 0x0001;
private const int LVM_SETITEMTEXTA = (LVM_FIRST + 46);
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct LVITEM
{
public uint mask;
public int iItem;
public int iSubItem;
public uint state;
public uint stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
public IntPtr lParam;
}
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd,
int Msg,
IntPtr wParam,
IntPtr lParam);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess,
IntPtr lpAddress,
uint dwSize,
AllocationType flAllocationType,
MemoryProtection flProtect);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern bool VirtualFreeEx(IntPtr hProcess,
IntPtr lpAddress,
int dwSize,
AllocationType dwFreeType);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteProcessMemory(IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
uint nSize,
out int lpNumberOfBytesWritten);
有什么想法?感谢。