สร้างแอปพลิเคชันคอนโซล. NET Core เพื่อส่งออก EXE


413

สำหรับโครงการแอปพลิเคชันคอนโซลที่กำหนดเป้าหมาย. NET Core 1.0 ฉันไม่สามารถทราบวิธีรับ. exe เพื่อแสดงผลในระหว่างการบิลด์ โครงการทำงานได้ดีในการดีบัก

ฉันพยายามเผยแพร่โครงการ แต่ก็ไม่ได้ผลเหมือนกัน มันสมเหตุสมผลแล้วเนื่องจากไฟล์ EXE จะเป็นแบบเฉพาะแพลตฟอร์ม แต่ต้องมีวิธี การค้นหาของฉันมีการอ้างอิงถึงรุ่น. NET Core รุ่นเก่าที่ใช้ project.json เท่านั้น

เมื่อใดก็ตามที่ฉันสร้างหรือเผยแพร่นี่คือทั้งหมดที่ฉันได้รับ:

สร้างไดเรกทอรี


15
สำเนาที่เป็นไปได้ของVS2017 Compile NetCoreApp เป็น EXE
Martin Ullrich

2
@ geekzster โปรดยกเลิกการลบ - ฉันรู้ว่าคุณไม่ได้ตอบคำถาม OP แต่คุณตอบฉันและฉันสงสัยว่าคนอื่น ๆ ด้วยการพูดdotnet <path>.dll(ฉันไม่ได้คิดและพิมพ์dotnet run <path>.dllโดยไม่ประสบความสำเร็จด้วยเหตุผลที่ชัดเจน)! (ในภาพสะท้อนมันจะดีที่ว่านี้ถูกปิดในความโปรดปรานของคำถามอื่น ๆ ที่มีชุดของคำตอบที่คล้ายกัน)
Ruben Bartelink

คำตอบ:


480

สำหรับวัตถุประสงค์ในการแก้ไขข้อบกพร่องคุณสามารถใช้ไฟล์ DLL คุณสามารถเรียกใช้โดยใช้dotnet ConsoleApp2.dllคุณสามารถเรียกใช้หากคุณต้องการสร้างไฟล์ EXE คุณต้องสร้างแอปพลิเคชันที่มีในตัวเอง

ในการสร้างแอปพลิเคชั่นที่มีในตัวเอง (EXE ใน Windows) คุณจะต้องระบุรันไทม์เป้าหมาย (ซึ่งเฉพาะสำหรับระบบปฏิบัติการที่คุณกำหนดเป้าหมาย)

Pre-.NET Core 2.0 เท่านั้น : ขั้นแรกเพิ่มตัวระบุรันไทม์ของ runtimes เป้าหมายในไฟล์. csproj ( รายการ RID ที่รองรับ ):

<PropertyGroup>
    <RuntimeIdentifiers>win10-x64;ubuntu.16.10-x64</RuntimeIdentifiers>
</PropertyGroup>

ขั้นตอนข้างต้นไม่จำเป็นต้องเริ่มต้นด้วย. NET Core 2.0 อีกต่อไปอีกต่อไป

จากนั้นตั้งค่ารันไทม์ที่ต้องการเมื่อคุณเผยแพร่แอปพลิเคชันของคุณ:

dotnet publish -c Release -r win10-x64
dotnet publish -c Release -r ubuntu.16.10-x64

15
ฉันคิดว่าสิ่งนี้สามารถทำได้กับ CLI เท่านั้น BTW เริ่มต้นด้วย. net core 2 คุณไม่จำเป็นต้องตั้งค่าRuntimeIdentifierใน csproj
meziantou

26
. NET Core 2.0 สามารถทำได้ใน Visual Studio หรือไม่? หรือฉันต้องพิมพ์คำสั่งเหล่านี้ด้วยมือ?
Tomasz Sikora

77
มากกว่า 60MB สำหรับแอพ Hello world console!
shox

13
@mikolaj มีเพียงหนึ่งรันไทม์เป้าหมาย "พกพา" มีวิธีที่จะนำเป้าหมายทั้งหมดมาด้วยหรือไม่? ฉันโอเคกับการใช้บรรทัดคำสั่ง แต่คิดว่ามันเป็นขั้นตอนหลัง
gsharp

10
สิ่งนี้ไม่ได้สร้างปฏิบัติการแบบสแตนด์อโลน สิ่งนี้จะสร้างไฟล์ปฏิบัติการพร้อมกับโฮสต์ของไฟล์อื่น ๆ (ในโฟลเดอร์ release ฉันหมายถึง) รวมถึงโฟลเดอร์ย่อยบางไฟล์พร้อมกับไฟล์ของตนเอง มีวิธีในการสร้างไฟล์ปฏิบัติการแบบสแตนด์อโลนจริงหรือไม่?
แมทธิว

122

อัปเดต (31-OCT-2019)

สำหรับทุกคนที่ต้องการทำสิ่งนี้ผ่าน GUI และ:

  • กำลังใช้ Visual Studio 2019
  • ติดตั้ง. NET Core 3.0 (รวมอยู่ใน Visual Studio 2019 เวอร์ชันล่าสุด)
  • ต้องการสร้างไฟล์เดียว

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

บันทึก

สังเกตขนาดไฟล์ใหญ่สำหรับแอพพลิเคชั่นขนาดเล็ก

ป้อนคำอธิบายภาพที่นี่

คุณสามารถเพิ่มคุณสมบัติ "PublishTrimmed" แอปพลิเคชันจะรวมเฉพาะส่วนประกอบที่ใช้งานโดยแอปพลิเคชัน ข้อควรระวัง : อย่าทำสิ่งนี้หากคุณใช้การสะท้อน

ป้อนคำอธิบายภาพที่นี่

เผยแพร่อีกครั้ง

ป้อนคำอธิบายภาพที่นี่


โพสต์ก่อนหน้า

สำหรับทุกคนที่ใช้ Visual Studio และต้องการทำสิ่งนี้ผ่าน GUI ดูขั้นตอนด้านล่าง:

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่


19
น่าเสียดายที่ผลลัพธ์คือไฟล์จำนวนมากไม่ใช่เพียง EXE เดียวเช่น. NET Framework เก่า
Tomas Karban

2
@Tomas Karban - มันเป็นกรณีจนกว่าฉันจะเปลี่ยนโหมดการใช้งานที่ "อยู่ในตัวเอง" หลังจากการเปลี่ยนแปลงไฟล์ exe ปรากฏในโฟลเดอร์เผยแพร่ยัง :-)
Mariusz

@TomasKarban .NET Core ไม่ใช่วัตถุประสงค์ทั่วไปของรันไทม์ มันออกแบบมาเป็นพิเศษสำหรับ 1) การใช้งานคลาวด์ / ภาชนะ 2) หลายแพลตฟอร์ม นอกจากนี้ยังหมายถึงเป็นการชั่วคราว - เป็นเพียงแฮ็ค "ด่วน" จนกว่า NET ทั้งหมดจะสามารถทำโอเพนซอร์ซได้ . NET 5.0 จะเป็นวัตถุประสงค์ทั่วไปต่อไปของ. NET
Luaan

3
ถึงกระนั้นก็ไร้สาระที่ The IDE สำหรับ. NET ไม่รองรับฟังก์ชั่นพื้นฐานที่สุดเมื่อคุณกำหนดเป้าหมายเป็น. NET Core และนั่นคือสิ่งที่ทุกคนต้องกำหนดเป้าหมายเพื่อสร้างแอปพลิเคชันบรรทัดคำสั่งข้ามแพลตฟอร์ม - เช่นคอมไพเลอร์
Reinstate Monica

18

ต่อไปนี้จะผลิตในไดเรกทอรีผลลัพธ์

  • การอ้างอิงแพ็คเกจทั้งหมด
  • แอสเซมบลีเอาท์พุท
  • bootstrapping exe

แต่มันไม่มีแอสเซมบลีรันไทม์. NET Core ทั้งหมด

<PropertyGroup>
  <Temp>$(SolutionDir)\packaging\</Temp>
</PropertyGroup>

<ItemGroup>
  <BootStrapFiles Include="$(Temp)hostpolicy.dll;$(Temp)$(ProjectName).exe;$(Temp)hostfxr.dll;"/>
</ItemGroup>

<Target Name="GenerateNetcoreExe"
        AfterTargets="Build"
        Condition="'$(IsNestedBuild)' != 'true'">
  <RemoveDir Directories="$(Temp)" />
  <Exec
    ConsoleToMSBuild="true"
    Command="dotnet build $(ProjectPath) -r win-x64 /p:CopyLocalLockFileAssemblies=false;IsNestedBuild=true --output $(Temp)" >
    <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
  </Exec>
  <Copy
    SourceFiles="@(BootStrapFiles)"
    DestinationFolder="$(OutputPath)"
  />

</Target>

ฉันรวบรวมมันไว้ในตัวอย่างที่นี่: https://github.com/SimonCropp/NetCoreConsole


ยกเว้นจุด ($ Temp) ไปที่ c: \ Users \ xxx \ AppData \ Local \ Temp ซึ่งไม่สามารถลบ / ล้างได้อย่างชัดเจน - และไม่แนะนำให้ทำเช่นนั้น
Adaptabi

1
@Adaptabi Temp ถูกกำหนดให้เป็นสถานที่ให้บริการในช่วงเริ่มต้นของสคริปต์
Simon

2

หากยอมรับไฟล์. bat คุณสามารถสร้างไฟล์ bat ที่มีชื่อเดียวกันกับไฟล์ DLL (และวางไว้ในโฟลเดอร์เดียวกัน) จากนั้นวางเนื้อหาดังต่อไปนี้:

dotnet %~n0.dll %*

เห็นได้ชัดว่านี่เป็นเครื่องที่ติดตั้ง. NET Core และมีวางจำหน่ายทั่วโลก

c:\> "path\to\batch\file" -args blah

(คำตอบนี้ได้มาจากความคิดเห็นของ Chet )


0

นี่คือวิธีแก้ปัญหาแฮ็คของฉัน - สร้างแอปพลิเคชั่นคอนโซล (.NET Framework) ที่อ่านชื่อและอาร์กิวเมนต์ของตัวเองแล้วโทร dotnet [nameOfExe].dll [args]ที่อ่านชื่อของตัวเองและข้อโต้แย้งและบริการโทรแล้ว

แน่นอนว่าสมมติว่ามีการติดตั้ง. NET บนเครื่องเป้าหมาย

นี่คือรหัส อย่าลังเลที่จะคัดลอก!

using System;
using System.Diagnostics;
using System.Text;

namespace dotNetLauncher
{
    class Program
    {
        /*
            If you make .NET Core applications, they have to be launched like .NET blah.dll args here
            This is a convenience EXE file that launches .NET Core applications via name.exe
            Just rename the output exe to the name of the .NET Core DLL file you wish to launch
        */
        static void Main(string[] args)
        {
            var exePath = AppDomain.CurrentDomain.BaseDirectory;
            var exeName = AppDomain.CurrentDomain.FriendlyName;
            var assemblyName = exeName.Substring(0, exeName.Length - 4);
            StringBuilder passInArgs = new StringBuilder();
            foreach(var arg in args)
            {
                bool needsSurroundingQuotes = false;
                if (arg.Contains(" ") || arg.Contains("\""))
                {
                    passInArgs.Append("\"");
                    needsSurroundingQuotes = true;
                }
                passInArgs.Append(arg.Replace("\"","\"\""));
                if (needsSurroundingQuotes)
                {
                    passInArgs.Append("\"");
                }

                passInArgs.Append(" ");
            }
            string callingArgs = $"\"{exePath}{assemblyName}.dll\" {passInArgs.ToString().Trim()}";

            var p = new Process
            {
                StartInfo = new ProcessStartInfo("dotnet", callingArgs)
                {
                    UseShellExecute = false
                }
            };

            p.Start();
            p.WaitForExit();
        }
    }
}

6
หากคุณกำลังจะมีไฟล์เพิ่มเติมอยู่ทำไมไม่สร้างไฟล์ bat ที่มีdotnet [nameOfExe].dll %*
Chet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.