2019-1-29-Roslyn-使用-WriteLinesToFile-解决参数过长无法传入
title | author | date | CreateTime | categories |
---|---|---|---|---|
Roslyn 使用 WriteLinesToFile 解决参数过长无法传入
|
lindexi
|
2019-01-29 16:31:43 +0800
|
2018-07-23 20:48:32 +0800
|
Roslyn MSBuild 编译器
|
在写 Roslyn 的时候,经常需要辅助编译的工具,而这些工具需要传入一些参数,在项目很大的时候,会发现自己传入的参数比微软限制控制台可以传入的参数大很多,这时就无法传入了参数。
本文告诉大家如何使用 WriteLinesToFile 先把参数写入文件,通过文件的方式传输参数
为了让大家可以方便了解 Roslyn 编译过程,所以本文是带着一个任务来做的。通过阅读本文,大家可以学会怎么写出一些神奇的代码。
任务的背景是,在编译的过程,暗中修改一些代码,而且让开发者发现不了。
最简单的方法就是修改编译流程,修改编译流程是相对比较复杂的。但是上面在 MSBuild 可以使用很多奇怪的 Task 来做很多有趣的事情,其中就有一个强大的 Task 是 Exec
,这个命令就是使用命令行调用另一个程序。
也就是在编译的过程可以调用另一个程序,所以就把辅助编译的方法放在另一个程序去做。
但是要让这个辅助的程序跑,还需要告诉这个辅助的程序一下信息,如哪些需要编译的文件。
于是最简单的方式就是写一个 Target 来执行这个辅助的程序。先假设这个辅助的程序就放在 E:\辅助程序.exe
,调用的方法请看代码
<Target Name="BitedeZawpiDafuge" BeforeTargets="CoreCompile">
<Exec Command="E:\辅助程序.exe @(Compile)"></Exec>
</Target>
为了让 Target 运行需要给 Target 一个 Name ,还需要告诉 VisualStudio 什么时候运行这个 Target ,于是就使用BeforeTargets="CoreCompile"
告诉 VisualStudio 在开始编译之前就执行
当然,上面的写法只是为了方便第一次接触 Roslyn 的小伙伴,如果看到了这里还是有很多内容不知道,请先看手把手教你写 Roslyn 修改编译。
现在的问题是,调用 Exec 能传入的参数就是被微软限制大小,我的Compile
编译文件有 10000000000000 个,于是就有很多文件无法传参数进去,这时我就无法在编译之前把代码修改掉,让项目可以成功运行,这样本渣还怎么去坑一个团队。
所以腹黑的本渣就需要一个方式传入很大的参数,找到了一个简单的方法就是使用WriteLinesToFile
先把参数写到文件,然后把文件路径给辅助程序就可以
为了写入的文件可以在辅助程序找到,就需要先定义文件,请看代码
<ItemGroup>
<TextFile Include="Items.txt" />
</ItemGroup>
把参数写入文件的方法请看代码
<Target Name="WriteToFile" BeforeTargets="CoreCompile">
<WriteLinesToFile File="@(TextFile)" Lines="@(Compile)" Overwrite="true" />
</Target>
这时就会把 Compile 的所有文件都写入到TextFile
文件
在写完之后就可以调用 Exec 执行程序了,也许这时大家会发现,本金鱼又在逗大家了,辅助的程序怎么知道 WriteLinesToFile 执行完了,会不会拿到一个空的文件。
我很负责和大家说,会的,如果现在不修改代码直接调用就会出现读取到的文件可能是空的
还记得 DependsOnTargets
这个属性?通过这个属性可以指定一个 Target 在什么时候运行,在运行辅助程序的代码就需要依赖上面的代码运行。于是修改之后的全部代码请看下面
<Target Name="WriteToFile">
<WriteLinesToFile File="@(TextFile)" Lines="@(Compile)" Overwrite="true" />
</Target> <Target Name="BitedeZawpiDafuge" BeforeTargets="CoreCompile" DependsOnTargets="WriteToFile">
<Exec Command="E:\辅助程序.exe $(MSBuildProjectDirectory)\@(TextFile)"></Exec>
</Target>
现在的代码是可以运行了,从参数可以拿到文件名,然后通过读文件的方式拿到输入的文件
现在的代码已经可以运行了,但是本渣还需要继续告诉大家一些属性的设置是为什么,第一个设置的参数就是WriteLinesToFile
的 File
,使用这个就可以设置输出到哪个文件。第二个参数Lines
就是输入的文本,不要问我文本怎么写为 line
而且是按照;
分割多行的。
最后一个参数比较重要,是设置如果存在这个文件是否覆盖,如果没有选择覆盖,那么下面的辅助程序拿到的文件都会是以前的文件。我就是没有设置这个属性用了半个钟才发现读的文件都是以前的文件。
在另一个 Target 就是调用辅助程序,需要知道在参数传入的是$(MSBuildProjectDirectory)
路径的,原因就是刚才写入的文件相对的就是项目所在的文件夹,所以需要从项目所在的文件夹才可以拿到这个文件。
如果是想把文件写在一个临时的文件夹,那么建议使用 $(IntermediateOutputPath)
文件夹,这个$(IntermediateOutputPath)
文件夹就是 obj
文件夹,建议在这个文件夹里再创建一个文件夹用来放临时的文件。
需要注意,文件同样可以写在PropertyGroup
里,只是在PropertyGroup
的引用是使用$
请看下面代码
- <ItemGroup>
- <TextFile Include="Items.txt" />
- </ItemGroup>
+ <PropertyGroup>
+ <TextFile>Items.txt</TextFile>
+ </PropertyGroup>
<Target Name="WriteToFile">
- <WriteLinesToFile File="@(TextFile)" Lines="@(Compile)" Overwrite="true" />
+ <WriteLinesToFile File="$(TextFile)" Lines="@(Compile)" Overwrite="true" />
</Target>
因为 PropertyGroup 的内容是不存在 Include 特性,所以需要使用上面的方法
如果写入的文件的文件夹是不存在,就需要先创建,如写入的是 lindexi\foo.txt
就需要先判断lindexi
文件夹是否存在,如果没有判断直接使用就会出现下面代码
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 MSB3491 未能向文件“obj\Debug\netcoreapp2.0\lindexi\Items.txt”写入命令行。未能找到路径“C:\lindexi\framework\lindexi.Mvvm.framework\obj\Debug\netcoreapp2.0\lindexi\Items.txt”的一部分。 framework C:\Users\lindexi\.nuget\packages\lindexi.Mvvm.framework\0.1.52-alpha\build\lindexi.Mvvm.framework.targets 11
简单创建文件夹的方法是使用 MakeDir 请看下面代码
<PropertyGroup>
<TextDirectory>lindexi/</TextDirectory>
<TextFile>$(TextDirectory)Items.txt</TextFile>
</PropertyGroup>
<Target Name="WriteToFile">
<MakeDir Condition="!Exists($(TextDirectory))" Directories="$(TextDirectory)"></MakeDir>
<WriteLinesToFile File="$(TextFile)" Lines="@(Compile)" Overwrite="true" />
</Target>
我在测试的项目写了很长的参数,这个参数只能通过写入到文件的方式传输,不能通过参数的方法传输。测试项目请点击 Roslyn 使用 WriteLinesToFile 解决参数过长无法传入 1.0-CSDN下载
参见:
项目文件中的已知属性(知道了这些,就不会随便在 csproj 中写死常量啦) - walterlv
2019-1-29-Roslyn-使用-WriteLinesToFile-解决参数过长无法传入的更多相关文章
- Roslyn 使用 WriteLinesToFile 解决参数过长无法传入
在写 Roslyn 的时候,经常需要辅助编译的工具,而这些工具需要传入一些参数,在项目很大的时候,会发现自己传入的参数比微软限制控制台可以传入的参数大很多,这时就无法传入了参数 本文告诉大家如何使用 ...
- Alpha冲刺(6/10)——2019.4.29
所属课程 软件工程1916|W(福州大学) 作业要求 Alpha冲刺(6/10)--2019.4.29 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪 ...
- linux下删除大量文件提示参数过长解决办法
linux下删除大量文件提示参数过长解决办法:在当前目录下rm -rf * 在linux中删除大量文件时,直接用rm会出现:-bash: /bin/rm: 参数列表过长的错误. 这时可以用find命令 ...
- 解决window.location.href参数太长
前言:一提到页面跳转,最常用的一般就是window.location.href,如果需要带参数,也许可以在后面用?拼上,但这样并不安全,而且有个更严重的问题,这样的拼接是有长度限制的,如果达到好几千个 ...
- 解决window.location.href参数太长 post提交数据
前言:一提到页面跳转,最常用的一般就是window.location.href,如果需要带参数,也许可以在后面用?拼上,但这样并不安全,而且有个更严重的问题,这样的拼接是有长度限制的,如果达到好几千个 ...
- 六、SQL语句进行多条件查询,并解决参数为空的情况
一.SQL语句进行多条件查询,并解决参数为空的情况 QueryEntity query; var whereSql = new StringBuilder("Where 1=1") ...
- js代码生成form,解决mvc的url参数过长问题
在MVC项目中,通常下载的文件的简单方式是直接采用 location.href+查询参数方式. var searchParams = { studentName: $("#StudentNa ...
- excel导出使用get请求参数过长问题
遇到的问题: excel导出功能时,使用的是window.location.href=url也就是get请求.当传入参数过长的时候就报了414,地址过长的错误. 解决思路: 将get请求换为post请 ...
- Ajax请求参数较长导致请求失败
Ajax请求参数比较长,第5行参数大概1100个字符吧,是接口的请求报文. $.ajax({ type:"POST", url:"${ctx}/test.action?m ...
随机推荐
- CSS三大特性之继承性
1.并不是所有的属性都可以继承,只有以color/font/text/line开头的属性 才可以继承. 2.在CSS的继承中,不仅仅是儿子可以继承,只要是后代都可以继承. 3.继承中的特殊性 3.1 ...
- Nginx 教程 2:性能
为了获得更好的学习效果,我们建议你在本机安装 Nginx 并且尝试进行实践. tcp_nodelay, tcp_nopush 和 sendfile tcp_nodelay 在 TCP 发展早期,工程师 ...
- scull 中的设备注册
在内部, scull 使用一个 struct scull_dev 类型的结构表示每个设备. 这个结构定义为: struct scull_dev { struct scull_qset *data; ...
- BP 算法之一种直观的解释
0. 前言 之前上模式识别课程的时候,老师也讲过 MLP 的 BP 算法, 但是 ppt 过得太快,只有一个大概印象.后来课下自己也尝试看了一下 stanford deep learning 的 wi ...
- Entity Framework Code First 模式-建立一对一联系
使用的例子为教室(ClassRoom),教室里的多媒体设备(Device),一个教室里有一套多媒体设备,一套多媒体设备只放在一个教室里. 1.Data Annotations方式 需要在任意一方的主键 ...
- 小米手机 DELETE_FAILED_INTERNAL_ERROR Error while Installing APKs
手机:小米2s,MIUI 9 7.11.16 开发版 手机已处于开发者模式,启用了USB调试,已使用USB线连接了手机,在Android Studio 工具栏点击 "Run ‘app’(Sh ...
- soj102 普通平衡树
题意: 标程: #include<cstdio> using namespace std; int read() { ,f=;char ch=getchar(); ;ch=getchar( ...
- [转]使用TortoiseGit处理代码冲突
场景一 user0 有新提交 user1 没有pull -> 写新代码 -> pull -> 提示有冲突 解决办法一 -> stash save(把自己的代码隐藏存起来) ...
- Python-线程(1)
目录 什么是线程 进程与线程的区别 开启线程 为什么要使用线程 线程之间数据是共享的 什么是线程 线程与进程都是虚拟单位,目的是为了更好的描述某种事物 进程与线程的区别 进程:资源单位 线程:执行单位 ...
- JS中的Map和Set
使用iterable内置的forEach方法 var a = ['A', 'B', 'C']; a.forEach(function (element, index, array) { // elem ...