本文记录一个 Win32 的有趣行为,调用 CreateProcess 方法传入特别的参数,可以让任务管理器里的命令行不显示应用文件路径

开始之前,先看看下面这张有趣的图片

可以看到我编写的 SvcawgewawkuHenaynairbelhurno.exe 应用在任务管理器的命令行里面显示的参数居然是 C:\Windows\notepad.exe 而不是具体的 SvcawgewawkuHenaynairbelhurno 应用 C:\lindexi\Code\SvcawgewawkuHenaynairbelhurno\SvcawgewawkuHenaynairbelhurno\bin\Debug\net6.0\SvcawgewawkuHenaynairbelhurno.dll 路径

这是如何实现的呢?这是使用了 CreateProcess 方法的一个过时用法,那就是在此方法的 lpApplicationName 参数里面传入将要启动的进程路径,在第二个参数 lpCommandLine 里面传入的是 C:\Windows\notepad.exe 命令行参数

以下是 CreateProcess 方法签名

BOOL CreateProcessW
(
[in, optional] LPCWSTR lpApplicationName,
[in, out, optional] LPWSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCWSTR lpCurrentDirectory,
[in] LPSTARTUPINFOW lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);

在开始之前,需要聊聊 CreateProcess 方法的参数。根据 Windows 核心编程 第 5 版的 4.2.1 章的内容,可以知道几乎所有的应用代码都应该传入 null 给到 lpApplicationName 参数。这个 lpApplicationName 参数是为了支持 Windows 的 POSIX 子系统。换句话说就是正常咱是不应该使用到这个参数的。以下是书中的原文:

之所以让我们能为 CreateProcess 添加 pszApplicationName 参数,实际是为了支持 Windows 的 POSIX 子系统

注:书中的 pszApplicationName 参数,就是以上代码的 lpApplicationName 参数,只是参数命名有所不同而已

如果咱偏偏就要用这个 lpApplicationName 参数呢,就可以玩出一些无文档的锅,例如让任务管理器里面的命令行行为奇怪起来

接下来咱将创建一个控制台项目来测试此行为

先新建一个 dotnet 6 控制台程序,为了方便 PInvoke 调用 Win32 的 CreateProcess 函数,根据 dotnet 使用 CsWin32 库简化 Win32 函数调用逻辑 博客,添加 Microsoft.Windows.CsWin32 库,编辑 csproj 项目文件,替换为如下代码

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWin32" PrivateAssets="all" Version="0.2.63-beta" />
</ItemGroup>
</Project>

接着再新建一个 NativeMethods.txt 文件,在此文件添加 CreateProcess 内容,用于让 CsWin32 生成调用相关的代码。但是 CsWin32 生成的代码比较难以使用,这里由自己定义了简单使用的方法

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "CreateProcessW", ExactSpelling = true, SetLastError = true)]
static extern bool CreateProcess([In] string lpApplicationName, [In] string lpCommandLine, [In] IntPtr lpProcessAttributes,
[In] IntPtr lpThreadAttributes, [In] bool bInheritHandles, [In] uint dwCreationFlags, [In] IntPtr lpEnvironment,
[In] IntPtr lpCurrentDirectory, [In] in STARTUPINFOW lpStartupInfo, [Out] out PROCESS_INFORMATION lpProcessInformation);

为了方便代码使用,这里启动的进程也是自身应用路径。先使用以下代码获取自身的应用程序路径。当然,你也可以换成其他你喜欢的应用程序路径

var mainModuleFileName = Process.GetCurrentProcess().MainModule!.FileName!;

接下来创建一个有趣的命令行参数,例如就是记事本的路径

var arguments = "\"C:\\windows\\notepad.exe\"";

接着调用 CreateProcess 函数,如以下代码

var mainModuleFileName = Process.GetCurrentProcess().MainModule!.FileName!;

var startupInfo = new STARTUPINFOW();
startupInfo.cb = (uint) Marshal.SizeOf<STARTUPINFOW>(); var arguments = "\"C:\\windows\\notepad.exe\""; CreateProcess(mainModuleFileName, arguments, IntPtr.Zero, IntPtr.Zero, false, (uint) PROCESS_CREATION_FLAGS.CREATE_NEW_CONSOLE,
IntPtr.Zero, IntPtr.Zero, startupInfo, out var information);

由于是应用程序启动自身应用程序路径,还需要加上一点代码,防止不断启动

var processList = Process.GetProcessesByName(Assembly.GetExecutingAssembly().GetName().Name);
if (processList.Length > 1)
{
Console.WriteLine($"被启动的进程");
Console.Read();
}

开始启动项目,即可看到在任务管理器里面显示的命令行奇怪起来

如果以上的 arguments 是一个空字符串,那任务管理器将依然显示的是应用程序的文件路径

本文的代码放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 5bdc7de90b19094ecde1fc78a404f3d753c159cf

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 5bdc7de90b19094ecde1fc78a404f3d753c159cf

获取代码之后,进入 SvcawgewawkuHenaynairbelhurno 文件夹

Win32 使用 CreateProcess 方法让任务管理器里的命令行不显示应用文件路径的更多相关文章

  1. 【Android测试】【随笔】在手机里用命令行创建中文文件夹

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4580319.html 不知道为啥当时自己写了一段在手机里用 ...

  2. 命令行下从bak文件恢复sqlserver数据库方法

    命令行下从bak文件恢复sqlserver数据库方法 注:本文所示访问从SqlServer 2000 - 2014版都是通用的 参考:http://blog.sina.com.cn/s/blog_5c ...

  3. 方法:怎么用ionic命令行调试你的ionic app

    官网上有很详细的解说  http://blog.ionic.io/live-reload-all-things-ionic-cli/ 下面说说我自己的调试过程(android版): 首先用命令行进入你 ...

  4. 不用输入ssh -i命令行即可携带pem文件快速登录的方法

    如果要登录的服务器只允许pem认证 每次输入ssh -i xxxx.pem 用户@ip 地址  就很烦 这里有个一劳永逸的方法: 进入到自己的用户目录,例如/home/me 把pem文件放在当前目录 ...

  5. Mac os下换行符导致发布到npm里的命令行模块不能使用问题

    学习node,弄一个命令行模块,发布到npm后,Windows安装后可以使用,但Mac 终端下则不行.对比grunt-cli搞了一夜,甚是郁闷,最后发现竟然是操作系统的换行符问题. npm insta ...

  6. 在终端(Terminal)里用命令行进行数学运算

    有时候我们进行一些数学运算,我们会去开系统自带的计算来做这件事情,其实我们也可以直接在终端里面用命令行进行的. 在命令行里敲 bc 进入数学计算模式,然后随便输入数学表达式 回车 ,结果就出来了,是不 ...

  7. Centos命令行窗口显示一大串前缀,777;notify;Command completed;的解决方法

    How to remove the return code from the terminal prompt In addition to the PS1 environment variable, ...

  8. 在VS中向命令行添加参数的方法

    在VS中向命令行添加参数的方法 在VS中向命令行添加参数,即向main()函数传递参数的方法: 右键单击要 添加参数的工程-->属性-->配置属性-->调试,在右侧“命令参数”栏输入 ...

  9. Mysql命令行中文乱码的解决方法

    环境:Windows 8 64位,Mysql  5.0.96 for Win64 (x86) 数据库本身安装时默认已经是使用utf8编码的了,但在命令行中执行查询时,查询到的中文依然乱码,解决方法如下 ...

  10. 命令行从Android手机中导出已安装APK的方法调研

    一.背景 二.步骤 一.背景 很多时候,APK文件只存在于应用市场,在PC上无法直接下载.用手机下载下来后就直接安装了,也不能保存原始的APK文件. APK安装到手机后,Android系统会保存一份和 ...

随机推荐

  1. .NET Emit 入门教程:第一部分:Emit 介绍

    前言: Emit 是开发者在掌握反射的使用后,进阶需要的知识,它能显著的改善因反射带来的性能影响. 目前能搜到的 Emit 的相关文章,都是一篇系列,通常推荐对照着反绎后的 IL 编写 Emit 代码 ...

  2. 【LeetCode刷题】剑指Offer 48.最长不含重复字符的子字符串

    剑指Offer 48.最长不含重复字符的子字符串(点击跳转LeetCode) 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度. 示例 1: 输入: "abcab ...

  3. 以最大速度将数据迁移至AWS S3存储

    数据上云,已经成为企业数据管理发展的必然趋势. 对于企业而言,数据上云"常态化"的趋势,无疑是一个巨大的技术红利.而数据规模爆发式增长的今天,移动和访问云端数据却成为困扰企业的一大 ...

  4. KingbaseES V8R6集群运维系列 -- connect_check_type参数

    案例说明: 在KingbaseES V8R6C7的版本中,repmgr.conf增加了connect_check_type参数可以指定参数值,默认值是'mix',以前版本为隐藏参数,默认值'ping' ...

  5. el-table设置列属性fixed导致滚动条无法拖动-骨灰级

    一.前言说明 网上一搜索,千篇一律的设置el-table__fixed,如: .el-table__fixed { // 左固定列 height: auto !important; bottom: 1 ...

  6. Python 中的字符串基础与应用

    在Python中,字符串可以用单引号或双引号括起来.'hello' 与 "hello" 是相同的.您可以使用print()函数显示字符串文字: 示例: print("He ...

  7. SSM框架整合——书籍管理系统

    1.准备工作: 1.1.环境要求 IDEA MySQL 5.7.19 Tomcat 9 Maven 3.6 1.2.数据库设计 创建一个存放书籍数据的数据库表: CREATE DATABASE `ss ...

  8. JDBC驱动连接MogDB/opengauss

    JDBC 驱动连接 MogDB/opengauss 一.环境说明 [root@node1 ~]# cat /etc/redhat-release CentOS Linux release 7.6.18 ...

  9. git worktree与分支依赖隔离

    git worktree介绍 git worktree 是 Git 命令,用于管理多分支工作区. 使用场景: 同时维护不同分支,隔离分支依赖差异:从原有项目开辟一个分支作为另一个新项目,当两个项目依赖 ...

  10. 重新点亮linux 命令树————网络故障排除[十一五]

    前言 简单整理一下网络故障不可达命令. 正文 ping 是否能ping traceroute 追踪路由跳转 mtr 检查数据包是否丢失 nslookup telnet 端口是否可达 tcpdump 能 ...