Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在将文件添加到程序集之前转换文件?_C#_File_Build Process_Transformation - Fatal编程技术网

C# 如何在将文件添加到程序集之前转换文件?

C# 如何在将文件添加到程序集之前转换文件?,c#,file,build-process,transformation,C#,File,Build Process,Transformation,我想做以下工作: (项目是WPF的用户控制库) 将一组.FX(着色器源代码)文件作为资源添加到项目中(生成操作) 通过调用FXC.EXE实用程序将每个文件转换为.PS文件(编译着色器) 使用生成的文件代替输入的文件 我一直想写一个,不幸的是,Visual Studio从来没有看到过本文中提到的工具。在这篇文章中,有人说,有时它是看不见的,但在我的情况下,它翻译成每一次 我也看过,但我不确定它是否适合这个任务 这样做的目的是包含着色器文件源代码,并在生成时对其进行转换,而不是从命令行手动生成着

我想做以下工作:

(项目是WPF的用户控制库)

  • 将一组.FX(着色器源代码)文件作为资源添加到项目中(生成操作)
  • 通过调用FXC.EXE实用程序将每个文件转换为.PS文件(编译着色器)
  • 使用生成的文件代替输入的文件
我一直想写一个,不幸的是,Visual Studio从来没有看到过本文中提到的工具。在这篇文章中,有人说,有时它是看不见的,但在我的情况下,它翻译成每一次

我也看过,但我不确定它是否适合这个任务

这样做的目的是包含着色器文件源代码,并在生成时对其进行转换,而不是从命令行手动生成着色器文件,然后每次都将其放到项目中

你知道怎样才能做到这一点吗?欢迎使用任何方法

编辑

感谢@Luaan的回答:

public class CompileEffectTask : Task
{
    public string[] Files { get; set; }

    public override bool Execute()
    {
        if (Files != null)
        {
            foreach (string file in Files)
            {
                if (file != null)
                {
                    Log.LogMessage(MessageImportance.High, file);

                    string s = @"C:\Program Files (x86)\Windows Kits\8.1\bin\x86\fxc.exe";
                    string changeExtension = Path.ChangeExtension(file, "ps");
                    string arguments = string.Format("/T ps_3_0 /Fo \"{0}\"" + " " + "\"{1}\"", changeExtension,
                        file);
                    Log.LogMessage(MessageImportance.High, arguments);
                    var process = new Process
                    {
                        StartInfo = new ProcessStartInfo(s, arguments)
                    };
                    process.Start();
                    process.WaitForExit();
                }
            }
        }
        return true;
    }
}
以及MSBuild部分:

  <UsingTask TaskName="CompileEffectTask" AssemblyFile="D:\HLSLCompiler.dll" />
  <PropertyGroup>
    <BuildDependsOn>
      MyCustomTarget1;
      $(BuildDependsOn);
    </BuildDependsOn>
  </PropertyGroup>
  <Target Name="MyCustomTarget1">
    <Message Text="CompileEffectTask started" Importance="high" />
    <Message Text="Compiling FX files ..." Importance="high" />
    <CompileEffectTask Files="@(CompileEffectTask)"/>
    <Message Text="Adding resulting .PS files as resources ..." Importance="high" />
    <ItemGroup>
      <Resource Include="**\*.ps" />
    </ItemGroup>
  </Target>
  <Target Name="AfterBuild">
    <CreateItem Include="**\*.ps">
      <Output TaskParameter="Include" ItemName="DeleteAfterBuild" />
    </CreateItem>
    <Delete Files="@(DeleteAfterBuild)" />
  </Target>

MyCustomTarget1;
$(BuildDependsOn);

(仍然需要一些清理,但它可以工作:D)

事实上,自定义工具确实可以工作,但它们的设置相当棘手-它们是Visual Studio的COM扩展。但是,对于您的情况,更好的解决方案是自定义生成目标或预生成事件—自定义工具(代码生成器)更适合生成代码(文本)而不是二进制文件

因此,预构建事件是一个简单的事件。它只是在项目开始构建之前运行的一些脚本。您可以在项目属性中找到它。最简单的方法是将所有
.fx
文件放在一个目录中,在预构建事件中,只需对每个文件调用
fxc.exe

现在,构建目标更酷了。它们允许您将自己的构建操作添加到文件中。因此,您只需在文件的
buildaction
中选择
CompileEffect
,奇迹就发生了

目标文件可以非常简单:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <AvailableItemName Include="CompileEffect"></AvailableItemName>
  </ItemGroup>
</Project>
这基本上是说“先运行我的构建目标,然后运行你想要的任何东西”

现在,对于建筑:

<Target Name="MyCompileTarget">
  <CompileEffectTask
      ProjectDirectory="$(ProjectDir)"
      Files="@(CompileEffect)"
      RootNamespace="$(RootNamespace)">
  </CompileEffectTaskTask>
</Target>
然后您只需要实现编译器任务本身

现在,如果只想调用可执行文件或批处理脚本,甚至不需要该自定义任务,因为MSBuild中有很多内置任务(甚至更多的内置任务)<代码>执行任务应能工作:

<Target Name="MyCompileTarget">
  <Exec Command="fxc.exe @(CompileEffect)" />
</Target>


你可能必须在那里为循环编写一个
,我不完全确定。你可以做很多事情来定制项目构建(特别是任务引用部分),这是一个很好的开始。

听起来很有希望:D我今天下午会尝试一下,然后回来。非常好,完成了工作:D谢谢!
<UsingTask TaskName="MyAssembly.CompileEffectTask" 
           AssemblyFile="C:\MyAssembly.dll"/>
<Target Name="MyCompileTarget">
  <Exec Command="fxc.exe @(CompileEffect)" />
</Target>