调整代码
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
#if false
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.ExtensibleStorage;
|
||||
using OpenMcdf;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using System.Diagnostics;
|
||||
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.ExtensibleStorage;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using OpenMcdf;
|
||||
using System.Windows;
|
||||
|
||||
namespace ShrlAlgoToolkit.RevitCore.Assists;
|
||||
@@ -27,7 +27,7 @@ public class PublishAssist
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
if(File.Exists(filePath))
|
||||
{
|
||||
var info = new FileInfo(filePath);
|
||||
info.IsReadOnly = readOnly;
|
||||
@@ -36,16 +36,44 @@ public class PublishAssist
|
||||
{
|
||||
Debug.WriteLine("文件不存在。");
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
} catch(UnauthorizedAccessException)
|
||||
{
|
||||
Debug.WriteLine("无权限修改文件属性。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
} catch(Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断文件是否被加密
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="tag"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsEncrypted(string filePath, string tag = "VmVyc2lvbiAxLjAgU1pNZWRpRGF0YQ==")
|
||||
{
|
||||
// 关键:用写入时相同的编码(通常 UTF-8 或 ASCII)
|
||||
var tagBytes = Encoding.UTF8.GetBytes(tag); // 或 Encoding.ASCII
|
||||
|
||||
var data = File.ReadAllBytes(filePath);
|
||||
// 检查开头和结尾是否匹配
|
||||
var startMatch = data.Length >= tagBytes.Length && ArrayEquals(data, 0, tagBytes, 0, tagBytes.Length);
|
||||
var endMatch = data.Length >= tagBytes.Length * 2 &&
|
||||
ArrayEquals(data, data.Length - tagBytes.Length, tagBytes, 0, tagBytes.Length);
|
||||
return startMatch && endMatch;
|
||||
}
|
||||
|
||||
static bool ArrayEquals(byte[] a, int aStart, byte[] b, int bStart, int length)
|
||||
{
|
||||
for(var i = 0; i < length; i++)
|
||||
{
|
||||
if(a[aStart + i] != b[bStart + i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置文件为只读
|
||||
/// </summary>
|
||||
@@ -54,7 +82,7 @@ public class PublishAssist
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
if(File.Exists(filePath))
|
||||
{
|
||||
var info = new FileInfo(filePath);
|
||||
File.SetAttributes(filePath, FileAttributes.Hidden | FileAttributes.System | FileAttributes.ReadOnly);
|
||||
@@ -63,18 +91,16 @@ public class PublishAssist
|
||||
{
|
||||
Debug.WriteLine("文件不存在。");
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
} catch(UnauthorizedAccessException)
|
||||
{
|
||||
Debug.WriteLine("无权限修改文件属性。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
} catch(Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
//需要与addin文件里的GUID保持一致
|
||||
private static readonly Guid SchemaGuid = new Guid("A519E82B-911C-4CA5-9BC5-ED509B2055D2");
|
||||
|
||||
@@ -84,77 +110,135 @@ public class PublishAssist
|
||||
public static void StoreSignatureMap(Document doc, IDictionary<string, byte[]> signatureMap)
|
||||
{
|
||||
ProjectInfo projectInfo = doc.ProjectInformation;
|
||||
if (projectInfo == null) return;
|
||||
if(projectInfo == null)
|
||||
return;
|
||||
|
||||
Schema schema = GetOrCreateSchema();
|
||||
Entity entity = new Entity(schema);
|
||||
IDictionary<int, string> imageMap = new Dictionary<int, string>();
|
||||
Entity entity = projectInfo.GetEntity(schema);
|
||||
if(entity == null || !entity.IsValid())
|
||||
{
|
||||
entity = new Entity(schema); // 如果没有,才新建
|
||||
}
|
||||
try
|
||||
{
|
||||
IDictionary<string, string> stringMap = signatureMap
|
||||
.ToDictionary(kvp => kvp.Key, kvp => Convert.ToBase64String(kvp.Value));
|
||||
|
||||
entity.Set<IDictionary<string, string>>("SignatureMap", stringMap);
|
||||
entity.Set("SignatureMap", stringMap);
|
||||
|
||||
projectInfo.SetEntity(entity);
|
||||
}
|
||||
catch (Exception ex)
|
||||
} catch(Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取图片字节数据列表 (Revit 2020 兼容版, 使用 Base64 解码)
|
||||
/// 读取签章图片字节数据列表 (使用 Base64 解码)
|
||||
/// </summary>
|
||||
public static IDictionary<string, byte[]> RetrieveSignatureMap(Document doc)
|
||||
{
|
||||
ProjectInfo projectInfo = doc.ProjectInformation;
|
||||
var emptyDict = new Dictionary<string, byte[]>();
|
||||
if (projectInfo == null) return emptyDict;
|
||||
if(projectInfo == null)
|
||||
return emptyDict;
|
||||
|
||||
Schema schema = Schema.Lookup(SchemaGuid);
|
||||
if (schema == null) return emptyDict;
|
||||
if(schema == null)
|
||||
return emptyDict;
|
||||
|
||||
Entity entity = projectInfo.GetEntity(schema);
|
||||
if (entity == null || !entity.IsValid()) return emptyDict;
|
||||
if(entity == null || !entity.IsValid())
|
||||
return emptyDict;
|
||||
IDictionary<string, string> retrievedMap = entity.Get<IDictionary<string, string>>("SignatureMap");
|
||||
|
||||
if (retrievedMap == null) return emptyDict;
|
||||
if(retrievedMap == null)
|
||||
return emptyDict;
|
||||
|
||||
return retrievedMap.ToDictionary(kvp => kvp.Key, kvp => Convert.FromBase64String(kvp.Value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建数据模式 (Revit 2020 兼容版)
|
||||
/// 存储基本信息数据列表
|
||||
/// </summary>
|
||||
public static void StoreSignatureCommonMap(Document doc, IDictionary<string, string> signatureCommonMap)
|
||||
{
|
||||
ProjectInfo projectInfo = doc.ProjectInformation;
|
||||
if(projectInfo == null)
|
||||
return;
|
||||
|
||||
Schema schema = GetOrCreateSchema();
|
||||
//每个元素只有一个实体
|
||||
Entity entity = projectInfo.GetEntity(schema);
|
||||
if(entity == null || !entity.IsValid())
|
||||
{
|
||||
entity = new Entity(schema); // 如果没有,才新建
|
||||
}
|
||||
try
|
||||
{
|
||||
entity.Set("SignatureCommonMap", signatureCommonMap);
|
||||
|
||||
projectInfo.SetEntity(entity);
|
||||
} catch(Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取基本信息数据列表
|
||||
/// </summary>
|
||||
public static IDictionary<string, string> RetrieveSignatureCommonMap(Document doc)
|
||||
{
|
||||
ProjectInfo projectInfo = doc.ProjectInformation;
|
||||
var emptyDict = new Dictionary<string, string>();
|
||||
if(projectInfo == null)
|
||||
return emptyDict;
|
||||
|
||||
Schema schema = Schema.Lookup(SchemaGuid);
|
||||
if(schema == null)
|
||||
return emptyDict;
|
||||
|
||||
Entity entity = projectInfo.GetEntity(schema);
|
||||
if(entity == null || !entity.IsValid())
|
||||
return emptyDict;
|
||||
IDictionary<string, string> retrievedMap = entity.Get<IDictionary<string, string>>("SignatureCommonMap");
|
||||
|
||||
if(retrievedMap == null)
|
||||
return emptyDict;
|
||||
|
||||
return retrievedMap.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建数据模式
|
||||
/// </summary>
|
||||
private static Schema GetOrCreateSchema()
|
||||
{
|
||||
Schema schema = Schema.Lookup(SchemaGuid);
|
||||
if (schema == null)
|
||||
if(schema != null)
|
||||
return schema;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
SchemaBuilder schemaBuilder = new SchemaBuilder(SchemaGuid);
|
||||
schemaBuilder.SetReadAccessLevel(AccessLevel.Application);
|
||||
schemaBuilder.SetWriteAccessLevel(AccessLevel.Application);
|
||||
schemaBuilder.SetVendorId("SZMC");
|
||||
schemaBuilder.SetApplicationGUID(SchemaGuid);
|
||||
schemaBuilder.SetSchemaName("SignatureStorage");
|
||||
|
||||
schemaBuilder.AddMapField("SignatureMap", typeof(string), typeof(string));
|
||||
|
||||
schema = schemaBuilder.Finish();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message, "创建schema错误");
|
||||
}
|
||||
SchemaBuilder schemaBuilder = new SchemaBuilder(SchemaGuid);
|
||||
schemaBuilder.SetReadAccessLevel(AccessLevel.Application);
|
||||
schemaBuilder.SetWriteAccessLevel(AccessLevel.Application);
|
||||
schemaBuilder.SetVendorId("SZMC");
|
||||
schemaBuilder.SetApplicationGUID(SchemaGuid);
|
||||
schemaBuilder.SetSchemaName("SignatureStorage");
|
||||
// 添加 Map 字段用来存储图片字节数据列表
|
||||
schemaBuilder.AddMapField("SignatureMap", typeof(string), typeof(string));
|
||||
// 添加 Map 字段用来存储基本信息数据列表
|
||||
schemaBuilder.AddMapField("SignatureCommonMap", typeof(string), typeof(string));
|
||||
|
||||
schema = schemaBuilder.Finish();
|
||||
} catch(Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message, "创建schema错误");
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
#region ExtensionsStorage
|
||||
//private const string SchemaGuid = "{FBC67C54-781F-4D0A-B31B-8F54707889E0}";
|
||||
///// <summary>
|
||||
@@ -172,12 +256,12 @@ public class PublishAssist
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region PreviewSettings
|
||||
/// <summary>
|
||||
/// 完全替换缩略图
|
||||
/// </summary>
|
||||
/// 完全替换缩略图
|
||||
/// </summary>
|
||||
/// <param name="rvtFilePath"></param>
|
||||
/// <param name="imgPath"></param>
|
||||
internal static void ReplaceThumb(string rvtFilePath, Bitmap bmp)
|
||||
@@ -188,7 +272,7 @@ public class PublishAssist
|
||||
CFStorage root = cf.RootStorage;
|
||||
|
||||
// 更新 Windows 预览
|
||||
if (root.TryGetStream("RevitPreview4.0", out var previewStream))
|
||||
if(root.TryGetStream("RevitPreview4.0", out var previewStream))
|
||||
{
|
||||
using var outMs = new MemoryStream();
|
||||
bmp.Save(outMs, ImageFormat.Png);
|
||||
@@ -196,7 +280,7 @@ public class PublishAssist
|
||||
}
|
||||
|
||||
// 更新 Revit 预览
|
||||
if (root.TryGetStream("BasicFileInfo", out var basicFileInfo))
|
||||
if(root.TryGetStream("BasicFileInfo", out var basicFileInfo))
|
||||
{
|
||||
// 读取现有数据
|
||||
byte[] data = basicFileInfo.GetData();
|
||||
@@ -204,15 +288,15 @@ public class PublishAssist
|
||||
// 基本文件信息头部大小(版本等信息)
|
||||
const int HEADER_SIZE = 0x2C8;
|
||||
|
||||
if (data.Length > HEADER_SIZE)
|
||||
if(data.Length > HEADER_SIZE)
|
||||
{
|
||||
// 转换图片为字节数组
|
||||
using (var ms = new MemoryStream())
|
||||
using(var ms = new MemoryStream())
|
||||
{
|
||||
// 转换为24位色
|
||||
using (var temp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format24bppRgb))
|
||||
using(var temp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format24bppRgb))
|
||||
{
|
||||
using (var g = Graphics.FromImage(temp))
|
||||
using(var g = Graphics.FromImage(temp))
|
||||
{
|
||||
g.DrawImage(bmp, 0, 0);
|
||||
}
|
||||
@@ -254,7 +338,7 @@ public class PublishAssist
|
||||
// 创建画布
|
||||
Bitmap result = new Bitmap(thumbnail.Width, thumbnail.Height);
|
||||
|
||||
using (Graphics graphics = Graphics.FromImage(result))
|
||||
using(Graphics graphics = Graphics.FromImage(result))
|
||||
{
|
||||
// 绘制缩略图
|
||||
graphics.DrawImage(thumbnail, 0, 0);
|
||||
@@ -273,8 +357,7 @@ public class PublishAssist
|
||||
resizedOverlay,
|
||||
new System.Drawing.Rectangle(x, y, iconSize, iconSize),
|
||||
new System.Drawing.Rectangle(0, 0, overlay.Width, overlay.Height),
|
||||
GraphicsUnit.Pixel
|
||||
);
|
||||
GraphicsUnit.Pixel);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -294,13 +377,13 @@ public class PublishAssist
|
||||
CFStorage root = cf.RootStorage;
|
||||
|
||||
// 检查是否存在 "RevitPreview4.0" 流
|
||||
if (!root.TryGetStream("RevitPreview4.0", out var previewStream))
|
||||
if(!root.TryGetStream("RevitPreview4.0", out var previewStream))
|
||||
{
|
||||
Debug.WriteLine("未找到 RevitPreview4.0 流。");
|
||||
return;
|
||||
}
|
||||
// 在图像上绘制半透明文字水印
|
||||
if (!string.IsNullOrEmpty(watermark))
|
||||
if(!string.IsNullOrEmpty(watermark))
|
||||
{
|
||||
using var g = Graphics.FromImage(bmp);
|
||||
var font = new Font("微软雅黑", 20, System.Drawing.FontStyle.Bold);
|
||||
@@ -363,6 +446,7 @@ public class PublishAssist
|
||||
0cMfedRgHigwi+T818aFnC8qPzTMqCMQyxRTYxEC43OB9VcPyzo1yA==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
""";
|
||||
|
||||
private static AsymmetricKeyParameter GetPublicKey()
|
||||
{
|
||||
using var reader = new StringReader(PublicKeyPem);
|
||||
@@ -398,7 +482,9 @@ public class PublishAssist
|
||||
rsaEngine.Init(false, privateKey);
|
||||
return rsaEngine.ProcessBlock(encryptedData, 0, encryptedData.Length);
|
||||
}
|
||||
|
||||
private static readonly string EncryptFileName = ".hashes.enc";
|
||||
|
||||
/// <summary>
|
||||
/// 获取相对路径
|
||||
/// </summary>
|
||||
@@ -408,7 +494,8 @@ public class PublishAssist
|
||||
private static string GetRelativePath(string relativeTo, string path)
|
||||
{
|
||||
// 确保路径以目录分隔符结尾(对于目录路径)
|
||||
string from = Path.GetFullPath(relativeTo).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||
string from = Path.GetFullPath(relativeTo).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) +
|
||||
Path.DirectorySeparatorChar;
|
||||
string to = Path.GetFullPath(path);
|
||||
|
||||
Uri fromUri = new Uri(from);
|
||||
@@ -431,7 +518,7 @@ public class PublishAssist
|
||||
using var fs = new FileStream(encFilePath, FileMode.Create, FileAccess.Write);
|
||||
using var bw = new BinaryWriter(fs);
|
||||
|
||||
foreach (var file in files)
|
||||
foreach(var file in files)
|
||||
{
|
||||
//var fileName = Path.GetFileName(file);
|
||||
var fileName = GetRelativePath(directoryPath, file);
|
||||
@@ -455,7 +542,7 @@ public class PublishAssist
|
||||
var encFilePath = Path.Combine(directoryPath, EncryptFileName);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (!File.Exists(encFilePath))
|
||||
if(!File.Exists(encFilePath))
|
||||
{
|
||||
sb.AppendLine("验证文件未找到。");
|
||||
return sb;
|
||||
@@ -465,21 +552,18 @@ public class PublishAssist
|
||||
{
|
||||
//转成相对路径
|
||||
allFiles = Directory.GetFiles(directoryPath, "*.rvt", SearchOption.AllDirectories)
|
||||
.ToDictionary(
|
||||
file => GetRelativePath(directoryPath, file),
|
||||
file => file,
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
.ToDictionary(
|
||||
file => GetRelativePath(directoryPath, file),
|
||||
file => file,
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
} catch(Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message, "验证出错!", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return sb;
|
||||
}
|
||||
using var fs = new FileStream(encFilePath, FileMode.Open, FileAccess.Read);
|
||||
using var br = new BinaryReader(fs);
|
||||
while (fs.Position < fs.Length)
|
||||
while(fs.Position < fs.Length)
|
||||
{
|
||||
var nameLen = br.ReadInt32();
|
||||
//if (nameLen <= 0 || nameLen > 256) // 假设文件名长度不超过256字节
|
||||
@@ -493,7 +577,7 @@ public class PublishAssist
|
||||
var encLen = br.ReadInt32();
|
||||
var encrypted = br.ReadBytes(encLen);
|
||||
|
||||
if (!allFiles.TryGetValue(fileName, out var actualFilePath))
|
||||
if(!allFiles.TryGetValue(fileName, out var actualFilePath))
|
||||
{
|
||||
sb.AppendLine($"{fileName} 未找到");
|
||||
continue;
|
||||
@@ -505,16 +589,14 @@ public class PublishAssist
|
||||
|
||||
var currentHash = ComputeFileHash(actualFilePath);
|
||||
bool match = expectedName == fileName && currentHash.SequenceEqual(expectedHash);
|
||||
if (!match)
|
||||
if(!match)
|
||||
{
|
||||
hasModified = true;
|
||||
sb.AppendLine($"{fileName}");
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user