Code2Md
Code2Md\Code2md\Program.cs
if (args.Length == 0)
{
Console.WriteLine("请传入文件夹路径");
return;
}
if (!Directory.Exists(args[0]))
{
Console.WriteLine($"传入的文件夹不存在 : {args[0]}");
return;
}
Project project = new Project(args[0].Trim());
await project.Run();
Code2Md\Code2md\Project.cs
using System.Text;
public class Project
{
private readonly string _srcPath;
private readonly Config _config;
private readonly DateTime _now = DateTime.Now;
private string _suffix = string.Empty;
public Project(string srcPath)
{
_srcPath = srcPath;
_config = new Config(srcPath);
}
public async Task Run()
{
Console.WriteLine("============== Run Code2md START==============");
bool hasConfig = _config.CheckCode2mdConfig();
if (!hasConfig)
{
return;
}
Console.WriteLine("请输入文件名后缀:");
Console.InputEncoding = Encoding.Unicode;
Console.OutputEncoding = Encoding.Unicode;
_suffix = Console.ReadLine()?.Trim() ?? string.Empty;
_config.LoadConfig();
List<string> rootDirPaths = this.GetRootDirPaths();
List<string> deepDirs = await GetDeepDirPaths(rootDirPaths);
List<string> allDirPaths = rootDirPaths.Concat(deepDirs).ToList();
allDirPaths.Add(_srcPath);
List<string> allFilePaths = await GetAllFiles(allDirPaths);
List<string> sortedFilePaths = allFilePaths
.Select(path => new { Path = path, LastWriteTime = File.GetLastWriteTime(path) })
.OrderByDescending(file => file.LastWriteTime)
.Select(file => file.Path)
.ToList();
this.CodeToOneMarkdown(sortedFilePaths);
Console.WriteLine("============== Run Code2md END ==============");
}
private void CodeToOneMarkdown(List<string> filePaths)
{
var mdFileName = $"{_now:yyyyMMdd_HHmmss}_{_suffix}.md";
var mdFolderPath = Path.Combine(_srcPath, "zz_zz");
if (!Directory.Exists(mdFolderPath))
{
Directory.CreateDirectory(mdFolderPath);
}
string mdFilePath = Path.Combine(mdFolderPath, mdFileName);
using StreamWriter sw = new StreamWriter(mdFilePath, false, Encoding.UTF8);
string basePath = Path.GetDirectoryName(_srcPath) ?? string.Empty;
foreach (var file in filePaths)
{
string fileExtension = Path.GetExtension(file).ToLowerInvariant().Trim();
if (!_config.CodeToMarkDownExtension.Contains(fileExtension))
{
Console.WriteLine($"skip code2md no suffix: {file}");
continue;
}
string relativePath = Path.GetRelativePath(basePath, file);
sw.WriteLine($"\n## `{relativePath}`\n");
string? markdownCodeBlockName = _config.CodeSuffixMap.GetValueOrDefault(fileExtension);
if (string.IsNullOrEmpty(markdownCodeBlockName))
{
markdownCodeBlockName = fileExtension.Replace(".", "").Trim();
}
sw.WriteLine($"\n```{markdownCodeBlockName}\n");
try
{
using var fs = new FileStream(
file,
FileMode.Open,
FileAccess.Read,
FileShare.Read,
bufferSize: 4096,
useAsync: false
);
using var reader = new StreamReader(
fs,
Encoding.UTF8,
detectEncodingFromByteOrderMarks: true,
bufferSize: 8192
);
string? line;
while ((line = reader.ReadLine()) != null)
{
if (fileExtension.Equals(".cs"))
{
if (line.Trim().StartsWith("//"))
{
continue;
}
if (string.IsNullOrEmpty(line.Trim()))
{
continue;
}
}
sw.WriteLine(line);
}
}
catch (UnauthorizedAccessException)
{
Console.WriteLine($"Unauthorized access to file: {file}");
sw.WriteLine($"<!-- Unauthorized access to file: {file} -->\n```");
continue;
}
catch (IOException ex)
{
Console.WriteLine($"IO error reading file {file}: {ex.Message}");
sw.WriteLine($"<!-- IO error reading file: {file} - {ex.Message} -->\n```");
continue;
}
catch (System.Exception ex)
{
Console.WriteLine($"Error reading file {file}: {ex.Message}");
sw.WriteLine($"<!-- Error reading file: {file} - {ex.Message} -->\n```");
continue;
}
sw.WriteLine("\n```");
}
Console.WriteLine($"=========代码转成一个Markdown文件成功!!!=========");
}
private async Task<List<string>> GetAllFiles(List<string> allDirPaths)
{
List<Task<List<string>>> tasks = new List<Task<List<string>>>();
foreach (var allDirPath in allDirPaths)
{
tasks.Add(Task.Run(() => GetFilteringTopDirFiles(allDirPath)));
}
await Task.WhenAll(tasks);
var files = new List<string>();
foreach (var task in tasks)
{
files.AddRange(task.Result);
}
return files;
}
public List<string> GetFilteringTopDirFiles(string folderPath)
{
return Directory
.GetFiles(folderPath, "*", SearchOption.TopDirectoryOnly)
.Where(file => ShouldIncludeFile(Path.GetFileName(file)))
.ToList();
}
public bool ShouldIncludeFile(string fileName)
{
return !_config.GetExcludeFileFlag(fileName) || _config.GetIncludeFileFlag(fileName);
}
private List<string> GetRootDirPaths()
{
return Directory
.GetDirectories(_srcPath, "*", SearchOption.TopDirectoryOnly)
.Where(dirPath =>
{
string folderName = Path.GetFileName(dirPath);
System.Console.WriteLine(folderName);
return !_config.GetExcludeDirFlag(folderName)
|| _config.GetIncludeDirFlag(folderName);
})
.ToList();
}
private async Task<List<string>> GetDeepDirPaths(List<string> rootDirPaths)
{
var tasks = rootDirPaths
.Select(rootDirPath => Task.Run(() => GetFilteringAllDirTask(rootDirPath)))
.ToArray();
await Task.WhenAll(tasks);
return tasks.SelectMany(task => task.Result).ToList();
}
private List<string> GetFilteringAllDirTask(string rootDirPath)
{
var deepDirs = new List<string>();
GetFilteringAllDirs(rootDirPath, deepDirs);
return deepDirs;
}
public void GetFilteringAllDirs(string folderPath, List<string> allFolders)
{
try
{
var validSubdirs = GetFilteringTopDirFolders(folderPath);
foreach (var dir in validSubdirs)
{
allFolders.Add(dir);
GetFilteringAllDirs(dir, allFolders);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error while traversing folder: {ex.Message}");
}
}
public List<string> GetFilteringTopDirFolders(string folderPath)
{
return Directory
.GetDirectories(folderPath, "*", SearchOption.TopDirectoryOnly)
.Where(dir => ShouldIncludeDir(Path.GetFileName(dir)))
.ToList();
}
public bool ShouldIncludeDir(string folderName)
{
return !GetExcludeDirFlag(folderName) || GetIncludeDirFlag(folderName);
}
private bool GetExcludeDirFlag(string folderName)
{
return _config.ExcludeEqualDirs.Any(folder => folderName.Equals(folder))
|| _config.ExcludeStartDirs.Any(folder => folderName.StartsWith(folder))
|| _config.ExcludeEndDirs.Any(folder => folderName.EndsWith(folder));
}
private bool GetIncludeDirFlag(string folderName)
{
return _config.IncludeEqualDirs.Any(folder => folderName.Equals(folder))
|| _config.IncludeStartDirs.Any(folder => folderName.StartsWith(folder))
|| _config.IncludeEndDirs.Any(folder => folderName.EndsWith(folder));
}
}
Code2Md\Code2md\Code2md.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="3.1.0" />
<PackageReference Include="YamlDotNet" Version="15.1.2" />
</ItemGroup>
</Project>
Code2Md\run.bat
set "scriptPath=%cd%"
dotnet run --project ./Code2md/Code2md.csproj -- "%scriptPath%"
@REM set "scriptPath=D:\Jobs\LongforceJobApp"
@REM set "scriptPath=D:\Jobs\LongforceAutomation"
@REM dotnet run --project ./CopyFile/CopyFile.csproj -- "%scriptPath%"
dotnet publish .\Code2md\Code2md.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true /p:DebugType=None -o .\Publish\Code2md
Code2Md\publish.bat
@REM dotnet publish .\Code2md\Code2md.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true -o .\Publish\Code2md\V2.0.0
dotnet publish .\Code2md\Code2md.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true /p:DebugType=None -o .\Publish\Code2md
Code2Md\CopyFile\Program.cs
using System.Collections.Concurrent;
using System.Diagnostics;
public class Program
{
private static string SourceDirectory = string.Empty;
private static string DstFolderPath = string.Empty;
private static string SourceDirectoryBakPath = string.Empty;
private static string DirectorySuffix = string.Empty;
private static readonly DateTime Now = DateTime.Now;
private static readonly List<string> ExcludedEqualDirectories = new List<string>
{
"bin",
"obj",
"npm_modules",
".git",
"Publish",
};
private static readonly BlockingCollection<CopyFileTask> BackupCollection =
new BlockingCollection<CopyFileTask>();
private static readonly ConcurrentDictionary<string, object> DirectoryLocks =
new ConcurrentDictionary<string, object>();
private static readonly CancellationTokenSource CancellationTokenSource =
new CancellationTokenSource();
static void Main(string[] args)
{
try
{
Console.WriteLine("正在扫描文件...");
System.Console.WriteLine("输入文件夹后缀:");
DirectorySuffix = System.Console.ReadLine() ?? string.Empty;
if (args.Length == 0)
{
System.Console.WriteLine("请传入文件夹路径");
return;
}
SourceDirectory = args[0];
if (!Directory.Exists(SourceDirectory))
{
Console.WriteLine($"错误: 源目录 {SourceDirectory} 不存在。");
return;
}
System.Console.WriteLine("请输入目标文件夹:");
DstFolderPath = System.Console.ReadLine() ?? string.Empty;
if (DstFolderPath == string.Empty)
return;
SourceDirectoryBakPath =
Path.GetFileName(SourceDirectory) + $"_{Now:yyyyMMdd_HHmmss}_{DirectorySuffix}";
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var producerTask = Task.Run(() =>
{
try
{
var options = new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount * 2,
};
Parallel.ForEach(
Directory.EnumerateDirectories(SourceDirectory),
options,
(dirPath) =>
{
ScanDirectory(dirPath);
}
);
GetFiles(SourceDirectory);
}
finally
{
BackupCollection.CompleteAdding();
}
});
Console.WriteLine("扫描已启动,开始并行处理文件...");
const int maxThreads = 8;
var backupTasks = new Task[maxThreads];
for (int i = 0; i < maxThreads; i++)
{
backupTasks[i] = Task.Run(() => CodeBackup(CancellationTokenSource.Token));
}
Task.WaitAll(backupTasks);
stopwatch.Stop();
Console.WriteLine($"处理完成,共耗时 {stopwatch.Elapsed.TotalSeconds} s");
}
catch (Exception ex)
{
Console.WriteLine($"\n发生致命错误: {ex.Message}");
}
finally
{
CancellationTokenSource.Cancel();
}
Console.WriteLine("============备份完成============");
}
private static bool FilterFolder(string dirPath)
{
var dirName = Path.GetFileName(dirPath);
var excludedSet = new HashSet<string>(
ExcludedEqualDirectories,
StringComparer.OrdinalIgnoreCase
);
return !excludedSet.Contains(dirName);
}
private static void ScanDirectory(string currentPath)
{
if (!FilterFolder(currentPath))
return;
try
{
GetFiles(currentPath);
var options = new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount * 2,
};
Parallel.ForEach(
Directory.EnumerateDirectories(currentPath),
options,
(subDirectory) =>
{
ScanDirectory(subDirectory); // 递归调用
}
);
}
catch (IOException ex)
{
Console.WriteLine($"IOException ex: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{ /* 忽略无权限目录 */
System.Console.WriteLine($"UnauthorizedAccessException ex: {ex.Message} ");
}
catch (Exception ex)
{
Console.WriteLine($"\n扫描目录时出错 ({currentPath}): {ex.Message}");
}
}
private static void GetFiles(string sourcePath)
{
var files = Directory.GetFiles(sourcePath, "*", SearchOption.TopDirectoryOnly);
foreach (string filePath in files)
{
string relativePath = Path.GetRelativePath(SourceDirectory, filePath);
string dstCodePath = Path.Combine(DstFolderPath, SourceDirectoryBakPath, relativePath);
EnsureDirectoryExists(Path.GetDirectoryName(dstCodePath)!);
var task = new CopyFileTask { CodePath = filePath, DstCodePath = dstCodePath };
BackupCollection.Add(task);
}
}
private static void CodeBackup(CancellationToken cancellationToken)
{
try
{
foreach (var copyFileTask in BackupCollection.GetConsumingEnumerable(cancellationToken))
{
try
{
CopyFile(copyFileTask);
}
catch (Exception ex)
{
Console.WriteLine($"\n处理文件时出错 ({copyFileTask.CodePath}): {ex.Message}");
}
}
}
catch (OperationCanceledException)
{
System.Console.WriteLine("\n文件处理已取消。");
}
}
private static void CopyFile(CopyFileTask code2mdTask, int maxRetries = 3)
{
int retries = 0;
while (true)
{
try
{
string codePath = code2mdTask.CodePath;
string dstCodePath = code2mdTask.DstCodePath;
File.Copy(codePath, dstCodePath, false);
System.Console.WriteLine(codePath + "=>" + dstCodePath);
if (!File.Exists(dstCodePath))
{
throw new IOException("文件复制后不存在于目标位置");
}
break;
}
catch (Exception ex)
{
retries++;
if (retries > maxRetries)
{
Console.WriteLine($"文件移动失败 ({code2mdTask.CodePath} : {ex.Message}");
throw;
}
Thread.Sleep(500 * retries);
}
}
}
private static void EnsureDirectoryExists(string directoryPath)
{
if (Directory.Exists(directoryPath))
return;
object dirLock = DirectoryLocks.GetOrAdd(directoryPath, _ => new object());
if (!Directory.Exists(directoryPath))
{
if (Directory.Exists(directoryPath))
return;
lock (dirLock)
{
Directory.CreateDirectory(directoryPath);
}
}
}
}
public class CopyFileTask
{
public required string CodePath { get; set; }
public required string DstCodePath { get; set; }
}
Code2Md\Code2md\Config.cs
using Microsoft.Extensions.Configuration;
public class Config
{
private readonly string _srcPath;
private readonly string _code2mdConfigFolder;
private readonly string _code2mdConfigPath;
private IConfigurationRoot _configurationRoot = null!;
public List<string> ExcludeEqualDirs { get; set; } = null!;
public List<string> ExcludeStartDirs { get; set; } = null!;
public List<string> ExcludeEndDirs { get; set; } = null!;
public List<string> IncludeEqualDirs { get; set; } = null!;
public List<string> IncludeStartDirs { get; set; } = null!;
public List<string> IncludeEndDirs { get; set; } = null!;
public List<string> ExcludeEqualFiles { get; set; } = null!;
public List<string> ExcludeStartFiles { get; set; } = null!;
public List<string> ExcludeEndFiles { get; set; } = null!;
public List<string> IncludeEqualFiles { get; set; } = null!;
public List<string> IncludeStartFiles { get; set; } = null!;
public List<string> IncludeEndFiles { get; set; } = null!;
public List<string> CodeToMarkDownExtension { get; set; } = null!;
public Dictionary<string, string> CodeSuffixMap { get; set; } = null!;
public Config(string srcPath)
{
_srcPath = srcPath;
_code2mdConfigFolder = Path.Combine(_srcPath, ".vscode");
_code2mdConfigPath = Path.Combine(_srcPath, ".vscode", "code2md.yaml");
}
public bool CheckCode2mdConfig()
{
if (!Directory.Exists(_code2mdConfigFolder))
{
Directory.CreateDirectory(_code2mdConfigFolder);
}
if (!Path.Exists(_code2mdConfigPath))
{
Console.WriteLine($"无配置文件 : {_code2mdConfigPath} , 已生成配置文件,然后返回");
File.WriteAllText(
_code2mdConfigPath,
GenerateCode2mdConfigYaml(),
System.Text.Encoding.UTF8
);
return false;
}
return true;
}
public void LoadConfig()
{
_configurationRoot = new ConfigurationBuilder()
.SetBasePath(_srcPath)
.AddYamlFile(_code2mdConfigPath, optional: true, reloadOnChange: true)
.Build();
ExcludeEqualDirs = GetConfigList("ExcludeEqualDirs");
ExcludeStartDirs = GetConfigList("ExcludeStartDirs");
ExcludeEndDirs = GetConfigList("ExcludeEndDirs");
IncludeEqualDirs = GetConfigList("IncludeEqualDirs");
IncludeStartDirs = GetConfigList("IncludeStartDirs");
IncludeEndDirs = GetConfigList("IncludeEndDirs");
ExcludeEqualFiles = GetConfigList("ExcludeEqualFiles");
ExcludeStartFiles = GetConfigList("ExcludeStartFiles");
ExcludeEndFiles = GetConfigList("ExcludeEndFiles");
IncludeEqualFiles = GetConfigList("IncludeEqualFiles");
IncludeStartFiles = GetConfigList("IncludeStartFiles");
IncludeEndFiles = GetConfigList("IncludeEndFiles");
CodeToMarkDownExtension = GetConfigList("CodeToMarkDownExtension");
CodeSuffixMap = GetConfigMap("CodeSuffixDic");
}
public bool GetExcludeDirFlag(string folderName)
{
return ExcludeEqualDirs.Any(folder => folderName.Equals(folder))
|| ExcludeStartDirs.Any(folder => folderName.StartsWith(folder))
|| ExcludeEndDirs.Any(folder => folderName.EndsWith(folder));
}
public bool GetIncludeDirFlag(string folderName)
{
return IncludeEqualDirs.Any(folder => folderName.Equals(folder))
|| IncludeStartDirs.Any(folder => folderName.StartsWith(folder))
|| IncludeEndDirs.Any(folder => folderName.EndsWith(folder));
}
public bool GetExcludeFileFlag(string fileName)
{
return ExcludeEqualFiles.Any(folder => fileName.Equals(folder))
|| ExcludeStartFiles.Any(folder => fileName.StartsWith(folder))
|| ExcludeEndFiles.Any(folder => fileName.EndsWith(folder));
}
public bool GetIncludeFileFlag(string fileName)
{
return IncludeEqualFiles.Any(folder => fileName.Equals(folder))
|| IncludeStartFiles.Any(folder => fileName.StartsWith(folder))
|| IncludeEndFiles.Any(folder => fileName.EndsWith(folder));
}
private List<string> GetConfigList(string sectionName)
{
return _configurationRoot
.GetSection(sectionName)
.GetChildren()
.Select(child => child.Value ?? string.Empty)
.ToList();
}
private Dictionary<string, string> GetConfigMap(string sectionName)
{
return _configurationRoot
.GetSection(sectionName)
.GetChildren()
.ToDictionary(e => e.Key, e => e.Value ?? string.Empty);
}
public static string GenerateCode2mdConfigYaml()
{
return @"ExcludeEqualDirs:
- ""res""
- ""docs""
- ""note""
- ""config""
- ""Publish""
- "".idea""
- "".vs""
- "".vscode""
- "".git""
- ""zz_pro""
- ""zz_res""
- ""zz_zz""
- ""bin""
- ""zz_config""
- ""zz_note""
- ""zz_cache""
- ""node_modules""
- ""obj""
- ""zz_zz_publish""
- ""zz_zz_pro""
- ""Migrations""
- ""log""
- ""logs""
ExcludeStartDirs: []
ExcludeEndDirs: []
IncludeEqualDirs: []
IncludeStartDirs: []
IncludeEndDirs: []
ExcludeEqualFiles:
- ""zz.bat""
- ""AssemblyInfo.cs""
- ""out.txt""
ExcludeStartFiles:
- ""temp""
ExcludeEndFiles:
- "".xlsx""
- "".doc""
- "".docx""
- "".ppt""
- "".pptx""
- "".pdf""
- "".png""
- "".jpg""
- "".jpeg""
- "".gif""
- "".mp4""
- "".mp3""
IncludeEqualFiles: []
IncludeStartFiles: []
IncludeEndFiles: []
CodeSuffixDic:
"".cs"": ""cs""
"".csproj"": ""csproj""
"".http"": ""http""
"".bat"": ""sh""
"".ps1"": ""sh""
"".py"": ""py""
"".js"": ""js""
"".ts"": ""ts""
"".cpp"": ""cpp""
"".c"": ""c""
"".json"": ""json""
"".sln"": ""xml""
"".config"": ""config""
"".xaml"": ""xml""
CodeToMarkDownExtension:
- "".txt""
- "".log""
- "".ini""
- "".conf""
- "".cfg""
- "".toml""
- "".yml""
- "".yaml""
- "".json""
- "".xml""
- "".properties""
- "".c""
- "".cpp""
- "".h""
- "".hpp""
- "".cs""
- "".java""
- "".js""
- "".ts""
- "".py""
- "".rb""
- "".php""
- "".go""
- "".rs""
- "".swift""
- "".m""
- "".mm""
- "".scala""
- "".groovy""
- "".pl""
- "".pm""
- "".sh""
- "".bat""
- "".cmd""
- "".ps1""
- "".html""
- "".htm""
- "".css""
- "".markdown""
- "".rst""
- "".sql""
- "".graphql""
- "".sln""
- "".csproj""
- "".vbproj""
- "".fsproj""
- "".gradle""
- "".pom.xml""
- "".gemspec""
- "".npmrc""
- "".yarnrc""
- "".package.json""
- "".cabal""
- "".opam""
- "".pubspec.yaml""
- "".rst""
- "".tex""
- "".gitignore""
- "".editorconfig""
- "".dockerfile""
- "".env""
- "".class""
- "".asm""
- "".ada""
- "".pas""
- "".bas""
- "".xaml""
- "".axaml""
- "".manifest""
- "".config""
- "".qwenignore""";
}
}
Code2Md\build.bat
dotnet build
Code2Md\code2md.bat
set "scriptPath=%cd%"
D:\Code2Md\Publish\Code2md\V2.0.0\Code2md.exe "%scriptPath%"
Code2Md\backup.bat
set "scriptPath=%cd%"
D:\Code2Md\CopyFile\bin\Debug\net9.0\CopyFile.exe "%scriptPath%"
Code2Md\Code2Md.sln
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Code2md", "Code2md\Code2md.csproj", "{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CopyFile", "CopyFile\CopyFile.csproj", "{EBB30421-8AA6-4544-BA5F-47E159D249EA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Debug|x64.ActiveCfg = Debug|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Debug|x64.Build.0 = Debug|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Debug|x86.ActiveCfg = Debug|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Debug|x86.Build.0 = Debug|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Release|Any CPU.Build.0 = Release|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Release|x64.ActiveCfg = Release|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Release|x64.Build.0 = Release|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Release|x86.ActiveCfg = Release|Any CPU
{0E7945A4-11DF-3F2D-5C0F-DA17206D17C9}.Release|x86.Build.0 = Release|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Debug|x64.ActiveCfg = Debug|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Debug|x64.Build.0 = Debug|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Debug|x86.ActiveCfg = Debug|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Debug|x86.Build.0 = Debug|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Release|Any CPU.Build.0 = Release|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Release|x64.ActiveCfg = Release|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Release|x64.Build.0 = Release|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Release|x86.ActiveCfg = Release|Any CPU
{EBB30421-8AA6-4544-BA5F-47E159D249EA}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {952E0F08-889A-4D42-8C09-9A6CE65269E2}
EndGlobalSection
EndGlobal
Code2Md\CopyFile\CopyFile.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>