看起来应该很简单,但基本上我有两个类库配置。一个是普通的 .NET 4.0 配置,另一个配置为注册 COM Interop,并另外定义了一个编译符号,以便我可以使用预处理器指令解决一些与 COM 相关的问题。
问题是,部署时,这两个 DLL 必须位于同一文件夹中,调用应用程序才能使用它们(根据设计,对此无能为力)。将每个配置编译到各自的bin/子文件夹时,一切都运行良好,包括使用不同的强名称密钥对两个配置进行签名,以便 GAC 看到两个不同的程序集,即使具有相同的名称和版本。
但是将它们放在同一个文件夹中需要重命名,这就是问题所在。
如果在 Visual Studio 中我可以有条件地在“应用程序”选项卡中设置“程序集名称”属性,那就太棒了,但看起来该选项卡是项目范围的,而不是配置范围的。除此之外,有没有什么方法可以指定不同的文件名,这样就不会导致运行时问题,更不用说开发人员的理智问题了?我的目标是能够向 .NET 客户端提供 COM 不支持的功能,同时仍然与 COM 兼容。我非常不希望将所有内容复制并粘贴到另一个只有不同程序集名称的项目中......
我的 C# 代码有一个struct要导出到 COM 的代码。该结构的属性带有奇怪的名称,这些名称甚至在 VB6 中都不是有效语法,因此无法访问它们。
有什么方法可以让它们以正常、可用的名称导出吗?我是否缺少某个属性或其他内容?
COM/VB6 中名称的格式为:
<original_name>k__BackingField
Run Code Online (Sandbox Code Playgroud)
其中只有original_name部分位于我的 C# 代码中。
我只能在 VB6 对象浏览器中看到这些疯狂的属性名称,Intellisense 不会显示它。
这是正在构建的(稍微清理过的)代码:
[Guid("....")]
[ComVisible(true)]
public struct MyStruct
{
public string StringA { get; set; }
public string StringB { get; set; }
public MyStruct(string a, string b)
{
StringA = a;
StringB = b;
}
... // some other methods, no fields or properties
}
Run Code Online (Sandbox Code Playgroud)
为了更好地衡量,这里是生成的 IDL:
typedef [uuid(....), version(1.0), custom(xxxx, MyNamespace.MyStruct)]
struct tagMyStruct {
LPSTR <StringA>k__BackingField;
LPSTR <StringB>k__BackingField; …Run Code Online (Sandbox Code Playgroud) 我被告知在C#中没有可选参数这样的东西.但是您可以使用重载功能并使用默认值输入变量,例如:
void Person(string name, int age)
void Person(string name)
Run Code Online (Sandbox Code Playgroud)
和
void Person(string name, int age = 30)
Run Code Online (Sandbox Code Playgroud)
我的问题是,当从VB6调用C#组件时,重载方法往往会将名称更改为例如"Person(字符串名称),Person _1(字符串名称,int age)"等,并且当使用时不能使用具有默认值的变量"出"变量.
但是怎么样
void Person(string name, [Optional] int age)
Run Code Online (Sandbox Code Playgroud)
??
有人可以向我解释这项工作是如何使用它来模拟VB6中的可选变量吗?
当.net程序集注册COM Interop时,注册表中有一个指向可执行文件的CodeBase项.
我的问题是:CodeBase密钥是特定于.NET的东西,还是这是一个通用的COM东西,所有注册的组件都应该有?
在尝试将现有的32位应用程序转换为64位时,我遇到了使一些COM Interop代码正常工作的问题.代码正在使用从各种Windows SDK标头/ IDL文件翻译的托管代码访问结构化存储API.
当我尝试调用时,代码失败IPropertyStorage.ReadMultiple()了STG_E_INVALIDPARAMETER.以前的互操作调用,StgOpenStorageEx和IPropertySetStorage.Open,似乎工作正常.MSDN声称这个错误意味着我的PROPSPEC参数有问题,但是当编译为32位应用程序时,相同的参数值工作正常,并且我得到的值是指定属性的正确字符串值.
以下是我认为的相关内容:
// PropertySpecKind enumeration.
public enum PropertySpecKind : uint
{
Lpwstr = 0,
PropId = 1
}
// PropertySpec structure:
[StructLayout(LayoutKind.Explicit)]
public struct PropertySpec
{
[FieldOffset(0)] public PropertySpecKind kind;
[FieldOffset(4)] public uint propertyId;
[FieldOffset(4)] public IntPtr name;
}
// PropertyVariant Structure:
[StructLayout(LayoutKind.Explicit)]
public struct PropertyVariant
{
[FieldOffset(0)] public Vartype vt;
[FieldOffset(8)] public IntPtr pointerValue;
}
// IPropertyStorage interface
[ComImport]
[Guid("00000138-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPropertyStorage
{
int ReadMultiple( …Run Code Online (Sandbox Code Playgroud) 我试图从C#应用程序打开一个Word文档,插入一个宏,运行它,然后关闭.我遇到的问题是
编译错误:参数不是可选的
我一直在看这篇文章,但我没有回复任何东西.没看到我在这里缺少什么.
这是调试器:
这是C#代码:
Microsoft.Office.Interop.Word.Application newApp = new Microsoft.Office.Interop.Word.Application();
newApp.Visible = true;
object Unknown = Type.Missing;
var Source = fileName;
var doc = newApp.Documents.Open(Source);
var project = doc.VBProject;
var module = project.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
var macro = "Public Sub DoKbTest()\r\n" +
"MsgBox 'Hello'\r\n" +
"End Sub\r\n" +
"Public sub DoKbTestWithParameter(sMsg As String)\r\n" +
"MsgBox sMsg\r\n" +
"End Sub";
module.CodeModule.AddFromString(macro);
newApp.Run("DoKbTest");
newApp.Quit(ref Unknown, ref Unknown, ref Unknown);
Run Code Online (Sandbox Code Playgroud) 我有下面的结构,正在为 COM 互操作进行编译。我收到以下构建警告:
warning :类型库导出器警告处理“MyNamespace.MyStruct.k__BackingField,MyAssemblyName”。警告:公共结构包含一个或多个将被导出的非公共字段。
但我不明白它指的是什么——根本没有非公共字段或字段。也许编译器正在生成一些我看不到的东西?这个警告是什么意思?如果我能做些什么来清理它怎么办?
这是正在构建的(稍微清理过的)代码:
[Guid("....")]
[ComVisible(true)]
public struct MyStruct
{
public string StringA { get; set; }
public string StringB { get; set; }
public MyStruct(string a, string b)
{
StringA = a;
StringB = b;
}
public MyStruct(MyStruct other)
{
StringA = other.StringA;
StringB = other.StringB;
}
public override bool Equals(object obj)
{
if (!(obj is MyStruct)) return false;
var other = (MyStruct)obj;
return
other.StringA == this.StringA &&
other.StringB == this.StringB;
} …Run Code Online (Sandbox Code Playgroud)