我有一个非常简单的应用程序,它会自动从 Git 标签获取固件文件的版本号,并将固件版本写入二进制文件的末尾,并在每次构建固件时将版本附加到名称文件。对于我处理的每个项目,我想将这个可执行文件复制到固件的项目文件夹中,因此该应用程序只需在它所在的同一目录中查找所需的文件,而不管它的实际位置如何(因此我不不必每次都重新编程)。
这在 VS 项目文件夹中完美运行(我复制了所需的文件),但是当我将 .exe 文件移动到固件项目文件夹时,它不再起作用。我认为问题是获取 .exe 位置路径的代码仍然是它自己的项目文件夹,而不是新位置。让它发挥作用的正确方法是什么?
我试过了:
Environment.CurrentDirectory;
Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
System.Reflection.Assembly.GetExecutingAssembly().Location;
和其他一些。我不明白为什么这是一件如此困难的事情。
编辑:.Net Core3.1
编辑:完整代码:
using System;
using System.IO;
using System.Diagnostics;
namespace VersionAppend
{
class Program
{
const int INSERT_OFFSET = 0x1EFF9;
const byte VER_NUMS = 3;
const byte VER_SIZE = VER_NUMS * sizeof(ushort);
static void Main(string[] args)
{
byte[] version = new byte[VER_SIZE];
string versionFileName = AppContext.BaseDirectory + @"\version";
if (!File.Exists(versionFileName))
{
Trace.WriteLine("Error");
return;
}
// Get Firmware version as string
string versionString = File.ReadAllText(versionFileName);
// Break version into parts
Version ver = Version.Parse(versionString);
convertVersionToBytes(ver, version);
// Search for Firmware File
string directory = AppContext.BaseDirectory + @"\Debug";
string firmwareKeyword = "firmware";
var files = Directory.EnumerateFiles(directory, "*" + firmwareKeyword + ".bin");
foreach (string item in files)
{
// Open firmware file
BinaryWriter firmware = new BinaryWriter(new FileStream(item, FileMode.Open));
firmware.Seek(INSERT_OFFSET, SeekOrigin.Begin);
// Write version to end
firmware.Write(version, 0, (int)VER_SIZE);
// Close firmware file
firmware.Close();
string extension = Path.GetExtension(item);
string file = Path.GetFileNameWithoutExtension(item);
// Rename file with version
string verString = convertVersionToString(version);
File.Move(item, @item.Substring(0, item.Length -extension.Length) + "_" + verString + ".bin");
}
}
private static void convertVersionToBytes (Version ver, byte [] version)
{
// Major.MSB, Major LSB, Minor...
version[0] = (byte)((ushort)(ver.Major >> 8) & 0xFF);
version[1] = (byte)((ushort)ver.Major & 0xFF);
version[2] = (byte)((ushort)(ver.Minor >> 8) & 0xFF);
version[3] = (byte)((ushort)ver.Minor & 0xFF);
version[4] = (byte)((ushort)(ver.Build >> 8) & 0xFF);
version[5] = (byte)((ushort)ver.Build & 0xFF);
}
private static string convertVersionToString(byte [] version)
{
return BitConverter.ToString(version).Replace("-", "");
}
}
}
答案 0 :(得分:1)
不难。
但它可能取决于您的目标平台(您尚未指定)。
对于 .Net Core 1.x 和 .Net 5 或更高版本,我会使用 AppContext.BaseDirectory
以下是多年来适用于各种环境的其他一些替代方案:
<块引用>6 ways to get the current directory in C#, August 17, 2010
AppDomain.CurrentDomain.BaseDirectory 这是全方位的最佳选择。它将为您提供类库的基目录, 包括 ASP.NET 应用程序中的那些。
Directory.GetCurrentDirectory() 注意:在 .NET Core 中,这是当前的最佳实践。以下详细信息与 .NET Framework 相关 4.5 及以下。
这使用 winapi GetCurrentDirectory 调用进行互操作调用 在 kernel32.dll 中,这意味着启动进程的文件夹将 经常被退回。同样正如 MSDN 文档所说,不能保证 在移动设备上工作。
Environment.CurrentDirectory
这只是调用 Directory.GetCurrentDirectory()
装配.位置
这将使用
this.GetType().Assembly.Location
这将返回调用程序集的完整路径,包括 程序集名称本身。如果您正在调用单独的类库, 然后将返回其基目录,例如“C:\myassembly.dll” - 显然取决于正在使用的程序集实例。
Application.StartupPath
它位于 System.Windows.Forms 命名空间内,因此通常仅用于窗口窗体应用程序。
Application.ExecutablePath 与 Application.StartupPath 相同,但也包括应用程序名称,例如“myapp.exe”